Pristine Ack-5.5
[Ack-5.5.git] / lang / cem / libcc.ansi / time / strftime.c
1 /*
2  * strftime - convert a structure to a string, controlled by an argument
3  */
4 /* $Id: strftime.c,v 1.4 1994/06/24 11:58:24 ceriel Exp $ */
5
6 #include        <time.h>
7 #include        "loc_time.h"
8
9 /* The width can be -1 in both s_prnt() as in u_prnt(). This
10  * indicates that as many characters as needed should be printed.
11  */
12 static char *
13 s_prnt(char *s, size_t maxsize, const char *str, int width)
14 {
15         while (width > 0 || (width < 0 && *str)) {
16                 if (!maxsize) break;
17                 *s++ = *str++;
18                 maxsize--;
19                 width--;
20         }
21         return s;
22 }
23
24 static char *
25 u_prnt(char *s, size_t maxsize, unsigned val, int width)
26 {
27         int c;
28
29         c = val % 10;
30         val = val / 10;
31         if (--width > 0 || (width < 0 && val != 0))
32                 s = u_prnt(s, (maxsize ? maxsize - 1 : 0), val, width);
33         if (maxsize) *s++ = c + '0';
34         return s;
35 }
36
37 size_t
38 strftime(char *s, size_t maxsize,
39                 const char *format, const struct tm *timeptr)
40 {
41         size_t n;
42         char *firsts, *olds;
43
44         if (!format) return 0;
45
46         _tzset();       /* for %Z conversion */
47         firsts = s;
48         while (maxsize && *format) {
49                 while (maxsize && *format && *format != '%') {
50                         *s++ = *format++;
51                         maxsize--;
52                 }
53                 if (!maxsize || !*format) break;
54                 format++;
55
56                 olds = s;
57                 switch (*format++) {
58                 case 'a':
59                         s = s_prnt(s, maxsize,
60                                         _days[timeptr->tm_wday], ABB_LEN);
61                         maxsize -= s - olds;
62                         break;
63                 case 'A':
64                         s = s_prnt(s, maxsize, _days[timeptr->tm_wday], -1);
65                         maxsize -= s - olds;
66                         break;
67                 case 'b':
68                         s = s_prnt(s, maxsize,
69                                         _months[timeptr->tm_mon], ABB_LEN);
70                         maxsize -= s - olds;
71                         break;
72                 case 'B':
73                         s = s_prnt(s, maxsize, _months[timeptr->tm_mon], -1);
74                         maxsize -= s - olds;
75                         break;
76                 case 'c':
77                         n = strftime(s, maxsize,
78                                         "%a %b %d %H:%M:%S %Y", timeptr);
79                         if (n) maxsize -= n;
80                         else maxsize = 0;
81                         s += n;
82                         break;
83                 case 'd':
84                         s = u_prnt(s, maxsize, timeptr->tm_mday, 2);
85                         maxsize -= s - olds;
86                         break;
87                 case 'H':
88                         s = u_prnt(s, maxsize, timeptr->tm_hour, 2);
89                         maxsize -= s - olds;
90                         break;
91                 case 'I':
92                         s = u_prnt(s, maxsize,
93                                         (timeptr->tm_hour + 11) % 12 + 1, 2);
94                         maxsize -= s - olds;
95                         break;
96                 case 'j':
97                         s = u_prnt(s, maxsize, timeptr->tm_yday + 1, 3);
98                         maxsize -= s - olds;
99                         break;
100                 case 'm':
101                         s = u_prnt(s, maxsize, timeptr->tm_mon + 1, 2);
102                         maxsize -= s - olds;
103                         break;
104                 case 'M':
105                         s = u_prnt(s, maxsize, timeptr->tm_min, 2);
106                         maxsize -= s - olds;
107                         break;
108                 case 'p':
109                         s = s_prnt(s, maxsize,
110                                     (timeptr->tm_hour < 12) ? "AM" : "PM", 2);
111                         maxsize -= s - olds;
112                         break;
113                 case 'S':
114                         s = u_prnt(s, maxsize, timeptr->tm_sec, 2);
115                         maxsize -= s - olds;
116                         break;
117                 case 'U':
118                         s = u_prnt(s, maxsize,          /* ??? */
119                             (timeptr->tm_yday + 7 - timeptr->tm_wday) / 7, 2);
120                         maxsize -= s - olds;
121                         break;
122                 case 'w':
123                         s = u_prnt(s, maxsize, timeptr->tm_wday, 1);
124                         maxsize -= s - olds;
125                         break;
126                 case 'W':
127                         s = u_prnt(s, maxsize,          /* ??? */
128                             (timeptr->tm_yday+7-(timeptr->tm_wday+6)%7)/7,2);
129                         maxsize -= s - olds;
130                         break;
131                 case 'x':
132                         n = strftime(s, maxsize, "%a %b %d %Y", timeptr);
133                         if (n) maxsize -= n;
134                         else maxsize = 0;
135                         s += n;
136                         break;
137                 case 'X':
138                         n = strftime(s, maxsize, "%H:%M:%S", timeptr);
139                         if (n) maxsize -= n;
140                         else maxsize = 0;
141                         s += n;
142                         break;
143                 case 'y':
144                         s = u_prnt(s, maxsize, timeptr->tm_year % 100, 2);
145                         maxsize -= s - olds;
146                         break;
147                 case 'Y':
148                         s = u_prnt(s, maxsize, timeptr->tm_year + YEAR0, -1);
149                         maxsize -= s - olds;
150                         break;
151                 case 'Z':
152                         s = s_prnt(s, maxsize,
153                                         _tzname[(timeptr->tm_isdst > 0)], -1);
154                         maxsize -= s - olds;
155                         break;
156                 case '%':
157                         *s++ = '%';
158                         maxsize--;
159                         break;
160                 default:
161                         /* A conversion error. Leave the loop. */
162                         while (*format) format++;
163                         break;
164                 }
165
166         }
167         if (maxsize) {
168                 *s = '\0';
169                 return s - firsts;
170         }
171         return 0;       /* The buffer is full */
172 }