Mercurial > hg > xemacs-beta
annotate src/strftime.c @ 5041:efaa6cd845e5
add regexp-debugging
-------------------- ChangeLog entries follow: --------------------
src/ChangeLog addition:
2010-02-15 Ben Wing <ben@xemacs.org>
* regex.c:
* regex.c (DEBUG_FAIL_PRINT1):
* regex.c (PUSH_FAILURE_POINT):
* regex.c (POP_FAILURE_POINT):
* regex.c (regex_compile):
* regex.c (re_match_2_internal):
* regex.h:
* search.c:
* search.c (search_buffer):
* search.c (debug_regexps_changed):
* search.c (vars_of_search):
Add an internal variable debug_regexps and a corresponding Lisp
variable `debug-regexps' that takes a list of areas in which to
display debugging info about regex compilation and matching
(currently three areas exist). Use existing debugging code
already in regex.c and modify it so that it recognizes the
debug_regexps variable and the flags in it.
Rename variable `debug-xemacs-searches' to just `debug-searches',
consistent with other debug vars.
tests/ChangeLog addition:
2010-02-15 Ben Wing <ben@xemacs.org>
* automated/search-tests.el (let):
* automated/search-tests.el (boundp):
debug-xemacs-searches renamed to debug-searches.
| author | Ben Wing <ben@xemacs.org> |
|---|---|
| date | Mon, 15 Feb 2010 21:51:22 -0600 |
| parents | 2ade80e8c640 |
| children | 1537701f08a1 |
| rev | line source |
|---|---|
| 428 | 1 /* strftime - custom formatting of date and/or time |
| 2 Copyright (C) 1989, 1991, 1992 Free Software Foundation, Inc. | |
| 3 | |
| 4 This program is free software; you can redistribute it and/or modify | |
| 5 it under the terms of the GNU General Public License as published by | |
| 6 the Free Software Foundation; either version 2, or (at your option) | |
| 7 any later version. | |
| 8 | |
| 9 This program is distributed in the hope that it will be useful, | |
| 10 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 12 GNU General Public License for more details. | |
| 13 | |
| 14 You should have received a copy of the GNU General Public License | |
| 15 along with this program; see the file COPYING. If not, write to | |
| 16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
| 17 Boston, MA 02111-1307, USA. */ | |
| 18 | |
| 19 /* Synched up with: FSF 19.30. */ | |
| 20 | |
| 771 | 21 /* This file has been ... uhhhhh ... Mule-ized. Yeah. |
| 22 | |
| 23 (Everything here is external format. This is DANGEROUS and | |
| 24 data-lossy, but fixing it is too much of a bother now.) --ben */ | |
| 25 | |
| 428 | 26 /* Note: this version of strftime lacks locale support, |
| 27 but it is standalone. | |
| 28 | |
| 29 Performs `%' substitutions similar to those in printf. Except | |
| 30 where noted, substituted fields have a fixed size; numeric fields are | |
| 31 padded if necessary. Padding is with zeros by default; for fields | |
| 32 that display a single number, padding can be changed or inhibited by | |
| 33 following the `%' with one of the modifiers described below. Unknown | |
| 34 field specifiers are copied as normal characters. All other | |
| 35 characters are copied to the output without change. | |
| 36 | |
| 37 Supports a superset of the ANSI C field specifiers. | |
| 38 | |
| 39 Literal character fields: | |
| 40 % % | |
| 41 n newline | |
| 42 t tab | |
| 43 | |
| 44 Numeric modifiers (a nonstandard extension): | |
| 45 - do not pad the field | |
| 46 _ pad the field with spaces | |
| 47 | |
| 48 Time fields: | |
| 49 %H hour (00..23) | |
| 50 %I hour (01..12) | |
| 51 %k hour ( 0..23) | |
| 52 %l hour ( 1..12) | |
| 53 %M minute (00..59) | |
| 54 %p locale's AM or PM | |
| 55 %r time, 12-hour (hh:mm:ss [AP]M) | |
| 56 %R time, 24-hour (hh:mm) | |
| 57 %s time in seconds since 00:00:00, Jan 1, 1970 (a nonstandard extension) | |
| 58 %S second (00..61) | |
| 59 %T time, 24-hour (hh:mm:ss) | |
| 60 %X locale's time representation (%H:%M:%S) | |
| 4203 | 61 %z time zone offset (e.g. +0530, -0800 etc) |
| 428 | 62 %Z time zone (EDT), or nothing if no time zone is determinable |
| 63 | |
| 64 Date fields: | |
| 65 %a locale's abbreviated weekday name (Sun..Sat) | |
| 66 %A locale's full weekday name, variable length (Sunday..Saturday) | |
| 67 %b locale's abbreviated month name (Jan..Dec) | |
| 68 %B locale's full month name, variable length (January..December) | |
| 69 %c locale's date and time (Sat Nov 04 12:02:33 EST 1989) | |
| 70 %C century (00..99) | |
| 71 %d day of month (01..31) | |
| 72 %e day of month ( 1..31) | |
| 73 %D date (mm/dd/yy) | |
| 4203 | 74 %G year corresponding to the ISO 8601 week |
| 75 %g Year of the ISO 8601 week within century (00 - 99) | |
| 428 | 76 %h same as %b |
| 77 %j day of year (001..366) | |
| 78 %m month (01..12) | |
| 79 %U week number of year with Sunday as first day of week (00..53) | |
| 4203 | 80 %V ISO 8601 week number (first week is the earliest one with Thu) |
| 428 | 81 %w day of week (0..6) |
| 82 %W week number of year with Monday as first day of week (00..53) | |
| 83 %x locale's date representation (mm/dd/yy) | |
| 84 %y last two digits of year (00..99) | |
| 85 %Y year (1970...) | |
| 86 | |
| 87 David MacKenzie <djm@gnu.ai.mit.edu> */ | |
| 88 | |
| 89 #ifdef HAVE_CONFIG_H | |
| 90 #include <config.h> | |
| 91 #include "lisp.h" | |
| 92 #endif | |
| 93 | |
| 94 #include <stdio.h> | |
| 95 #include <sys/types.h> | |
| 96 #if defined(TM_IN_SYS_TIME) || (!defined(HAVE_TM_ZONE) && !defined(HAVE_TZNAME)) | |
| 97 #include <sys/time.h> | |
| 98 #else | |
| 99 #include <time.h> | |
| 100 #endif | |
| 101 | |
| 102 #ifndef STDC_HEADERS | |
| 103 time_t mktime (); | |
| 104 #endif | |
| 105 | |
| 442 | 106 #if defined(WIN32_NATIVE) || defined(CYGWIN) |
| 428 | 107 #include <time.h> |
| 108 #else | |
| 109 #if defined(HAVE_TZNAME) | |
| 110 extern char *tzname[2]; | |
| 111 #endif | |
| 442 | 112 #endif /* WIN32_NATIVE */ |
| 428 | 113 |
| 114 #ifdef emacs | |
| 115 #define strftime emacs_strftime | |
| 116 #endif | |
| 117 | |
| 118 /* Types of padding for numbers in date and time. */ | |
| 119 enum padding | |
| 120 { | |
| 121 none, blank, zero | |
| 122 }; | |
| 123 | |
| 442 | 124 static char const* const days[] = |
| 428 | 125 { |
| 126 "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" | |
| 127 }; | |
| 128 | |
| 442 | 129 static char const * const months[] = |
| 428 | 130 { |
| 131 "January", "February", "March", "April", "May", "June", | |
| 132 "July", "August", "September", "October", "November", "December" | |
| 133 }; | |
| 134 | |
| 135 /* Add character C to STRING and increment LENGTH, | |
| 136 unless LENGTH would exceed MAX. */ | |
| 137 | |
| 138 #define add_char(c) do \ | |
| 139 { \ | |
| 140 if (length + 1 <= max) \ | |
| 141 string[length++] = (c); \ | |
| 142 } while (0) | |
| 143 | |
| 144 /* Add a 2 digit number to STRING, padding if specified. | |
| 145 Return the number of characters added, up to MAX. */ | |
| 146 | |
| 147 static int | |
| 148 add_num2 (char *string, int num, int max, enum padding pad) | |
| 149 { | |
| 150 int top = num / 10; | |
| 151 int length = 0; | |
| 152 | |
| 153 if (top == 0 && pad == blank) | |
| 154 add_char (' '); | |
| 155 else if (top != 0 || pad == zero) | |
| 156 add_char (top + '0'); | |
| 157 add_char (num % 10 + '0'); | |
| 158 return length; | |
| 159 } | |
| 160 | |
| 161 /* Add a 3 digit number to STRING, padding if specified. | |
| 162 Return the number of characters added, up to MAX. */ | |
| 163 | |
| 164 static int | |
| 165 add_num3 (char *string, int num, int max, enum padding pad) | |
| 166 { | |
| 167 int top = num / 100; | |
| 168 int mid = (num - top * 100) / 10; | |
| 169 int length = 0; | |
| 170 | |
| 171 if (top == 0 && pad == blank) | |
| 172 add_char (' '); | |
| 173 else if (top != 0 || pad == zero) | |
| 174 add_char (top + '0'); | |
| 175 if (mid == 0 && top == 0 && pad == blank) | |
| 176 add_char (' '); | |
| 177 else if (mid != 0 || top != 0 || pad == zero) | |
| 178 add_char (mid + '0'); | |
| 179 add_char (num % 10 + '0'); | |
| 180 return length; | |
| 181 } | |
| 182 | |
| 183 /* Like strncpy except return the number of characters copied. */ | |
| 184 | |
| 185 static int | |
| 442 | 186 add_str (char *to, const char *from, int max) |
| 428 | 187 { |
| 188 int i; | |
| 189 | |
| 190 for (i = 0; from[i] && i <= max; ++i) | |
| 191 to[i] = from[i]; | |
| 192 return i; | |
| 193 } | |
| 194 | |
| 195 static int | |
| 196 add_num_time_t (char *string, int max, time_t num) | |
| 197 { | |
| 198 /* This buffer is large enough to hold the character representation | |
| 199 (including the trailing NUL) of any unsigned decimal quantity | |
| 200 whose binary representation fits in 128 bits. */ | |
| 201 char buf[40]; | |
| 202 | |
| 203 if (sizeof (num) > 16) | |
| 2500 | 204 ABORT (); |
| 428 | 205 sprintf (buf, "%lu", (unsigned long) num); |
| 793 | 206 return add_str (string, buf, max); |
| 428 | 207 } |
| 208 | |
| 209 /* Return the week in the year of the time in TM, with the weeks | |
| 210 starting on Sundays. */ | |
| 211 | |
| 212 static int | |
| 442 | 213 sun_week (const struct tm *tm) |
| 428 | 214 { |
| 215 int dl; | |
| 216 | |
| 217 /* Set `dl' to the day in the year of the last day of the week previous | |
| 218 to the one containing the day specified in TM. If the day specified | |
| 219 in TM is in the first week of the year, `dl' will be negative or 0. | |
| 220 Otherwise, calculate the number of complete weeks before our week | |
| 221 (dl / 7) and add any partial week at the start of the year (dl % 7). */ | |
| 222 dl = tm->tm_yday - tm->tm_wday; | |
| 223 return dl <= 0 ? 0 : dl / 7 + (dl % 7 != 0); | |
| 224 } | |
| 225 | |
| 226 /* Return the week in the year of the time in TM, with the weeks | |
| 227 starting on Mondays. */ | |
| 228 | |
| 229 static int | |
| 442 | 230 mon_week (const struct tm *tm) |
| 428 | 231 { |
| 232 int dl, wday; | |
| 233 | |
| 234 if (tm->tm_wday == 0) | |
| 235 wday = 6; | |
| 236 else | |
| 237 wday = tm->tm_wday - 1; | |
| 238 dl = tm->tm_yday - wday; | |
| 239 return dl <= 0 ? 0 : dl / 7 + (dl % 7 != 0); | |
| 240 } | |
| 241 | |
| 4203 | 242 #ifndef __isleap |
| 243 /* Nonzero if YEAR is a leap year (every 4 years, | |
| 244 except every 100th isn't, and every 400th is). */ | |
| 245 # define __isleap(year) \ | |
| 246 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) | |
| 247 #endif | |
| 248 | |
| 249 /* The number of days from the first day of the first ISO week of this | |
| 250 year to the year day YDAY with week day WDAY. ISO weeks start on | |
| 251 Monday; the first ISO week has the year's first Thursday. YDAY may | |
| 252 be as small as YDAY_MINIMUM. */ | |
| 253 #define ISO_WEEK_START_WDAY 1 /* Monday */ | |
| 254 #define ISO_WEEK1_WDAY 4 /* Thursday */ | |
| 255 #define YDAY_MINIMUM (-366) | |
| 256 static int | |
| 257 iso_week_days (int yday, int wday) | |
| 258 { | |
| 259 /* Add enough to the first operand of % to make it nonnegative. */ | |
| 260 int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7; | |
| 261 return (yday | |
| 262 - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7 | |
| 263 + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY); | |
| 264 } | |
| 265 | |
| 428 | 266 #if !defined(HAVE_TM_ZONE) && !defined(HAVE_TZNAME) |
| 442 | 267 char *zone_name (const struct tm *tp); |
| 428 | 268 char * |
| 442 | 269 zone_name (const struct tm *tp) |
| 428 | 270 { |
| 271 char *timezone (); | |
| 272 struct timeval tv; | |
| 273 struct timezone tz; | |
| 274 | |
| 275 gettimeofday (&tv, &tz); | |
| 276 return timezone (tz.tz_minuteswest, tp->tm_isdst); | |
| 277 } | |
| 278 #endif | |
| 279 | |
| 280 /* Format the time given in TM according to FORMAT, and put the | |
| 281 results in STRING. | |
| 282 Return the number of characters (not including terminating null) | |
| 283 that were put into STRING, or 0 if the length would have | |
| 284 exceeded MAX. */ | |
| 285 | |
| 442 | 286 size_t strftime (char *string, size_t max, const char *format, |
| 287 const struct tm *tm); | |
| 428 | 288 |
| 289 size_t | |
| 442 | 290 strftime (char *string, size_t max, const char *format, const struct tm *tm) |
| 428 | 291 { |
| 292 enum padding pad; /* Type of padding to apply. */ | |
| 293 size_t length = 0; /* Characters put in STRING so far. */ | |
| 294 | |
| 295 for (; *format && length < max; ++format) | |
| 296 { | |
| 297 if (*format != '%') | |
| 298 add_char (*format); | |
| 299 else | |
| 300 { | |
| 301 ++format; | |
| 302 /* Modifiers: */ | |
| 303 if (*format == '-') | |
| 304 { | |
| 305 pad = none; | |
| 306 ++format; | |
| 307 } | |
| 308 else if (*format == '_') | |
| 309 { | |
| 310 pad = blank; | |
| 311 ++format; | |
| 312 } | |
| 313 else | |
| 314 pad = zero; | |
| 315 | |
| 316 switch (*format) | |
| 317 { | |
| 318 /* Literal character fields: */ | |
| 319 case 0: | |
| 320 case '%': | |
| 321 add_char ('%'); | |
| 322 break; | |
| 323 case 'n': | |
| 324 add_char ('\n'); | |
| 325 break; | |
| 326 case 't': | |
| 327 add_char ('\t'); | |
| 328 break; | |
| 329 default: | |
| 330 add_char (*format); | |
| 331 break; | |
| 332 | |
| 333 /* Time fields: */ | |
| 334 case 'H': | |
| 335 case 'k': | |
| 336 length += | |
| 337 add_num2 (&string[length], tm->tm_hour, max - length, | |
| 338 *format == 'H' ? pad : blank); | |
| 339 break; | |
| 340 case 'I': | |
| 341 case 'l': | |
| 342 { | |
| 343 int hour12; | |
| 344 | |
| 345 if (tm->tm_hour == 0) | |
| 346 hour12 = 12; | |
| 347 else if (tm->tm_hour > 12) | |
| 348 hour12 = tm->tm_hour - 12; | |
| 349 else | |
| 350 hour12 = tm->tm_hour; | |
| 351 length += | |
| 352 add_num2 (&string[length], hour12, max - length, | |
| 353 *format == 'I' ? pad : blank); | |
| 354 } | |
| 355 break; | |
| 356 case 'M': | |
| 357 length += | |
| 358 add_num2 (&string[length], tm->tm_min, max - length, pad); | |
| 359 break; | |
| 360 case 'p': | |
| 361 if (tm->tm_hour < 12) | |
| 362 add_char ('A'); | |
| 363 else | |
| 364 add_char ('P'); | |
| 365 add_char ('M'); | |
| 366 break; | |
| 367 case 'r': | |
| 368 length += | |
| 369 strftime (&string[length], max - length, "%I:%M:%S %p", tm); | |
| 370 break; | |
| 371 case 'R': | |
| 372 length += | |
| 373 strftime (&string[length], max - length, "%H:%M", tm); | |
| 374 break; | |
| 375 | |
| 376 case 's': | |
| 377 { | |
| 378 struct tm writable_tm; | |
| 379 writable_tm = *tm; | |
| 380 length += add_num_time_t (&string[length], max - length, | |
| 381 mktime (&writable_tm)); | |
| 382 } | |
| 383 break; | |
| 384 | |
| 385 case 'S': | |
| 386 length += | |
| 387 add_num2 (&string[length], tm->tm_sec, max - length, pad); | |
| 388 break; | |
| 389 case 'T': | |
| 390 length += | |
| 391 strftime (&string[length], max - length, "%H:%M:%S", tm); | |
| 392 break; | |
| 4203 | 393 |
| 394 case 'V': | |
| 395 case 'g': | |
| 396 case 'G': | |
| 397 { | |
| 398 int year = tm->tm_year + 1900; | |
|
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4203
diff
changeset
|
399 int ndays = iso_week_days (tm->tm_yday, tm->tm_wday); |
| 4203 | 400 |
|
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4203
diff
changeset
|
401 if (ndays < 0) |
| 4203 | 402 { |
| 403 /* This ISO week belongs to the previous year. */ | |
| 404 year--; | |
|
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4203
diff
changeset
|
405 ndays = |
| 4203 | 406 iso_week_days (tm->tm_yday + (365 + __isleap (year)), |
| 407 tm->tm_wday); | |
| 408 } | |
| 409 else | |
| 410 { | |
| 411 int d = | |
| 412 iso_week_days (tm->tm_yday - (365 + __isleap (year)), | |
| 413 tm->tm_wday); | |
| 414 if (0 <= d) | |
| 415 { | |
| 416 /* This ISO week belongs to the next year. */ | |
| 417 year++; | |
|
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4203
diff
changeset
|
418 ndays = d; |
| 4203 | 419 } |
| 420 } | |
| 421 | |
| 422 switch (*format) | |
| 423 { | |
| 424 /* | |
| 425 #### FIXME | |
| 426 We really can't assume 1000 <= year <= 9999 | |
| 427 once time_t gets beyond 32 bits, but it's true | |
| 428 of the rest of the code here so get with the | |
| 429 program | |
| 430 */ | |
| 431 case 'g': | |
| 432 length += | |
| 433 add_num2 (&string[length], year % 100, | |
| 434 max - length, pad); | |
| 435 break; | |
| 436 | |
| 437 case 'G': | |
| 438 add_char (year / 1000 + '0'); | |
| 439 length += add_num3 (&string[length], year % 1000, | |
| 440 max - length, zero); | |
| 441 break; | |
| 442 | |
| 443 default: | |
| 444 length += | |
|
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4203
diff
changeset
|
445 add_num2 (&string[length], ndays / 7 + 1, |
| 4203 | 446 max - length, pad); |
| 447 break; | |
| 448 } | |
| 449 } | |
| 450 break; | |
| 428 | 451 case 'X': |
| 452 length += | |
| 453 strftime (&string[length], max - length, "%H:%M:%S", tm); | |
| 454 break; | |
| 4203 | 455 case 'z': |
| 456 { | |
| 457 /* | |
| 458 #### FIXME: could use tm->tm_gmtoff if present. Since | |
| 459 the other code in xemacs does not do so we follow the | |
| 460 leaders (and don't add a autoconf macro to detect | |
| 461 its presence). | |
| 462 */ | |
| 463 long int offset; | |
| 464 long int minutes; | |
| 465 struct tm lt, *ut; | |
| 466 time_t utc; | |
| 467 | |
| 468 lt = *tm; | |
| 469 utc = mktime(<); | |
| 470 ut = gmtime(&utc); | |
| 471 /* assume that tm is valid so the others will be too! */ | |
| 472 assert( utc != (time_t) -1 && ut != NULL ); | |
| 473 | |
| 474 /* tm diff code below is based on mktime.c, glibc 2.3.2 */ | |
| 475 { | |
| 476 int lt4, ut4, lt100, ut100, lt400, ut400; | |
|
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4203
diff
changeset
|
477 int intervening_leap_days, years, ndays; |
| 4203 | 478 |
| 479 lt4 = (lt.tm_year >> 2) + (1900 >> 2) - | |
| 480 ! (lt.tm_year & 3); | |
| 481 ut4 = (ut->tm_year >> 2) + (1900 >> 2) - | |
| 482 ! (ut->tm_year & 3); | |
| 483 lt100 = lt4 / 25 - (lt4 % 25 < 0); | |
| 484 ut100 = ut4 / 25 - (ut4 % 25 < 0); | |
| 485 lt400 = lt100 >> 2; | |
| 486 ut400 = ut100 >> 2; | |
| 487 intervening_leap_days = | |
| 488 (lt4 - ut4) - (lt100 - ut100) + (lt400 - ut400); | |
| 489 years = lt.tm_year - ut->tm_year; | |
|
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4203
diff
changeset
|
490 ndays = (365 * years + intervening_leap_days |
| 4203 | 491 + (lt.tm_yday - ut->tm_yday)); |
|
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4203
diff
changeset
|
492 offset = (60 * (60 * (24 * ndays |
|
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4203
diff
changeset
|
493 + (lt.tm_hour - ut->tm_hour)) |
| 4203 | 494 + (lt.tm_min - ut->tm_min)) |
| 495 + (lt.tm_sec - ut->tm_sec)); | |
| 496 } | |
| 497 | |
| 498 minutes = offset / ( offset < 0 ? -60 : 60 ); | |
| 499 | |
| 500 add_char ((offset < 0 ? '-' : '+')); | |
| 501 | |
| 502 if ( minutes / 600 != 0 ) | |
| 503 add_char (minutes / 600 + '0'); | |
| 504 else if ( pad != none ) | |
| 505 add_char ((pad == zero ? '0' : ' ')); | |
| 506 | |
| 507 length += | |
| 508 add_num3 (&string[length], | |
| 509 ((minutes / 60 ) % 10) * 100 + (minutes % 60), | |
| 510 max - length, pad); | |
| 511 break; | |
| 512 } | |
| 428 | 513 case 'Z': |
| 514 #ifdef HAVE_TM_ZONE | |
| 515 length += add_str (&string[length], tm->tm_zone, max - length); | |
| 516 #else | |
| 517 #ifdef HAVE_TZNAME | |
| 518 if (tm->tm_isdst && tzname[1] && *tzname[1]) | |
| 519 length += add_str (&string[length], tzname[1], max - length); | |
| 520 else | |
| 521 length += add_str (&string[length], tzname[0], max - length); | |
| 522 #else | |
| 523 length += add_str (&string[length], zone_name (tm), max - length); | |
| 524 #endif | |
| 525 #endif | |
| 526 break; | |
| 527 | |
| 528 /* Date fields: */ | |
| 529 case 'a': | |
| 530 add_char (days[tm->tm_wday][0]); | |
| 531 add_char (days[tm->tm_wday][1]); | |
| 532 add_char (days[tm->tm_wday][2]); | |
| 533 break; | |
| 534 case 'A': | |
| 535 length += | |
| 536 add_str (&string[length], days[tm->tm_wday], max - length); | |
| 537 break; | |
| 538 case 'b': | |
| 539 case 'h': | |
| 540 add_char (months[tm->tm_mon][0]); | |
| 541 add_char (months[tm->tm_mon][1]); | |
| 542 add_char (months[tm->tm_mon][2]); | |
| 543 break; | |
| 544 case 'B': | |
| 545 length += | |
| 546 add_str (&string[length], months[tm->tm_mon], max - length); | |
| 547 break; | |
| 548 case 'c': | |
| 549 length += | |
| 550 strftime (&string[length], max - length, | |
| 551 "%a %b %d %H:%M:%S %Z %Y", tm); | |
| 552 break; | |
| 553 case 'C': | |
| 554 length += | |
| 555 add_num2 (&string[length], (tm->tm_year + 1900) / 100, | |
| 556 max - length, pad); | |
| 557 break; | |
| 558 case 'd': | |
| 559 length += | |
| 560 add_num2 (&string[length], tm->tm_mday, max - length, pad); | |
| 561 break; | |
| 562 case 'e': | |
| 563 length += | |
| 564 add_num2 (&string[length], tm->tm_mday, max - length, blank); | |
| 565 break; | |
| 566 case 'D': | |
| 567 length += | |
| 568 strftime (&string[length], max - length, "%m/%d/%y", tm); | |
| 569 break; | |
| 570 case 'j': | |
| 571 length += | |
| 572 add_num3 (&string[length], tm->tm_yday + 1, max - length, pad); | |
| 573 break; | |
| 574 case 'm': | |
| 575 length += | |
| 576 add_num2 (&string[length], tm->tm_mon + 1, max - length, pad); | |
| 577 break; | |
| 578 case 'U': | |
| 579 length += | |
| 580 add_num2 (&string[length], sun_week (tm), max - length, pad); | |
| 581 break; | |
| 582 case 'w': | |
| 583 add_char (tm->tm_wday + '0'); | |
| 584 break; | |
| 585 case 'W': | |
| 586 length += | |
| 587 add_num2 (&string[length], mon_week (tm), max - length, pad); | |
| 588 break; | |
| 589 case 'x': | |
| 590 length += | |
| 591 strftime (&string[length], max - length, "%m/%d/%y", tm); | |
| 592 break; | |
| 593 case 'y': | |
| 594 length += | |
| 595 add_num2 (&string[length], tm->tm_year % 100, | |
| 596 max - length, pad); | |
| 597 break; | |
| 598 case 'Y': | |
| 599 add_char ((tm->tm_year + 1900) / 1000 + '0'); | |
| 600 length += | |
| 601 add_num3 (&string[length], | |
| 602 (1900 + tm->tm_year) % 1000, max - length, zero); | |
| 603 break; | |
| 604 } | |
| 605 } | |
| 606 } | |
| 607 add_char (0); | |
| 608 return length - 1; | |
| 609 } |
