]> git.sur5r.net Git - cc65/blob - libsrc/common/strftime.c
Fix 32/64-bit int/pointer casts
[cc65] / libsrc / common / strftime.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                strftime.c                                 */
4 /*                                                                           */
5 /*      Convert broken down time to a string in a user specified format      */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2002      Ullrich von Bassewitz                                       */
10 /*               Wacholderweg 14                                             */
11 /*               D-70597 Stuttgart                                           */
12 /* EMail:        uz@musoftware.de                                            */
13 /*                                                                           */
14 /*                                                                           */
15 /* This software is provided 'as-is', without any expressed or implied       */
16 /* warranty.  In no event will the authors be held liable for any damages    */
17 /* arising from the use of this software.                                    */
18 /*                                                                           */
19 /* Permission is granted to anyone to use this software for any purpose,     */
20 /* including commercial applications, and to alter it and redistribute it    */
21 /* freely, subject to the following restrictions:                            */
22 /*                                                                           */
23 /* 1. The origin of this software must not be misrepresented; you must not   */
24 /*    claim that you wrote the original software. If you use this software   */
25 /*    in a product, an acknowledgment in the product documentation would be  */
26 /*    appreciated but is not required.                                       */
27 /* 2. Altered source versions must be plainly marked as such, and must not   */
28 /*    be misrepresented as being the original software.                      */
29 /* 3. This notice may not be removed or altered from any source              */
30 /*    distribution.                                                          */
31 /*                                                                           */
32 /*****************************************************************************/
33
34
35
36 #include <string.h>
37 #include <stdio.h>
38 #include <time.h>
39
40
41
42 /* Use static local variables for speed */
43 #pragma static-locals (on);
44
45
46
47 /*****************************************************************************/
48 /*                                   Code                                    */
49 /*****************************************************************************/
50
51
52
53 size_t __fastcall__ strftime (char* buf, size_t bufsize, const char* format,
54                               const struct tm* tm)
55 {
56     static const char* const days[7] = {
57         "Sunday",   "Monday", "Tuesday", "Wednesday",
58         "Thursday", "Friday", "Saturday"
59     };
60     static const char* const months[12] = {
61         "January", "February", "March", "April", "May", "June",
62         "July", "August", "September", "October", "November", "December"
63     };
64
65     unsigned    count;
66     unsigned    len;
67     char        c;
68     char        arg[40];
69     const char* argptr;
70
71     /* Copy until we reach the end of the format string or a format specifier */
72     count = 0;
73     while (1) {
74         if (count >= bufsize) {
75             /* Not enough buffer space available */
76             return 0;
77         }
78         if ((c = *format++) == '\0') {
79             /* End of format string reached */
80             *buf = '\0';
81             return count;
82         }
83         if (c == '%') {
84             /* Format specifier */
85             argptr = arg;
86             switch (*format++) {
87
88                 case '%':
89                     arg[0] = '%';
90                     arg[1] = '\0';
91                     break;
92
93                 case 'A':
94                     argptr = days[tm->tm_wday];
95                     break;
96
97                 case 'B':
98                     argptr = months[tm->tm_mon];
99                     break;
100
101                 case 'D':
102                     sprintf (arg, "%02d/%02d/%02d", tm->tm_mon + 1,
103                              tm->tm_mday, tm->tm_year % 100);
104                     break;
105
106                 case 'F':
107                     /* C99 */
108                     sprintf (arg, "%04d-%02d-%02d", tm->tm_year + 1900,
109                              tm->tm_mon + 1, tm->tm_mday);
110                     break;
111
112                 case 'H':
113                     sprintf (arg, "%02d", tm->tm_hour);
114                     break;
115
116                 case 'I':
117                     sprintf (arg, "%02d", (tm->tm_hour + 11) % 12 + 1);
118                     break;
119
120                 case 'M':
121                     sprintf (arg, "%02d", tm->tm_min);
122                     break;
123
124                 case 'P':
125                     /* GNU extension */
126                     argptr = (tm->tm_hour >= 12)? "pm" : "am";
127                     break;
128
129                 case 'S':
130                     sprintf (arg, "%02d", tm->tm_sec);
131                     break;
132
133                 case 'U':
134                     sprintf (arg, "%02d", (tm->tm_yday + 7 - tm->tm_wday) / 7);
135                     break;
136
137                 case 'W':
138                     sprintf (arg, "%02d",
139                              (tm->tm_yday + 7 - (tm->tm_wday? tm->tm_wday - 1 : 6)) / 7);
140                     break;
141
142                 case 'X':
143                     sprintf (arg, "%02d:%02d:%02d", tm->tm_hour,
144                              tm->tm_min, tm->tm_sec);
145                     break;
146
147                 case 'Y':
148                     sprintf (arg, "%4d", tm->tm_year + 1900);
149                     break;
150
151                 case 'Z':
152                     argptr = tm->tm_isdst? _tz.dstname : _tz.tzname;
153                     break;
154
155                 case 'a':
156                     sprintf (arg, "%.3s", days[tm->tm_wday]);
157                     break;
158
159                 case 'b':
160                     sprintf (arg, "%.3s", months[tm->tm_mon]);
161                     break;
162
163                 case 'c':
164                     sprintf (arg, "%.3s %.3s%3d %02d:%02d:%02d %d",
165                              days[tm->tm_wday], months[tm->tm_mon],
166                              tm->tm_mday, tm->tm_hour, tm->tm_min,
167                              tm->tm_sec, tm->tm_year + 1900);
168                     break;
169
170                 case 'd':
171                     sprintf (arg, "%02d", tm->tm_mday);
172                     break;
173
174                 case 'j':
175                     sprintf (arg, "%03d", tm->tm_yday + 1);
176                     break;
177
178                 case 'm':
179                     sprintf (arg, "%02d", tm->tm_mon + 1);
180                     break;
181
182                 case 'p':
183                     argptr = (tm->tm_hour >= 12)? "PM" : "AM";
184                     break;
185
186                 case 'w':
187                     sprintf (arg, "%d", tm->tm_wday);
188                     break;
189
190                 case 'x':
191                     sprintf (arg, "%04d-%02d-%02d", tm->tm_year + 1900,
192                              tm->tm_mon + 1, tm->tm_mday);
193                     break;
194
195                 case 'y':
196                     sprintf (arg, "%02d", tm->tm_year % 100);
197                     break;
198
199                 default:
200                     /* Unknown format specifier, convert to empty string */
201                     arg[0] = '\0';
202                     break;
203             }
204
205             /* Check if we have enough space to copy the argument string */
206             len = strlen (argptr);
207             count += len;
208             if (count < bufsize) {
209                 memcpy (buf, argptr, len);
210                 buf += len;
211             }
212
213         } else {
214
215             /* No format character, just copy */
216             *buf++ = c;
217             ++count;
218
219         }
220     }
221 }
222
223
224