date and time created 91/02/20 08:15:42 by bostic
[unix-history] / usr / src / lib / libc / string / strftime.c
CommitLineData
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 9static 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
17static char *afmt[] = {
18 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
19};
20static char *Afmt[] = {
21 "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
22 "Saturday",
23};
24static char *bfmt[] = {
25 "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
26 "Oct", "Nov", "Dec",
27};
28static char *Bfmt[] = {
29 "January", "February", "March", "April", "May", "June", "July",
30 "August", "September", "October", "November", "December",
31};
32
33static size_t gsize;
34static char *pt;
35
36size_t
37strftime(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
55static 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
222static
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 239static
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
254static
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}