Commit | Line | Data |
---|---|---|
e9fe19df KB |
1 | /* |
2 | * Copyright (c) 1989 The Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
019bea33 | 5 | * %sccs.include.redist.c% |
e9fe19df KB |
6 | */ |
7 | ||
8 | #if defined(LIBC_SCCS) && !defined(lint) | |
ecd4c37c | 9 | static char sccsid[] = "@(#)strftime.c 5.10 (Berkeley) %G%"; |
e9fe19df KB |
10 | #endif /* LIBC_SCCS and not lint */ |
11 | ||
12 | #include <sys/types.h> | |
13 | #include <sys/time.h> | |
14 | #include <tzfile.h> | |
336401ac | 15 | #include <string.h> |
e9fe19df KB |
16 | |
17 | static char *afmt[] = { | |
18 | "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", | |
19 | }; | |
20 | static char *Afmt[] = { | |
21 | "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", | |
22 | "Saturday", | |
23 | }; | |
24 | static char *bfmt[] = { | |
25 | "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", | |
26 | "Oct", "Nov", "Dec", | |
27 | }; | |
28 | static char *Bfmt[] = { | |
29 | "January", "February", "March", "April", "May", "June", "July", | |
30 | "August", "September", "October", "November", "December", | |
31 | }; | |
32 | ||
33 | static size_t gsize; | |
34 | static char *pt; | |
35 | ||
36 | size_t | |
37 | strftime(s, maxsize, format, t) | |
38 | char *s; | |
39 | char *format; | |
40 | size_t maxsize; | |
41 | struct tm *t; | |
42 | { | |
43 | size_t _fmt(); | |
44 | ||
45 | pt = s; | |
46 | if ((gsize = maxsize) < 1) | |
47 | return(0); | |
48 | if (_fmt(format, t)) { | |
49 | *pt = '\0'; | |
50 | return(maxsize - gsize); | |
51 | } | |
52 | return(0); | |
53 | } | |
54 | ||
55 | static size_t | |
56 | _fmt(format, t) | |
57 | register char *format; | |
58 | struct tm *t; | |
59 | { | |
e9fe19df KB |
60 | for (; *format; ++format) { |
61 | if (*format == '%') | |
62 | switch(*++format) { | |
e2abfca3 KB |
63 | case '\0': |
64 | --format; | |
65 | break; | |
e9fe19df | 66 | case 'A': |
e2abfca3 KB |
67 | if (t->tm_wday < 0 || t->tm_wday > 6) |
68 | return(0); | |
69 | if (!_add(Afmt[t->tm_wday])) | |
e9fe19df KB |
70 | return(0); |
71 | continue; | |
72 | case 'a': | |
e2abfca3 KB |
73 | if (t->tm_wday < 0 || t->tm_wday > 6) |
74 | return(0); | |
75 | if (!_add(afmt[t->tm_wday])) | |
e9fe19df KB |
76 | return(0); |
77 | continue; | |
78 | case 'B': | |
e2abfca3 KB |
79 | if (t->tm_mon < 0 || t->tm_mon > 11) |
80 | return(0); | |
e9fe19df KB |
81 | if (!_add(Bfmt[t->tm_mon])) |
82 | return(0); | |
83 | continue; | |
84 | case 'b': | |
e386ba1e | 85 | case 'h': |
e2abfca3 KB |
86 | if (t->tm_mon < 0 || t->tm_mon > 11) |
87 | return(0); | |
e9fe19df KB |
88 | if (!_add(bfmt[t->tm_mon])) |
89 | return(0); | |
90 | continue; | |
14fd63d8 KB |
91 | case 'C': |
92 | if (!_fmt("%a %b %e %H:%M:%S %Y", t)) | |
93 | return(0); | |
94 | continue; | |
e9fe19df | 95 | case 'c': |
5a2e4b32 | 96 | if (!_fmt("%m/%d/%y %H:%M:%S", t)) |
e9fe19df KB |
97 | return(0); |
98 | continue; | |
e386ba1e KB |
99 | case 'D': |
100 | if (!_fmt("%m/%d/%y", t)) | |
101 | return(0); | |
102 | continue; | |
e9fe19df | 103 | case 'd': |
14fd63d8 | 104 | if (!_conv(t->tm_mday, 2, '0')) |
e9fe19df KB |
105 | return(0); |
106 | continue; | |
e0b27de7 KB |
107 | case 'e': |
108 | if (!_conv(t->tm_mday, 2, ' ')) | |
109 | return(0); | |
110 | continue; | |
e9fe19df | 111 | case 'H': |
14fd63d8 | 112 | if (!_conv(t->tm_hour, 2, '0')) |
e9fe19df KB |
113 | return(0); |
114 | continue; | |
115 | case 'I': | |
e2abfca3 | 116 | if (!_conv(t->tm_hour % 12 ? |
14fd63d8 | 117 | t->tm_hour % 12 : 12, 2, '0')) |
e9fe19df KB |
118 | return(0); |
119 | continue; | |
120 | case 'j': | |
14fd63d8 KB |
121 | if (!_conv(t->tm_yday + 1, 3, '0')) |
122 | return(0); | |
123 | continue; | |
124 | case 'k': | |
125 | if (!_conv(t->tm_hour, 2, ' ')) | |
126 | return(0); | |
127 | continue; | |
128 | case 'l': | |
129 | if (!_conv(t->tm_hour % 12 ? | |
130 | t->tm_hour % 12 : 12, 2, ' ')) | |
e9fe19df KB |
131 | return(0); |
132 | continue; | |
133 | case 'M': | |
14fd63d8 | 134 | if (!_conv(t->tm_min, 2, '0')) |
e9fe19df KB |
135 | return(0); |
136 | continue; | |
137 | case 'm': | |
14fd63d8 | 138 | if (!_conv(t->tm_mon + 1, 2, '0')) |
e9fe19df KB |
139 | return(0); |
140 | continue; | |
e386ba1e KB |
141 | case 'n': |
142 | if (!_add("\n")) | |
143 | return(0); | |
144 | continue; | |
e9fe19df | 145 | case 'p': |
e2abfca3 | 146 | if (!_add(t->tm_hour >= 12 ? "PM" : "AM")) |
e9fe19df KB |
147 | return(0); |
148 | continue; | |
e386ba1e KB |
149 | case 'R': |
150 | if (!_fmt("%H:%M", t)) | |
151 | return(0); | |
152 | continue; | |
153 | case 'r': | |
154 | if (!_fmt("%I:%M:%S %p", t)) | |
155 | return(0); | |
156 | continue; | |
e9fe19df | 157 | case 'S': |
14fd63d8 | 158 | if (!_conv(t->tm_sec, 2, '0')) |
e9fe19df KB |
159 | return(0); |
160 | continue; | |
e0b27de7 KB |
161 | case 's': |
162 | if (!_secs(t)) | |
163 | return(0); | |
164 | continue; | |
e386ba1e KB |
165 | case 'T': |
166 | case 'X': | |
167 | if (!_fmt("%H:%M:%S", t)) | |
168 | return(0); | |
169 | continue; | |
170 | case 't': | |
171 | if (!_add("\t")) | |
172 | return(0); | |
173 | continue; | |
e9fe19df KB |
174 | case 'U': |
175 | if (!_conv((t->tm_yday + 7 - t->tm_wday) / 7, | |
14fd63d8 | 176 | 2, '0')) |
e9fe19df KB |
177 | return(0); |
178 | continue; | |
179 | case 'W': | |
180 | if (!_conv((t->tm_yday + 7 - | |
e2abfca3 | 181 | (t->tm_wday ? (t->tm_wday - 1) : 6)) |
14fd63d8 | 182 | / 7, 2, '0')) |
e9fe19df KB |
183 | return(0); |
184 | continue; | |
185 | case 'w': | |
14fd63d8 | 186 | if (!_conv(t->tm_wday, 1, '0')) |
e9fe19df | 187 | return(0); |
e9fe19df KB |
188 | continue; |
189 | case 'x': | |
5a2e4b32 | 190 | if (!_fmt("%m/%d/%y", t)) |
e9fe19df KB |
191 | return(0); |
192 | continue; | |
193 | case 'y': | |
194 | if (!_conv((t->tm_year + TM_YEAR_BASE) | |
14fd63d8 | 195 | % 100, 2, '0')) |
e9fe19df KB |
196 | return(0); |
197 | continue; | |
198 | case 'Y': | |
14fd63d8 | 199 | if (!_conv(t->tm_year + TM_YEAR_BASE, 4, '0')) |
e9fe19df KB |
200 | return(0); |
201 | continue; | |
202 | case 'Z': | |
e2abfca3 | 203 | if (!t->tm_zone || !_add(t->tm_zone)) |
e9fe19df KB |
204 | return(0); |
205 | continue; | |
206 | case '%': | |
207 | /* | |
208 | * X311J/88-090 (4.12.3.5): if conversion char is | |
209 | * undefined, behavior is undefined. Print out the | |
14fd63d8 | 210 | * character itself as printf(3) does. |
e9fe19df KB |
211 | */ |
212 | default: | |
213 | break; | |
214 | } | |
215 | if (!gsize--) | |
216 | return(0); | |
217 | *pt++ = *format; | |
218 | } | |
219 | return(gsize); | |
220 | } | |
221 | ||
e0b27de7 KB |
222 | static |
223 | _secs(t) | |
224 | struct tm *t; | |
225 | { | |
226 | static char buf[15]; | |
227 | register time_t s; | |
228 | register char *p; | |
ecd4c37c | 229 | struct tm tmp; |
e0b27de7 | 230 | |
ecd4c37c KB |
231 | /* Make a copy, mktime(3) modifies the tm struct. */ |
232 | tmp = *t; | |
233 | s = mktime(&tmp); | |
e0b27de7 KB |
234 | for (p = buf + sizeof(buf) - 2; s > 0 && p > buf; s /= 10) |
235 | *p-- = s % 10 + '0'; | |
236 | return(_add(++p)); | |
237 | } | |
238 | ||
e9fe19df | 239 | static |
14fd63d8 | 240 | _conv(n, digits, pad) |
e9fe19df | 241 | int n, digits; |
14fd63d8 | 242 | char pad; |
e9fe19df KB |
243 | { |
244 | static char buf[10]; | |
245 | register char *p; | |
246 | ||
247 | for (p = buf + sizeof(buf) - 2; n > 0 && p > buf; n /= 10, --digits) | |
248 | *p-- = n % 10 + '0'; | |
249 | while (p > buf && digits-- > 0) | |
14fd63d8 | 250 | *p-- = pad; |
e9fe19df KB |
251 | return(_add(++p)); |
252 | } | |
253 | ||
254 | static | |
255 | _add(str) | |
256 | register char *str; | |
257 | { | |
258 | for (;; ++pt, --gsize) { | |
259 | if (!gsize) | |
260 | return(0); | |
261 | if (!(*pt = *str++)) | |
262 | return(1); | |
263 | } | |
264 | } |