70322ae3 |
1 | /* |
2 | * malloc.c: implementation of malloc.h |
3 | */ |
4 | |
5 | #include <stdlib.h> |
6 | #include <string.h> |
7 | #include <stdarg.h> |
8 | #include <time.h> |
9 | #include <assert.h> |
10 | #include <stdio.h> |
11 | |
12 | #include "malloc.h" |
13 | |
14 | #define lenof(x) (sizeof((x))/sizeof(*(x))) |
15 | |
16 | extern void fatal(const char *, ...); |
17 | |
18 | void *smalloc(size_t size) { |
19 | void *p; |
20 | p = malloc(size); |
21 | if (!p) { |
22 | fatal("out of memory"); |
23 | } |
24 | return p; |
25 | } |
26 | |
27 | void sfree(void *p) { |
28 | if (p) { |
29 | free(p); |
30 | } |
31 | } |
32 | |
33 | void *srealloc(void *p, size_t size) { |
34 | void *q; |
35 | if (p) { |
36 | q = realloc(p, size); |
37 | } else { |
38 | q = malloc(size); |
39 | } |
40 | if (!q) |
41 | fatal("out of memory"); |
42 | return q; |
43 | } |
44 | |
45 | char *dupstr(const char *s) { |
46 | char *r = smalloc(1+strlen(s)); |
47 | strcpy(r,s); |
48 | return r; |
49 | } |
50 | |
51 | char *dupfmt(const char *fmt, ...) |
52 | { |
53 | int pass; |
54 | int totallen; |
55 | char *ret = NULL, *rp = NULL; |
56 | char datebuf[80]; |
57 | va_list ap; |
58 | time_t t; |
59 | struct tm tm; |
60 | int got_time = 0; |
61 | |
62 | datebuf[0] = '\0'; |
63 | totallen = 0; |
64 | |
65 | for (pass = 0; pass < 2; pass++) { |
66 | const char *p = fmt; |
67 | |
68 | va_start(ap, fmt); |
69 | |
70 | while (*p) { |
71 | const char *data = NULL; |
72 | int datalen = 0, stuffcr = 0; |
73 | |
74 | if (*p == '%') { |
75 | p++; |
76 | if (*p == 'D') { |
77 | if (!datebuf[0]) { |
78 | if (!got_time) { |
79 | t = time(NULL); |
80 | tm = *gmtime(&t); |
81 | got_time = 1; |
82 | } |
83 | strftime(datebuf, lenof(datebuf), |
84 | "%a, %d %b %Y %H:%M:%S GMT", &tm); |
85 | } |
86 | data = datebuf; |
87 | datalen = strlen(data); |
88 | } else if (*p == 'd') { |
89 | int i = va_arg(ap, int); |
90 | sprintf(datebuf, "%d", i); |
91 | data = datebuf; |
92 | datalen = strlen(data); |
93 | } else if (*p == 's') { |
94 | data = va_arg(ap, const char *); |
95 | datalen = strlen(data); |
96 | } else if (assert(*p == 'S'), 1) { |
97 | stuffcr = va_arg(ap, int); |
98 | data = va_arg(ap, const char *); |
99 | datalen = strlen(data); |
100 | } |
101 | p++; |
102 | } else { |
103 | data = p; |
104 | while (*p && *p != '%') p++; |
105 | datalen = p - data; |
106 | } |
107 | |
108 | if (pass == 0) { |
109 | totallen += datalen; |
110 | if (stuffcr) { |
111 | while (datalen > 0) { |
112 | if (*data == '\n') |
113 | totallen++; |
114 | data++, datalen--; |
115 | } |
116 | } |
117 | } else { |
118 | while (datalen > 0) { |
119 | if (stuffcr && *data == '\n') |
120 | *rp++ = '\r'; |
121 | *rp++ = *data++; |
122 | datalen--; |
123 | } |
124 | } |
125 | } |
126 | |
127 | va_end(ap); |
128 | |
129 | if (pass == 0) { |
130 | rp = ret = snewn(totallen+1, char); |
131 | } else { |
132 | assert(rp - ret == totallen); |
133 | *rp = '\0'; |
134 | } |
135 | } |
136 | |
137 | return ret; |
138 | } |