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) | |
019bea33 | 9 | static char sccsid[] = "@(#)strftime.c 5.8 (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; | |
14fd63d8 KB |
99 | case 'e': |
100 | if (!_conv(t->tm_mday, 2, ' ')) | |
101 | return(0); | |
102 | continue; | |
e386ba1e KB |
103 | case 'D': |
104 | if (!_fmt("%m/%d/%y", t)) | |
105 | return(0); | |
106 | continue; | |
e9fe19df | 107 | case 'd': |
14fd63d8 | 108 | if (!_conv(t->tm_mday, 2, '0')) |
e9fe19df KB |
109 | return(0); |
110 | continue; | |
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; | |
e386ba1e KB |
161 | case 'T': |
162 | case 'X': | |
163 | if (!_fmt("%H:%M:%S", t)) | |
164 | return(0); | |
165 | continue; | |
166 | case 't': | |
167 | if (!_add("\t")) | |
168 | return(0); | |
169 | continue; | |
e9fe19df KB |
170 | case 'U': |
171 | if (!_conv((t->tm_yday + 7 - t->tm_wday) / 7, | |
14fd63d8 | 172 | 2, '0')) |
e9fe19df KB |
173 | return(0); |
174 | continue; | |
175 | case 'W': | |
176 | if (!_conv((t->tm_yday + 7 - | |
e2abfca3 | 177 | (t->tm_wday ? (t->tm_wday - 1) : 6)) |
14fd63d8 | 178 | / 7, 2, '0')) |
e9fe19df KB |
179 | return(0); |
180 | continue; | |
181 | case 'w': | |
14fd63d8 | 182 | if (!_conv(t->tm_wday, 1, '0')) |
e9fe19df | 183 | return(0); |
e9fe19df KB |
184 | continue; |
185 | case 'x': | |
5a2e4b32 | 186 | if (!_fmt("%m/%d/%y", t)) |
e9fe19df KB |
187 | return(0); |
188 | continue; | |
189 | case 'y': | |
190 | if (!_conv((t->tm_year + TM_YEAR_BASE) | |
14fd63d8 | 191 | % 100, 2, '0')) |
e9fe19df KB |
192 | return(0); |
193 | continue; | |
194 | case 'Y': | |
14fd63d8 | 195 | if (!_conv(t->tm_year + TM_YEAR_BASE, 4, '0')) |
e9fe19df KB |
196 | return(0); |
197 | continue; | |
198 | case 'Z': | |
e2abfca3 | 199 | if (!t->tm_zone || !_add(t->tm_zone)) |
e9fe19df KB |
200 | return(0); |
201 | continue; | |
202 | case '%': | |
203 | /* | |
204 | * X311J/88-090 (4.12.3.5): if conversion char is | |
205 | * undefined, behavior is undefined. Print out the | |
14fd63d8 | 206 | * character itself as printf(3) does. |
e9fe19df KB |
207 | */ |
208 | default: | |
209 | break; | |
210 | } | |
211 | if (!gsize--) | |
212 | return(0); | |
213 | *pt++ = *format; | |
214 | } | |
215 | return(gsize); | |
216 | } | |
217 | ||
218 | static | |
14fd63d8 | 219 | _conv(n, digits, pad) |
e9fe19df | 220 | int n, digits; |
14fd63d8 | 221 | char pad; |
e9fe19df KB |
222 | { |
223 | static char buf[10]; | |
224 | register char *p; | |
225 | ||
226 | for (p = buf + sizeof(buf) - 2; n > 0 && p > buf; n /= 10, --digits) | |
227 | *p-- = n % 10 + '0'; | |
228 | while (p > buf && digits-- > 0) | |
14fd63d8 | 229 | *p-- = pad; |
e9fe19df KB |
230 | return(_add(++p)); |
231 | } | |
232 | ||
233 | static | |
234 | _add(str) | |
235 | register char *str; | |
236 | { | |
237 | for (;; ++pt, --gsize) { | |
238 | if (!gsize) | |
239 | return(0); | |
240 | if (!(*pt = *str++)) | |
241 | return(1); | |
242 | } | |
243 | } |