root / prex-0.9.0 / usr / lib / libc / time / strftime.c @ 03e9c04a
History | View | Annotate | Download (6.44 KB)
1 |
/*
|
---|---|
2 |
* Copyright (c) 1989, 1993
|
3 |
* The Regents of the University of California. All rights reserved.
|
4 |
*
|
5 |
* Redistribution and use in source and binary forms, with or without
|
6 |
* modification, are permitted provided that the following conditions
|
7 |
* are met:
|
8 |
* 1. Redistributions of source code must retain the above copyright
|
9 |
* notice, this list of conditions and the following disclaimer.
|
10 |
* 2. Redistributions in binary form must reproduce the above copyright
|
11 |
* notice, this list of conditions and the following disclaimer in the
|
12 |
* documentation and/or other materials provided with the distribution.
|
13 |
* 3. Neither the name of the University nor the names of its contributors
|
14 |
* may be used to endorse or promote products derived from this software
|
15 |
* without specific prior written permission.
|
16 |
*
|
17 |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
18 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
20 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
21 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
22 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
23 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
24 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
25 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
26 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
27 |
* SUCH DAMAGE.
|
28 |
*/
|
29 |
|
30 |
#include <sys/types.h> |
31 |
#include <sys/time.h> |
32 |
#include <tzfile.h> |
33 |
#include <string.h> |
34 |
|
35 |
static const char *afmt[] = { |
36 |
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", |
37 |
}; |
38 |
static const char *Afmt[] = { |
39 |
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", |
40 |
"Saturday",
|
41 |
}; |
42 |
static const char *bfmt[] = { |
43 |
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", |
44 |
"Oct", "Nov", "Dec", |
45 |
}; |
46 |
static const char *Bfmt[] = { |
47 |
"January", "February", "March", "April", "May", "June", "July", |
48 |
"August", "September", "October", "November", "December", |
49 |
}; |
50 |
|
51 |
static size_t gsize;
|
52 |
static char *pt; |
53 |
static int _add(const char *); |
54 |
static int _conv(int, int, int); |
55 |
static int _secs(const struct tm *); |
56 |
static size_t _fmt(const char *, const struct tm *); |
57 |
|
58 |
size_t |
59 |
strftime(s, maxsize, format, t) |
60 |
char *s;
|
61 |
size_t maxsize; |
62 |
const char *format; |
63 |
const struct tm *t; |
64 |
{ |
65 |
|
66 |
pt = s; |
67 |
if ((gsize = maxsize) < 1) |
68 |
return(0); |
69 |
if (_fmt(format, t)) {
|
70 |
*pt = '\0';
|
71 |
return(maxsize - gsize);
|
72 |
} |
73 |
return(0); |
74 |
} |
75 |
|
76 |
static size_t
|
77 |
_fmt(format, t) |
78 |
const char *format; |
79 |
const struct tm *t; |
80 |
{ |
81 |
for (; *format; ++format) {
|
82 |
if (*format == '%') |
83 |
switch(*++format) {
|
84 |
case '\0': |
85 |
--format; |
86 |
break;
|
87 |
case 'A': |
88 |
if (t->tm_wday < 0 || t->tm_wday > 6) |
89 |
return(0); |
90 |
if (!_add(Afmt[t->tm_wday]))
|
91 |
return(0); |
92 |
continue;
|
93 |
case 'a': |
94 |
if (t->tm_wday < 0 || t->tm_wday > 6) |
95 |
return(0); |
96 |
if (!_add(afmt[t->tm_wday]))
|
97 |
return(0); |
98 |
continue;
|
99 |
case 'B': |
100 |
if (t->tm_mon < 0 || t->tm_mon > 11) |
101 |
return(0); |
102 |
if (!_add(Bfmt[t->tm_mon]))
|
103 |
return(0); |
104 |
continue;
|
105 |
case 'b': |
106 |
case 'h': |
107 |
if (t->tm_mon < 0 || t->tm_mon > 11) |
108 |
return(0); |
109 |
if (!_add(bfmt[t->tm_mon]))
|
110 |
return(0); |
111 |
continue;
|
112 |
case 'C': |
113 |
if (!_fmt("%a %b %e %H:%M:%S %Y", t)) |
114 |
return(0); |
115 |
continue;
|
116 |
case 'c': |
117 |
if (!_fmt("%m/%d/%y %H:%M:%S", t)) |
118 |
return(0); |
119 |
continue;
|
120 |
case 'D': |
121 |
if (!_fmt("%m/%d/%y", t)) |
122 |
return(0); |
123 |
continue;
|
124 |
case 'd': |
125 |
if (!_conv(t->tm_mday, 2, '0')) |
126 |
return(0); |
127 |
continue;
|
128 |
case 'e': |
129 |
if (!_conv(t->tm_mday, 2, ' ')) |
130 |
return(0); |
131 |
continue;
|
132 |
case 'H': |
133 |
if (!_conv(t->tm_hour, 2, '0')) |
134 |
return(0); |
135 |
continue;
|
136 |
case 'I': |
137 |
if (!_conv(t->tm_hour % 12 ? |
138 |
t->tm_hour % 12 : 12, 2, '0')) |
139 |
return(0); |
140 |
continue;
|
141 |
case 'j': |
142 |
if (!_conv(t->tm_yday + 1, 3, '0')) |
143 |
return(0); |
144 |
continue;
|
145 |
case 'k': |
146 |
if (!_conv(t->tm_hour, 2, ' ')) |
147 |
return(0); |
148 |
continue;
|
149 |
case 'l': |
150 |
if (!_conv(t->tm_hour % 12 ? |
151 |
t->tm_hour % 12 : 12, 2, ' ')) |
152 |
return(0); |
153 |
continue;
|
154 |
case 'M': |
155 |
if (!_conv(t->tm_min, 2, '0')) |
156 |
return(0); |
157 |
continue;
|
158 |
case 'm': |
159 |
if (!_conv(t->tm_mon + 1, 2, '0')) |
160 |
return(0); |
161 |
continue;
|
162 |
case 'n': |
163 |
if (!_add("\n")) |
164 |
return(0); |
165 |
continue;
|
166 |
case 'p': |
167 |
if (!_add(t->tm_hour >= 12 ? "PM" : "AM")) |
168 |
return(0); |
169 |
continue;
|
170 |
case 'R': |
171 |
if (!_fmt("%H:%M", t)) |
172 |
return(0); |
173 |
continue;
|
174 |
case 'r': |
175 |
if (!_fmt("%I:%M:%S %p", t)) |
176 |
return(0); |
177 |
continue;
|
178 |
case 'S': |
179 |
if (!_conv(t->tm_sec, 2, '0')) |
180 |
return(0); |
181 |
continue;
|
182 |
case 's': |
183 |
if (!_secs(t))
|
184 |
return(0); |
185 |
continue;
|
186 |
case 'T': |
187 |
case 'X': |
188 |
if (!_fmt("%H:%M:%S", t)) |
189 |
return(0); |
190 |
continue;
|
191 |
case 't': |
192 |
if (!_add("\t")) |
193 |
return(0); |
194 |
continue;
|
195 |
case 'U': |
196 |
if (!_conv((t->tm_yday + 7 - t->tm_wday) / 7, |
197 |
2, '0')) |
198 |
return(0); |
199 |
continue;
|
200 |
case 'W': |
201 |
if (!_conv((t->tm_yday + 7 - |
202 |
(t->tm_wday ? (t->tm_wday - 1) : 6)) |
203 |
/ 7, 2, '0')) |
204 |
return(0); |
205 |
continue;
|
206 |
case 'w': |
207 |
if (!_conv(t->tm_wday, 1, '0')) |
208 |
return(0); |
209 |
continue;
|
210 |
case 'x': |
211 |
if (!_fmt("%m/%d/%y", t)) |
212 |
return(0); |
213 |
continue;
|
214 |
case 'y': |
215 |
if (!_conv((t->tm_year + TM_YEAR_BASE)
|
216 |
% 100, 2, '0')) |
217 |
return(0); |
218 |
continue;
|
219 |
case 'Y': |
220 |
if (!_conv(t->tm_year + TM_YEAR_BASE, 4, '0')) |
221 |
return(0); |
222 |
continue;
|
223 |
/*
|
224 |
case 'Z':
|
225 |
if (!t->tm_zone || !_add(t->tm_zone))
|
226 |
return(0);
|
227 |
continue;
|
228 |
*/
|
229 |
case '%': |
230 |
/*
|
231 |
* X311J/88-090 (4.12.3.5): if conversion char is
|
232 |
* undefined, behavior is undefined. Print out the
|
233 |
* character itself as printf(3) does.
|
234 |
*/
|
235 |
default:
|
236 |
break;
|
237 |
} |
238 |
if (!gsize--)
|
239 |
return(0); |
240 |
*pt++ = *format; |
241 |
} |
242 |
return(gsize);
|
243 |
} |
244 |
|
245 |
static int |
246 |
_secs(t) |
247 |
const struct tm *t; |
248 |
{ |
249 |
static char buf[15]; |
250 |
time_t s; |
251 |
char *p;
|
252 |
struct tm tmp;
|
253 |
|
254 |
/* Make a copy, mktime(3) modifies the tm struct. */
|
255 |
tmp = *t; |
256 |
s = mktime(&tmp); |
257 |
for (p = buf + sizeof(buf) - 2; s > 0 && p > buf; s /= 10) |
258 |
*p-- = s % 10 + '0'; |
259 |
return(_add(++p));
|
260 |
} |
261 |
|
262 |
static int |
263 |
_conv(n, digits, pad) |
264 |
int n, digits, pad;
|
265 |
{ |
266 |
static char buf[10]; |
267 |
char *p;
|
268 |
|
269 |
for (p = buf + sizeof(buf) - 2; n > 0 && p > buf; n /= 10, --digits) |
270 |
*p-- = n % 10 + '0'; |
271 |
while (p > buf && digits-- > 0) |
272 |
*p-- = pad; |
273 |
return(_add(++p));
|
274 |
} |
275 |
|
276 |
static int |
277 |
_add(str) |
278 |
const char *str; |
279 |
{ |
280 |
for (;; ++pt, --gsize) {
|
281 |
if (!gsize)
|
282 |
return(0); |
283 |
if (!(*pt = *str++))
|
284 |
return(1); |
285 |
} |
286 |
} |