Project

General

Profile

Statistics
| Branch: | Revision:

scoutos / prex-0.9.0 / usr / lib / libc / time / strftime.c @ 03e9c04a

History | View | Annotate | Download (6.44 KB)

1 03e9c04a Brad Neuman
/*
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
}