]> cloudbase.mooo.com Git - z180-stamp.git/blame - time/strftime.c
cli.c bugfix: Comment only lines are not an error.
[z180-stamp.git] / time / strftime.c
CommitLineData
e63b2f75
L
1/*
2 * (c)2012 Michael Duane Rice All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer. Redistributions in binary
10 * form must reproduce the above copyright notice, this list of conditions
11 * and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution. Neither the name of the copyright holders
13 * nor the names of contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/* $Id: strftime.c 2391 2013-05-03 20:53:06Z swfltek $ */
30
31/*
32 Standard strftime(). This is a memory hungry monster.
33*/
34
35#include <stdlib.h>
36#include <stdio.h>
37#include <time.h>
38
39extern long __utc_offset;
40
41#ifdef __MEMX
42
43const __memx char strfwkdays[] = "Sunday Monday Tuesday Wednesday Thursday Friday Saturday ";
44const __memx char strfmonths[] = "January February March April May June July August September October November December ";
45
46#else
47
48const char strfwkdays[] = "Sunday Monday Tuesday Wednesday Thursday Friday Saturday ";
49const char strfmonths[] = "January February March April May June July August September October November December ";
50
51#endif
52
53#ifdef __MEMX
54
55unsigned char
56pgm_copystring(const char __memx * p, unsigned char i, char *b, unsigned char l)
57{
58
59#else
60
61unsigned char
62pgm_copystring(const char *p, unsigned char i, char *b, unsigned char l)
63{
64
65#endif
66
67 unsigned char ret, c;
68
69 ret = 0;
70 while (i) {
71 c = *p++;
72 if (c == ' ')
73 i--;
74 }
75
76 c = *p++;
77 while (c != ' ' && l--) {
78 *b++ = c;
79 ret++;
80 c = *p++;
81 }
82 *b = 0;
83 return ret;
84}
85
86size_t
87strftime(char *buffer, size_t limit, const char *pattern, const struct tm * timeptr)
88{
89 unsigned int count, length;
90 int d, w;
91 char c;
92 char _store[26];
93 struct week_date wd;
94
95 count = length = 0;
96 while (count < limit) {
97 c = *pattern++;
98 if (c == '%') {
99 c = *pattern++;
100 if (c == 'E' || c == 'O')
101 c = *pattern++;
102 switch (c) {
103 case ('%'):
104 _store[0] = c;
105 length = 1;
106 break;
107
108 case ('a'):
109 length = pgm_copystring(strfwkdays, timeptr->tm_wday, _store, 3);
110 break;
111
112 case ('A'):
113 length = pgm_copystring(strfwkdays, timeptr->tm_wday, _store, 255);
114 break;
115
116 case ('b'):
117 case ('h'):
118 length = pgm_copystring(strfmonths, timeptr->tm_mon, _store, 3);
119 break;
120
121 case ('B'):
122 length = pgm_copystring(strfmonths, timeptr->tm_mon, _store, 255);
123 break;
124
125 case ('c'):
126 asctime_r(timeptr, _store);
127 length = 0;
128 while (_store[length])
129 length++;
130 break;
131
132 case ('C'):
133 d = timeptr->tm_year + 1900;
134 d /= 100;
135 length = sprintf(_store, "%.2d", d);
136 break;
137
138 case ('d'):
139 length = sprintf(_store, "%.2u", timeptr->tm_mday);
140 break;
141
142 case ('D'):
143 length = sprintf(_store, "%.2u/%.2u/%.2u", \
144 timeptr->tm_mon + 1, \
145 timeptr->tm_mday, \
146 timeptr->tm_year % 100 \
147 );
148 break;
149
150 case ('e'):
151 length = sprintf(_store, "%2d", timeptr->tm_mday);
152 break;
153
154 case ('F'):
155 length = sprintf(_store, "%d-%.2d-%.2d", \
156 timeptr->tm_year + 1900, \
157 timeptr->tm_mon + 1, \
158 timeptr->tm_mday \
159 );
160 break;
161
162 case ('g'):
163 case ('G'):
164 iso_week_date_r(timeptr->tm_year + 1900, timeptr->tm_yday, &wd);
165 if (c == 'g') {
166 length = sprintf(_store, "%.2d", wd.year % 100);
167 } else {
168 length = sprintf(_store, "%.4d", wd.year);
169 }
170
171 break;
172
173 case ('H'):
174 length = sprintf(_store, "%.2u", timeptr->tm_hour);
175 break;
176
177 case ('I'):
178 d = timeptr->tm_hour % 12;
179 if (d == 0)
180 d = 12;
181 length = sprintf(_store, "%.2u", d);
182 break;
183
184 case ('j'):
185 length = sprintf(_store, "%.3u", timeptr->tm_yday + 1);
186 break;
187
188 case ('m'):
189 length = sprintf(_store, "%.2u", timeptr->tm_mon + 1);
190 break;
191
192 case ('M'):
193 length = sprintf(_store, "%.2u", timeptr->tm_min);
194 break;
195
196 case ('n'):
197 _store[0] = 10;
198 length = 1;
199 break;
200
201 case ('p'):
202 length = 2;
203 _store[0] = 'A';
204 if (timeptr->tm_hour > 11)
205 _store[0] = 'P';
206 _store[1] = 'M';
207 _store[2] = 0;
208 break;
209
210 case ('r'):
211 d = timeptr->tm_hour % 12;
212 if (d == 0)
213 d = 12;
214 length = sprintf(_store, "%2d:%.2d:%.2d AM", \
215 d, \
216 timeptr->tm_min, \
217 timeptr->tm_sec \
218 );
219 if (timeptr->tm_hour > 11)
220 _store[10] = 'P';
221 break;
222
223 case ('R'):
224 length = sprintf(_store, "%.2d:%.2d", timeptr->tm_hour, timeptr->tm_min);
225 break;
226
227 case ('S'):
228 length = sprintf(_store, "%.2u", timeptr->tm_sec);
229 break;
230
231 case ('t'):
232 length = sprintf(_store, "\t");
233 break;
234
235 case ('T'):
236 length = sprintf(_store, "%.2d:%.2d:%.2d", \
237 timeptr->tm_hour, \
238 timeptr->tm_min, \
239 timeptr->tm_sec \
240 );
241 break;
242
243 case ('u'):
244 w = timeptr->tm_wday;
245 if (w == 0)
246 w = 7;
247 length = sprintf(_store, "%d", w);
248 break;
249
250 case ('U'):
251 length = sprintf(_store, "%.2u", week_of_year(timeptr, 0));
252 break;
253
254 case ('V'):
255 iso_week_date_r(timeptr->tm_year + 1900, timeptr->tm_yday, &wd);
256 length = sprintf(_store, "%.2u", wd.week);
257 break;
258
259 case ('w'):
260 length = sprintf(_store, "%u", timeptr->tm_wday);
261 break;
262
263 case ('W'):
264 w = week_of_year(timeptr, 1);
265 length = sprintf(_store, "%.2u", w);
266 break;
267
268 case ('x'):
269 length = sprintf(_store, "%.2u/%.2u/%.2u", timeptr->tm_mon + 1, timeptr->tm_mday, timeptr->tm_year % 100);
270 break;
271
272 case ('X'):
273 length = sprintf(_store, "%.2u:%.2u:%.2u", timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec);
274 break;
275
276 case ('y'):
277 length = sprintf(_store, "%.2u", timeptr->tm_year % 100);
278 break;
279
280 case ('Y'):
281 length = sprintf(_store, "%u", timeptr->tm_year + 1900);
282 break;
283
284 case ('z'):
285 d = __utc_offset / 60;
286 w = timeptr->tm_isdst / 60;
287 if (w > 0)
288 d += w;
289 w = abs(d % 60);
290 d = d / 60;
291 length = sprintf(_store, "%+.2d%.2d", d, w);
292 break;
293
294 default:
295 length = 1;
296 _store[0] = '?';
297 _store[1] = 0;
298 break;
299 }
300
301 if ((length + count) < limit) {
302 count += length;
303 for (d = 0; d < (int) length; d++) {
304 *buffer++ = _store[d];
305 }
306 } else {
307 *buffer = 0;
308 return count;
309 }
310
311 } else { /* copy a literal */
312 *buffer = c;
313 buffer++;
314 count++;
315 if (c == 0)
316 return count;
317 }
318 }
319
320 *buffer = 0;
321 return count;
322}