Subversion Repositories Kolibri OS

Rev

Rev 4874 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4874 Rev 4921
Line 22... Line 22...
22
INDEX
22
INDEX
23
	strftime
23
	strftime
Line 24... Line 24...
24
 
24
 
25
ANSI_SYNOPSIS
25
ANSI_SYNOPSIS
26
	#include 
26
	#include 
-
 
27
	size_t strftime(char *restrict <[s]>, size_t <[maxsize]>,
27
	size_t strftime(char *<[s]>, size_t <[maxsize]>,
28
			const char *restrict <[format]>,
Line 28... Line 29...
28
			const char *<[format]>, const struct tm *<[timp]>);
29
                        const struct tm *restrict <[timp]>);
29
 
30
 
30
TRAD_SYNOPSIS
31
TRAD_SYNOPSIS
31
	#include 
32
	#include 
Line 268... Line 269...
268
#include 
269
#include 
269
#include 
270
#include 
270
#include 
271
#include 
271
#include 
272
#include 
272
#include 
273
#include 
-
 
274
#include "local.h"
-
 
275
#include "../locale/timelocal.h"
Line 273... Line 276...
273
 
276
 
274
/* Defines to make the file dual use for either strftime() or wcsftime().
277
/* Defines to make the file dual use for either strftime() or wcsftime().
275
 * To get wcsftime, define MAKE_WCSFTIME.
278
 * To get wcsftime, define MAKE_WCSFTIME.
276
 * To get strftime, do not define MAKE_WCSFTIME.
279
 * To get strftime, do not define MAKE_WCSFTIME.
Line 281... Line 284...
281
#if !defined(MAKE_WCSFTIME)
284
#if !defined(MAKE_WCSFTIME)
282
#  define CHAR      char        /* string type basis */
285
#  define CHAR      char        /* string type basis */
283
#  define CQ(a)     a       /* character constant qualifier */
286
#  define CQ(a)     a       /* character constant qualifier */
284
#  define SFLG              /* %s flag (null for normal char) */
287
#  define SFLG              /* %s flag (null for normal char) */
285
#  define _ctloc(x) (ctloclen = strlen (ctloc = _CurrentTimeLocale->x), ctloc)
288
#  define _ctloc(x) (ctloclen = strlen (ctloc = _CurrentTimeLocale->x), ctloc)
-
 
289
#  define snprintf	sniprintf	/* avoid to pull in FP functions. */
286
#  define TOLOWER(c)    tolower((int)(unsigned char)(c))
290
#  define TOLOWER(c)    tolower((int)(unsigned char)(c))
287
#  define STRTOUL(c,p,b) strtoul((c),(p),(b))
291
#  define STRTOUL(c,p,b) strtoul((c),(p),(b))
288
#  define STRCPY(a,b)   strcpy((a),(b))
292
#  define STRCPY(a,b)   strcpy((a),(b))
289
#  define STRCHR(a,b)   strchr((a),(b))
293
#  define STRCHR(a,b)   strchr((a),(b))
290
#  define STRLEN(a) strlen(a)
294
#  define STRLEN(a) strlen(a)
Line 317... Line 321...
317
#   define _ctloc(x) (ctloc = __ctloc (ctlocbuf, _CurrentTimeLocale->x, \
321
#   define _ctloc(x) (ctloc = __ctloc (ctlocbuf, _CurrentTimeLocale->x, \
318
              &ctloclen))
322
              &ctloclen))
319
#  endif
323
#  endif
320
#endif  /* MAKE_WCSFTIME */
324
#endif  /* MAKE_WCSFTIME */
Line -... Line 325...
-
 
325
 
-
 
326
#define CHECK_LENGTH()	if (len < 0 || (count += len) >= maxsize) \
Line 321... Line 327...
321
 
327
			  return 0
322
 
328
 
323
size_t _DEFUN (strftime, (s, maxsize, format, tim_p),
329
/* Enforce the coding assumptions that YEAR_BASE is positive.  (%C, %Y, etc.) */
-
 
330
#if YEAR_BASE < 0
-
 
331
#  error "YEAR_BASE < 0"
324
	CHAR *s _AND
332
#endif
-
 
333
 
-
 
334
static _CONST int dname_len[7] =
-
 
335
{6, 6, 7, 9, 8, 6, 8};
-
 
336
 
-
 
337
/* Using the tm_year, tm_wday, and tm_yday components of TIM_P, return
-
 
338
   -1, 0, or 1 as the adjustment to add to the year for the ISO week
-
 
339
   numbering used in "%g%G%V", avoiding overflow.  */
325
	size_t maxsize _AND
340
static int
326
	_CONST CHAR *format _AND
341
_DEFUN (iso_year_adjust, (tim_p),
-
 
342
	_CONST struct tm *tim_p)
-
 
343
{
-
 
344
  /* Account for fact that tm_year==0 is year 1900.  */
-
 
345
  int leap = isleap (tim_p->tm_year + (YEAR_BASE
-
 
346
				       - (tim_p->tm_year < 0 ? 0 : 2000)));
-
 
347
 
-
 
348
  /* Pack the yday, wday, and leap year into a single int since there are so
-
 
349
     many disparate cases.  */
-
 
350
#define PACK(yd, wd, lp) (((yd) << 4) + (wd << 1) + (lp))
-
 
351
  switch (PACK (tim_p->tm_yday, tim_p->tm_wday, leap))
-
 
352
    {
-
 
353
    case PACK (0, 5, 0): /* Jan 1 is Fri, not leap.  */
-
 
354
    case PACK (0, 6, 0): /* Jan 1 is Sat, not leap.  */
-
 
355
    case PACK (0, 0, 0): /* Jan 1 is Sun, not leap.  */
-
 
356
    case PACK (0, 5, 1): /* Jan 1 is Fri, leap year.  */
-
 
357
    case PACK (0, 6, 1): /* Jan 1 is Sat, leap year.  */
-
 
358
    case PACK (0, 0, 1): /* Jan 1 is Sun, leap year.  */
-
 
359
    case PACK (1, 6, 0): /* Jan 2 is Sat, not leap.  */
-
 
360
    case PACK (1, 0, 0): /* Jan 2 is Sun, not leap.  */
-
 
361
    case PACK (1, 6, 1): /* Jan 2 is Sat, leap year.  */
-
 
362
    case PACK (1, 0, 1): /* Jan 2 is Sun, leap year.  */
-
 
363
    case PACK (2, 0, 0): /* Jan 3 is Sun, not leap.  */
-
 
364
    case PACK (2, 0, 1): /* Jan 3 is Sun, leap year.  */
-
 
365
      return -1; /* Belongs to last week of previous year.  */
-
 
366
    case PACK (362, 1, 0): /* Dec 29 is Mon, not leap.  */
-
 
367
    case PACK (363, 1, 1): /* Dec 29 is Mon, leap year.  */
-
 
368
    case PACK (363, 1, 0): /* Dec 30 is Mon, not leap.  */
-
 
369
    case PACK (363, 2, 0): /* Dec 30 is Tue, not leap.  */
-
 
370
    case PACK (364, 1, 1): /* Dec 30 is Mon, leap year.  */
-
 
371
    case PACK (364, 2, 1): /* Dec 30 is Tue, leap year.  */
-
 
372
    case PACK (364, 1, 0): /* Dec 31 is Mon, not leap.  */
-
 
373
    case PACK (364, 2, 0): /* Dec 31 is Tue, not leap.  */
-
 
374
    case PACK (364, 3, 0): /* Dec 31 is Wed, not leap.  */
-
 
375
    case PACK (365, 1, 1): /* Dec 31 is Mon, leap year.  */
-
 
376
    case PACK (365, 2, 1): /* Dec 31 is Tue, leap year.  */
-
 
377
    case PACK (365, 3, 1): /* Dec 31 is Wed, leap year.  */
-
 
378
      return 1; /* Belongs to first week of next year.  */
-
 
379
    }
-
 
380
  return 0; /* Belongs to specified year.  */
-
 
381
#undef PACK
-
 
382
}
-
 
383
 
-
 
384
#ifdef _WANT_C99_TIME_FORMATS
-
 
385
typedef struct {
-
 
386
  int   year;
-
 
387
  CHAR *era_C;
-
 
388
  CHAR *era_Y;
-
 
389
} era_info_t;
-
 
390
 
-
 
391
static era_info_t *
-
 
392
#if defined (MAKE_WCSFTIME) && defined (__HAVE_LOCALE_INFO_EXTENDED__)
-
 
393
get_era_info (const struct tm *tim_p, const wchar_t *era)
-
 
394
#else
-
 
395
get_era_info (const struct tm *tim_p, const char *era)
-
 
396
#endif
-
 
397
{
-
 
398
#if defined (MAKE_WCSFTIME) && defined (__HAVE_LOCALE_INFO_EXTENDED__)
-
 
399
  wchar_t *c;
-
 
400
  const wchar_t *dir;
-
 
401
# define ERA_STRCHR(a,b)	wcschr((a),(b))
-
 
402
# define ERA_STRNCPY(a,b,c)	wcsncpy((a),(b),(c))
-
 
403
# define ERA_STRTOL(a,b,c)	wcstol((a),(b),(c))
-
 
404
#else
-
 
405
  char *c;
-
 
406
  const char *dir;
-
 
407
# define ERA_STRCHR(a,b)	strchr((a),(b))
-
 
408
# define ERA_STRNCPY(a,b,c)	strncpy((a),(b),(c))
-
 
409
# define ERA_STRTOL(a,b,c)	strtol((a),(b),(c))
-
 
410
#endif
-
 
411
  long offset;
-
 
412
  struct tm stm, etm;
-
 
413
  era_info_t *ei;
-
 
414
 
-
 
415
  ei = (era_info_t *) calloc (1, sizeof (era_info_t));
-
 
416
  if (!ei)
-
 
417
    return NULL;
-
 
418
 
-
 
419
  stm.tm_isdst = etm.tm_isdst = 0;
-
 
420
  while (era)
-
 
421
    {
-
 
422
      dir = era;
-
 
423
      era += 2;
-
 
424
      offset = ERA_STRTOL (era, &c, 10);
-
 
425
      era = c + 1;
-
 
426
      stm.tm_year = ERA_STRTOL (era, &c, 10) - YEAR_BASE;
-
 
427
      /* Adjust offset for negative gregorian dates. */
-
 
428
      if (stm.tm_year <= -YEAR_BASE)
-
 
429
      	++stm.tm_year;
-
 
430
      stm.tm_mon = ERA_STRTOL (c + 1, &c, 10) - 1;
-
 
431
      stm.tm_mday = ERA_STRTOL (c + 1, &c, 10);
-
 
432
      stm.tm_hour = stm.tm_min = stm.tm_sec = 0;
-
 
433
      era = c + 1;
-
 
434
      if (era[0] == '-' && era[1] == '*')
-
 
435
      	{
-
 
436
	  etm = stm;
-
 
437
	  stm.tm_year = INT_MIN;
-
 
438
	  stm.tm_mon = stm.tm_mday = stm.tm_hour = stm.tm_min = stm.tm_sec = 0;
-
 
439
	  era += 3;
-
 
440
	}
-
 
441
      else if (era[0] == '+' && era[1] == '*')
-
 
442
	{
-
 
443
	  etm.tm_year = INT_MAX;
-
 
444
	  etm.tm_mon = 11;
-
 
445
	  etm.tm_mday = 31;
-
 
446
	  etm.tm_hour = 23;
-
 
447
	  etm.tm_min = etm.tm_sec = 59;
-
 
448
	  era += 3;
-
 
449
	}
-
 
450
      else
-
 
451
      	{
-
 
452
	  etm.tm_year = ERA_STRTOL (era, &c, 10) - YEAR_BASE;
-
 
453
	  /* Adjust offset for negative gregorian dates. */
-
 
454
	  if (etm.tm_year <= -YEAR_BASE)
-
 
455
	    ++etm.tm_year;
-
 
456
	  etm.tm_mon = ERA_STRTOL (c + 1, &c, 10) - 1;
-
 
457
	  etm.tm_mday = ERA_STRTOL (c + 1, &c, 10);
-
 
458
	  etm.tm_mday = 31;
-
 
459
	  etm.tm_hour = 23;
-
 
460
	  etm.tm_min = etm.tm_sec = 59;
-
 
461
	  era = c + 1;
-
 
462
	}
-
 
463
      if ((tim_p->tm_year > stm.tm_year
-
 
464
	   || (tim_p->tm_year == stm.tm_year
-
 
465
	       && (tim_p->tm_mon > stm.tm_mon
-
 
466
		   || (tim_p->tm_mon == stm.tm_mon
-
 
467
		       && tim_p->tm_mday >= stm.tm_mday))))
-
 
468
	  && (tim_p->tm_year < etm.tm_year
-
 
469
	      || (tim_p->tm_year == etm.tm_year
-
 
470
		  && (tim_p->tm_mon < etm.tm_mon
-
 
471
		      || (tim_p->tm_mon == etm.tm_mon
-
 
472
			  && tim_p->tm_mday <= etm.tm_mday)))))
-
 
473
	{
-
 
474
	  /* Gotcha */
-
 
475
	  size_t len;
-
 
476
 
-
 
477
	  /* year */
-
 
478
	  if (*dir == '+' && stm.tm_year != INT_MIN)
-
 
479
	    ei->year = tim_p->tm_year - stm.tm_year + offset;
-
 
480
	  else
-
 
481
	    ei->year = etm.tm_year - tim_p->tm_year + offset;
-
 
482
	  /* era_C */
-
 
483
	  c = ERA_STRCHR (era, ':');
-
 
484
#if defined (MAKE_WCSFTIME) && !defined (__HAVE_LOCALE_INFO_EXTENDED__)
-
 
485
	  len = mbsnrtowcs (NULL, &era, c - era, 0, NULL);
-
 
486
	  if (len == (size_t) -1)
-
 
487
	    {
-
 
488
	      free (ei);
-
 
489
	      return NULL;
-
 
490
	    }
-
 
491
#else
-
 
492
	  len = c - era;
-
 
493
#endif
-
 
494
	  ei->era_C = (CHAR *) malloc ((len + 1) * sizeof (CHAR));
-
 
495
	  if (!ei->era_C)
-
 
496
	    {
-
 
497
	      free (ei);
-
 
498
	      return NULL;
-
 
499
	    }
-
 
500
#if defined (MAKE_WCSFTIME) && !defined (__HAVE_LOCALE_INFO_EXTENDED__)
-
 
501
	  len = mbsnrtowcs (ei->era_C, &era, c - era, len + 1, NULL);
-
 
502
#else
-
 
503
	  ERA_STRNCPY (ei->era_C, era, len);
-
 
504
	  era += len;
-
 
505
#endif
-
 
506
	  ei->era_C[len] = CQ('\0');
-
 
507
	  /* era_Y */
-
 
508
	  ++era;
-
 
509
	  c = ERA_STRCHR (era, ';');
-
 
510
	  if (!c)
-
 
511
	    c = ERA_STRCHR (era, '\0');
-
 
512
#if defined (MAKE_WCSFTIME) && !defined (__HAVE_LOCALE_INFO_EXTENDED__)
-
 
513
	  len = mbsnrtowcs (NULL, &era, c - era, 0, NULL);
-
 
514
	  if (len == (size_t) -1)
-
 
515
	    {
-
 
516
	      free (ei->era_C);
-
 
517
	      free (ei);
-
 
518
	      return NULL;
-
 
519
	    }
-
 
520
#else
-
 
521
	  len = c - era;
-
 
522
#endif
-
 
523
	  ei->era_Y = (CHAR *) malloc ((len + 1) * sizeof (CHAR));
-
 
524
	  if (!ei->era_Y)
-
 
525
	    {
-
 
526
	      free (ei->era_C);
-
 
527
	      free (ei);
-
 
528
	      return NULL;
-
 
529
	    }
-
 
530
#if defined (MAKE_WCSFTIME) && !defined (__HAVE_LOCALE_INFO_EXTENDED__)
-
 
531
	  len = mbsnrtowcs (ei->era_Y, &era, c - era, len + 1, NULL);
-
 
532
#else
-
 
533
	  ERA_STRNCPY (ei->era_Y, era, len);
-
 
534
	  era += len;
-
 
535
#endif
-
 
536
	  ei->era_Y[len] = CQ('\0');
-
 
537
	  return ei;
-
 
538
	}
-
 
539
      else
-
 
540
	era = ERA_STRCHR (era, ';');
-
 
541
      if (era)
-
 
542
	++era;
-
 
543
    }
-
 
544
  return NULL;
-
 
545
}
-
 
546
 
-
 
547
static void
-
 
548
free_era_info (era_info_t *ei)
-
 
549
{
-
 
550
  free (ei->era_C);
-
 
551
  free (ei->era_Y);
-
 
552
  free (ei);
-
 
553
}
-
 
554
 
-
 
555
typedef struct {
-
 
556
  size_t num;
-
 
557
  CHAR **digit;
-
 
558
  CHAR *buffer;
-
 
559
} alt_digits_t;
-
 
560
 
-
 
561
static alt_digits_t *
-
 
562
#if defined (MAKE_WCSFTIME) && defined (__HAVE_LOCALE_INFO_EXTENDED__)
-
 
563
get_alt_digits (const wchar_t *alt_digits)
-
 
564
#else
-
 
565
get_alt_digits (const char *alt_digits)
-
 
566
#endif
-
 
567
{
-
 
568
  alt_digits_t *adi;
-
 
569
#if defined (MAKE_WCSFTIME) && defined (__HAVE_LOCALE_INFO_EXTENDED__)
-
 
570
  const wchar_t *a, *e;
-
 
571
# define ALT_STRCHR(a,b)	wcschr((a),(b))
-
 
572
# define ALT_STRCPY(a,b)	wcscpy((a),(b))
-
 
573
# define ALT_STRLEN(a)		wcslen(a)
-
 
574
#else
-
 
575
  const char *a, *e;
-
 
576
# define ALT_STRCHR(a,b)	strchr((a),(b))
-
 
577
# define ALT_STRCPY(a,b)	strcpy((a),(b))
-
 
578
# define ALT_STRLEN(a)		strlen(a)
-
 
579
#endif
-
 
580
  CHAR *aa, *ae;
-
 
581
  size_t len;
-
 
582
 
-
 
583
  adi = (alt_digits_t *) calloc (1, sizeof (alt_digits_t));
-
 
584
  if (!adi)
-
 
585
    return NULL;
-
 
586
 
-
 
587
  /* Compute number of alt_digits. */
-
 
588
  adi->num = 1;
-
 
589
  for (a = alt_digits; (e = ALT_STRCHR (a, ';')) != NULL; a = e + 1)
-
 
590
      ++adi->num;
-
 
591
  /* Allocate the `digit' array, which is an array of `num' pointers into
-
 
592
     `buffer'. */
-
 
593
  adi->digit = (CHAR **) calloc (adi->num, sizeof (CHAR **));
-
 
594
  if (!adi->digit)
-
 
595
    {
-
 
596
      free (adi);
-
 
597
      return NULL;
-
 
598
    }
-
 
599
  /* Compute memory required for `buffer'. */
-
 
600
#if defined (MAKE_WCSFTIME) && !defined (__HAVE_LOCALE_INFO_EXTENDED__)
-
 
601
  len = mbstowcs (NULL, alt_digits, 0);
-
 
602
  if (len == (size_t) -1)
-
 
603
    {
-
 
604
      free (adi->digit);
-
 
605
      free (adi);
-
 
606
      return NULL;
-
 
607
    }
-
 
608
#else
-
 
609
  len = ALT_STRLEN (alt_digits);
-
 
610
#endif
-
 
611
  /* Allocate it. */
-
 
612
  adi->buffer = (CHAR *) malloc ((len + 1) * sizeof (CHAR));
-
 
613
  if (!adi->buffer)
-
 
614
    {
-
 
615
      free (adi->digit);
-
 
616
      free (adi);
-
 
617
      return NULL;
-
 
618
    }
-
 
619
  /* Store digits in it. */
-
 
620
#if defined (MAKE_WCSFTIME) && !defined (__HAVE_LOCALE_INFO_EXTENDED__)
-
 
621
  mbstowcs (adi->buffer, alt_digits, len + 1);
-
 
622
#else
-
 
623
  ALT_STRCPY (adi->buffer, alt_digits);
-
 
624
#endif
-
 
625
  /* Store the pointers into `buffer' into the appropriate `digit' slot. */
-
 
626
  for (len = 0, aa = adi->buffer; (ae = STRCHR (aa, CQ(';'))) != NULL;
-
 
627
       ++len, aa = ae + 1)
-
 
628
    {
-
 
629
      *ae = '\0';
-
 
630
      adi->digit[len] = aa;
-
 
631
    }
-
 
632
  adi->digit[len] = aa;
-
 
633
  return adi;
-
 
634
}
-
 
635
 
-
 
636
static void
-
 
637
free_alt_digits (alt_digits_t *adi)
-
 
638
{
-
 
639
  free (adi->digit);
-
 
640
  free (adi->buffer);
-
 
641
  free (adi);
-
 
642
}
-
 
643
 
-
 
644
/* Return 0 if no alt_digit is available for a number.
-
 
645
   Return -1 if buffer size isn't sufficient to hold alternative digit.
-
 
646
   Return length of new digit otherwise. */
-
 
647
static int
-
 
648
conv_to_alt_digits (CHAR *buf, size_t bufsiz, unsigned num, alt_digits_t *adi)
-
 
649
{
-
 
650
  if (num < adi->num)
-
 
651
    {
-
 
652
      size_t len = STRLEN (adi->digit[num]);
-
 
653
      if (bufsiz < len)
-
 
654
      	return -1;
-
 
655
      STRCPY (buf, adi->digit[num]);
-
 
656
      return (int) len;
-
 
657
    }
-
 
658
  return 0;
-
 
659
}
-
 
660
 
-
 
661
static size_t __strftime (CHAR *, size_t, const CHAR *, const struct tm *,
-
 
662
			  era_info_t **, alt_digits_t **);
-
 
663
 
-
 
664
size_t
-
 
665
_DEFUN (strftime, (s, maxsize, format, tim_p),
-
 
666
	CHAR *__restrict s _AND
-
 
667
	size_t maxsize _AND
-
 
668
	_CONST CHAR *__restrict format _AND
-
 
669
	_CONST struct tm *__restrict tim_p)
-
 
670
{
-
 
671
  era_info_t *era_info = NULL;
-
 
672
  alt_digits_t *alt_digits = NULL;
-
 
673
  size_t ret = __strftime (s, maxsize, format, tim_p, &era_info, &alt_digits);
-
 
674
  if (era_info)
-
 
675
    free_era_info (era_info);
-
 
676
  if (alt_digits)
-
 
677
    free_alt_digits (alt_digits);
-
 
678
  return ret;
-
 
679
}
-
 
680
 
-
 
681
static size_t
-
 
682
__strftime (CHAR *s, size_t maxsize, const CHAR *format,
-
 
683
	    const struct tm *tim_p, era_info_t **era_info,
-
 
684
	    alt_digits_t **alt_digits)
-
 
685
#else /* !_WANT_C99_TIME_FORMATS */
-
 
686
# define __strftime(s,m,f,t,e,a)	strftime((s),(m),(f),(t))
-
 
687
 
-
 
688
size_t
-
 
689
_DEFUN (strftime, (s, maxsize, format, tim_p),
-
 
690
	CHAR *__restrict s _AND
-
 
691
	size_t maxsize _AND
-
 
692
	_CONST CHAR *__restrict format _AND
-
 
693
	_CONST struct tm *__restrict tim_p)
-
 
694
#endif /* !_WANT_C99_TIME_FORMATS */
-
 
695
{
-
 
696
  size_t count = 0;
-
 
697
  int i, len = 0;
-
 
698
  const CHAR *ctloc;
-
 
699
#if defined (MAKE_WCSFTIME) && !defined (__HAVE_LOCALE_INFO_EXTENDED__)
-
 
700
  CHAR ctlocbuf[CTLOCBUFLEN];
-
 
701
#endif
-
 
702
  size_t ctloclen;
-
 
703
  CHAR alt;
-
 
704
  CHAR pad;
-
 
705
  unsigned long width;
-
 
706
 
-
 
707
  struct lc_time_T *_CurrentTimeLocale = __get_current_time_locale ();
-
 
708
  for (;;)
-
 
709
    {
-
 
710
      while (*format && *format != CQ('%'))
-
 
711
	{
-
 
712
	  if (count < maxsize - 1)
-
 
713
	    s[count++] = *format++;
-
 
714
	  else
-
 
715
	    return 0;
-
 
716
	}
-
 
717
      if (*format == CQ('\0'))
-
 
718
	break;
-
 
719
      format++;
-
 
720
      pad = '\0';
-
 
721
      width = 0;
-
 
722
 
-
 
723
      /* POSIX-1.2008 feature: '0' and '+' modifiers require 0-padding with
-
 
724
         slightly different semantics. */
-
 
725
      if (*format == CQ('0') || *format == CQ('+'))
-
 
726
	pad = *format++;
-
 
727
 
-
 
728
      /* POSIX-1.2008 feature: A minimum field width can be specified. */
-
 
729
      if (*format >= CQ('1') && *format <= CQ('9'))
-
 
730
      	{
-
 
731
	  CHAR *fp;
-
 
732
	  width = STRTOUL (format, &fp, 10);
-
 
733
	  format = fp;
-
 
734
	}
-
 
735
 
-
 
736
      alt = CQ('\0');
-
 
737
      if (*format == CQ('E'))
-
 
738
	{
-
 
739
	  alt = *format++;
-
 
740
#ifdef _WANT_C99_TIME_FORMATS      
-
 
741
#if defined (MAKE_WCSFTIME) && defined (__HAVE_LOCALE_INFO_EXTENDED__)
-
 
742
	  if (!*era_info && *_CurrentTimeLocale->wera)
-
 
743
	    *era_info = get_era_info (tim_p, _CurrentTimeLocale->wera);
-
 
744
#else
-
 
745
	  if (!*era_info && *_CurrentTimeLocale->era)
-
 
746
	    *era_info = get_era_info (tim_p, _CurrentTimeLocale->era);
-
 
747
#endif
-
 
748
#endif /* _WANT_C99_TIME_FORMATS */
-
 
749
	}
-
 
750
      else if (*format == CQ('O'))
-
 
751
	{
-
 
752
	  alt = *format++;
-
 
753
#ifdef _WANT_C99_TIME_FORMATS      
-
 
754
#if defined (MAKE_WCSFTIME) && defined (__HAVE_LOCALE_INFO_EXTENDED__)
-
 
755
	  if (!*alt_digits && *_CurrentTimeLocale->walt_digits)
-
 
756
	    *alt_digits = get_alt_digits (_CurrentTimeLocale->walt_digits);
-
 
757
#else
-
 
758
	  if (!*alt_digits && *_CurrentTimeLocale->alt_digits)
-
 
759
	    *alt_digits = get_alt_digits (_CurrentTimeLocale->alt_digits);
-
 
760
#endif
-
 
761
#endif /* _WANT_C99_TIME_FORMATS */
-
 
762
	}
-
 
763
 
-
 
764
      switch (*format)
-
 
765
	{
-
 
766
	case CQ('a'):
-
 
767
	  _ctloc (wday[tim_p->tm_wday]);
-
 
768
	  for (i = 0; i < ctloclen; i++)
-
 
769
	    {
-
 
770
	      if (count < maxsize - 1)
-
 
771
		s[count++] = ctloc[i];
-
 
772
	      else
-
 
773
		return 0;
-
 
774
	    }
-
 
775
	  break;
-
 
776
	case CQ('A'):
-
 
777
	  _ctloc (weekday[tim_p->tm_wday]);
-
 
778
	  for (i = 0; i < ctloclen; i++)
-
 
779
	    {
-
 
780
	      if (count < maxsize - 1)
-
 
781
		s[count++] = ctloc[i];
-
 
782
	      else
-
 
783
		return 0;
-
 
784
	    }
-
 
785
	  break;
-
 
786
	case CQ('b'):
-
 
787
	case CQ('h'):
-
 
788
	  _ctloc (mon[tim_p->tm_mon]);
-
 
789
	  for (i = 0; i < ctloclen; i++)
-
 
790
	    {
-
 
791
	      if (count < maxsize - 1)
-
 
792
		s[count++] = ctloc[i];
-
 
793
	      else
-
 
794
		return 0;
-
 
795
	    }
-
 
796
	  break;
-
 
797
	case CQ('B'):
-
 
798
	  _ctloc (month[tim_p->tm_mon]);
-
 
799
	  for (i = 0; i < ctloclen; i++)
-
 
800
	    {
-
 
801
	      if (count < maxsize - 1)
-
 
802
		s[count++] = ctloc[i];
-
 
803
	      else
-
 
804
		return 0;
-
 
805
	    }
-
 
806
	  break;
-
 
807
	case CQ('c'):
-
 
808
#ifdef _WANT_C99_TIME_FORMATS
-
 
809
	  if (alt == 'E' && *era_info && *_CurrentTimeLocale->era_d_t_fmt)
-
 
810
	    _ctloc (era_d_t_fmt);
-
 
811
	  else
-
 
812
#endif /* _WANT_C99_TIME_FORMATS */
-
 
813
	    _ctloc (c_fmt);
-
 
814
	  goto recurse;
-
 
815
	case CQ('r'):
-
 
816
	  _ctloc (ampm_fmt);
-
 
817
	  goto recurse;
-
 
818
	case CQ('x'):
-
 
819
#ifdef _WANT_C99_TIME_FORMATS
-
 
820
	  if (alt == 'E' && *era_info && *_CurrentTimeLocale->era_d_fmt)
-
 
821
	    _ctloc (era_d_fmt);
-
 
822
	  else
-
 
823
#endif /* _WANT_C99_TIME_FORMATS */
-
 
824
	    _ctloc (x_fmt);
-
 
825
	  goto recurse;
-
 
826
	case CQ('X'):
-
 
827
#ifdef _WANT_C99_TIME_FORMATS
-
 
828
	  if (alt == 'E' && *era_info && *_CurrentTimeLocale->era_t_fmt)
-
 
829
	    _ctloc (era_t_fmt);
-
 
830
	  else
-
 
831
#endif /* _WANT_C99_TIME_FORMATS */
-
 
832
	    _ctloc (X_fmt);
-
 
833
recurse:
-
 
834
	  if (*ctloc)
-
 
835
	    {
-
 
836
	      /* Recurse to avoid need to replicate %Y formation. */
-
 
837
	      len = __strftime (&s[count], maxsize - count, ctloc, tim_p,
-
 
838
				era_info, alt_digits);
-
 
839
	      if (len > 0)
-
 
840
		count += len;
-
 
841
	      else
-
 
842
		return 0;
-
 
843
	    }
-
 
844
	  break;
-
 
845
	case CQ('C'):
-
 
846
	  {
-
 
847
	    /* Examples of (tm_year + YEAR_BASE) that show how %Y == %C%y
-
 
848
	       with 32-bit int.
-
 
849
	       %Y		%C		%y
-
 
850
	       2147485547	21474855	47
-
 
851
	       10000		100		00
-
 
852
	       9999		99		99
-
 
853
	       0999		09		99
-
 
854
	       0099		00		99
-
 
855
	       0001		00		01
-
 
856
	       0000		00		00
-
 
857
	       -001		-0		01
-
 
858
	       -099		-0		99
-
 
859
	       -999		-9		99
-
 
860
	       -1000		-10		00
Line -... Line 861...
-
 
861
	       -10000		-100		00
-
 
862
	       -2147481748	-21474817	48
-
 
863
 
-
 
864
	       Be careful of both overflow and sign adjustment due to the
-
 
865
	       asymmetric range of years.
-
 
866
	    */
-
 
867
#ifdef _WANT_C99_TIME_FORMATS
-
 
868
	    if (alt == 'E' && *era_info)
-
 
869
	      len = snprintf (&s[count], maxsize - count, CQ("%" SFLG "s"),
-
 
870
			      (*era_info)->era_C);
-
 
871
	    else
-
 
872
#endif /* _WANT_C99_TIME_FORMATS */
-
 
873
	      {
-
 
874
		CHAR *fmt = CQ("%s%.*d");
-
 
875
		char *pos = "";
-
 
876
		int neg = tim_p->tm_year < -YEAR_BASE;
-
 
877
		int century = tim_p->tm_year >= 0
-
 
878
		  ? tim_p->tm_year / 100 + YEAR_BASE / 100
-
 
879
		  : abs (tim_p->tm_year + YEAR_BASE) / 100;
-
 
880
		if (pad) /* '0' or '+' */
-
 
881
		  {
-
 
882
		    fmt = CQ("%s%0.*d");
-
 
883
		    if (century >= 100 && pad == CQ('+'))
-
 
884
		      pos = "+";
-
 
885
		  }
-
 
886
		if (width < 2)
-
 
887
		  width = 2;
-
 
888
		len = snprintf (&s[count], maxsize - count, fmt,
-
 
889
				neg ? "-" : pos, width - neg, century);
-
 
890
	      }
-
 
891
            CHECK_LENGTH ();
-
 
892
	  }
-
 
893
	  break;
-
 
894
	case CQ('d'):
-
 
895
	case CQ('e'):
-
 
896
#ifdef _WANT_C99_TIME_FORMATS
-
 
897
	  if (alt == CQ('O') && *alt_digits)
-
 
898
	    {
-
 
899
	      if (tim_p->tm_mday < 10)
-
 
900
	      	{
-
 
901
		  if (*format == CQ('d'))
-
 
902
		    {
-
 
903
		      if (maxsize - count < 2) return 0;
-
 
904
		      len = conv_to_alt_digits (&s[count], maxsize - count,
-
 
905
						0, *alt_digits);
-
 
906
		      CHECK_LENGTH ();
-
 
907
		    }
-
 
908
		  if (*format == CQ('e') || len == 0)
-
 
909
		    s[count++] = CQ(' ');
-
 
910
		}
-
 
911
	      len = conv_to_alt_digits (&s[count], maxsize - count,
-
 
912
					tim_p->tm_mday, *alt_digits);
-
 
913
	      CHECK_LENGTH ();
-
 
914
	      if (len > 0)
-
 
915
		break;
-
 
916
	    }
-
 
917
#endif /* _WANT_C99_TIME_FORMATS */
-
 
918
	  len = snprintf (&s[count], maxsize - count,
-
 
919
			  *format == CQ('d') ? CQ("%.2d") : CQ("%2d"),
-
 
920
			  tim_p->tm_mday);
-
 
921
	  CHECK_LENGTH ();
-
 
922
	  break;
-
 
923
	case CQ('D'):
-
 
924
	  /* %m/%d/%y */
-
 
925
	  len = snprintf (&s[count], maxsize - count,
-
 
926
			  CQ("%.2d/%.2d/%.2d"),
-
 
927
			  tim_p->tm_mon + 1, tim_p->tm_mday,
-
 
928
			  tim_p->tm_year >= 0 ? tim_p->tm_year % 100
-
 
929
			  : abs (tim_p->tm_year + YEAR_BASE) % 100);
-
 
930
          CHECK_LENGTH ();
-
 
931
	  break;
-
 
932
	case CQ('F'):
-
 
933
	  { /* %F is equivalent to "%+4Y-%m-%d", flags and width can change
-
 
934
	       that.  Recurse to avoid need to replicate %Y formation. */
-
 
935
	    CHAR fmtbuf[32], *fmt = fmtbuf;
-
 
936
	    
-
 
937
	    *fmt++ = CQ('%');
-
 
938
	    if (pad) /* '0' or '+' */
-
 
939
	      *fmt++ = pad;
-
 
940
	    else
-
 
941
	      *fmt++ = '+';
-
 
942
	    if (!pad)
-
 
943
	      width = 10;
-
 
944
	    if (width < 6)
-
 
945
	      width = 6;
-
 
946
	    width -= 6;
-
 
947
	    if (width)
-
 
948
	      {
-
 
949
		len = snprintf (fmt, fmtbuf + 32 - fmt, CQ("%lu"), width);
-
 
950
		if (len > 0)
-
 
951
		  fmt += len;
-
 
952
	      }
-
 
953
	    STRCPY (fmt, CQ("Y-%m-%d"));
-
 
954
	    len = __strftime (&s[count], maxsize - count, fmtbuf, tim_p,
-
 
955
			      era_info, alt_digits);
-
 
956
	    if (len > 0)
-
 
957
	      count += len;
-
 
958
	    else
-
 
959
	      return 0;
-
 
960
	  }
-
 
961
          break;
-
 
962
	case CQ('g'):
-
 
963
	  /* Be careful of both overflow and negative years, thanks to
-
 
964
		 the asymmetric range of years.  */
-
 
965
	  {
-
 
966
	    int adjust = iso_year_adjust (tim_p);
-
 
967
	    int year = tim_p->tm_year >= 0 ? tim_p->tm_year % 100
-
 
968
		: abs (tim_p->tm_year + YEAR_BASE) % 100;
-
 
969
	    if (adjust < 0 && tim_p->tm_year <= -YEAR_BASE)
-
 
970
		adjust = 1;
-
 
971
	    else if (adjust > 0 && tim_p->tm_year < -YEAR_BASE)
-
 
972
		adjust = -1;
-
 
973
	    len = snprintf (&s[count], maxsize - count, CQ("%.2d"),
-
 
974
			    ((year + adjust) % 100 + 100) % 100);
-
 
975
            CHECK_LENGTH ();
-
 
976
	  }
-
 
977
          break;
-
 
978
	case CQ('G'):
-
 
979
	  {
-
 
980
	    /* See the comments for 'C' and 'Y'; this is a variable length
-
 
981
	       field.  Although there is no requirement for a minimum number
-
 
982
	       of digits, we use 4 for consistency with 'Y'.  */
-
 
983
	    int sign = tim_p->tm_year < -YEAR_BASE;
-
 
984
	    int adjust = iso_year_adjust (tim_p);
-
 
985
	    int century = tim_p->tm_year >= 0
-
 
986
	      ? tim_p->tm_year / 100 + YEAR_BASE / 100
-
 
987
	      : abs (tim_p->tm_year + YEAR_BASE) / 100;
-
 
988
	    int year = tim_p->tm_year >= 0 ? tim_p->tm_year % 100
-
 
989
	      : abs (tim_p->tm_year + YEAR_BASE) % 100;
-
 
990
	    if (adjust < 0 && tim_p->tm_year <= -YEAR_BASE)
-
 
991
	      sign = adjust = 1;
-
 
992
	    else if (adjust > 0 && sign)
-
 
993
	      adjust = -1;
-
 
994
	    year += adjust;
-
 
995
	    if (year == -1)
-
 
996
	      {
-
 
997
		year = 99;
-
 
998
		--century;
-
 
999
	      }
-
 
1000
	    else if (year == 100)
-
 
1001
	      {
-
 
1002
		year = 0;
-
 
1003
		++century;
-
 
1004
	      }
-
 
1005
	    CHAR fmtbuf[10], *fmt = fmtbuf;
-
 
1006
	    /* int potentially overflows, so use unsigned instead.  */
-
 
1007
	    unsigned p_year = century * 100 + year;
-
 
1008
	    if (sign)
-
 
1009
	      *fmt++ = CQ('-');
-
 
1010
	    else if (pad == CQ('+') && p_year >= 10000)
-
 
1011
	      {
-
 
1012
		*fmt++ = CQ('+');
-
 
1013
		sign = 1;
-
 
1014
	      }
-
 
1015
	    if (width && sign)
-
 
1016
	      --width;
-
 
1017
	    *fmt++ = CQ('%');
-
 
1018
	    if (pad)
-
 
1019
	      *fmt++ = CQ('0');
-
 
1020
	    STRCPY (fmt, CQ(".*u"));
-
 
1021
	    len = snprintf (&s[count], maxsize - count, fmtbuf, width, p_year);
-
 
1022
            if (len < 0  ||  (count+=len) >= maxsize)
-
 
1023
              return 0;
-
 
1024
	  }
-
 
1025
          break;
-
 
1026
	case CQ('H'):
-
 
1027
#ifdef _WANT_C99_TIME_FORMATS
-
 
1028
	  if (alt == CQ('O') && *alt_digits)
-
 
1029
	    {
-
 
1030
	      len = conv_to_alt_digits (&s[count], maxsize - count,
-
 
1031
					tim_p->tm_hour, *alt_digits);
-
 
1032
	      CHECK_LENGTH ();
-
 
1033
	      if (len > 0)
-
 
1034
		break;
-
 
1035
	    }
-
 
1036
#endif /* _WANT_C99_TIME_FORMATS */
-
 
1037
	  /*FALLTHRU*/
-
 
1038
	case CQ('k'):	/* newlib extension */
-
 
1039
	  len = snprintf (&s[count], maxsize - count,
-
 
1040
			  *format == CQ('k') ? CQ("%2d") : CQ("%.2d"),
-
 
1041
			  tim_p->tm_hour);
-
 
1042
          CHECK_LENGTH ();
-
 
1043
	  break;
-
 
1044
	case CQ('l'):	/* newlib extension */
-
 
1045
	  if (alt == CQ('O'))
-
 
1046
	    alt = CQ('\0');
-
 
1047
	  /*FALLTHRU*/
-
 
1048
	case CQ('I'):
-
 
1049
	  {
-
 
1050
	    register int  h12;
-
 
1051
	    h12 = (tim_p->tm_hour == 0 || tim_p->tm_hour == 12)  ?
-
 
1052
						12  :  tim_p->tm_hour % 12;
-
 
1053
#ifdef _WANT_C99_TIME_FORMATS
-
 
1054
	    if (alt != CQ('O') || !*alt_digits
-
 
1055
		|| !(len = conv_to_alt_digits (&s[count], maxsize - count,
-
 
1056
					       h12, *alt_digits)))
-
 
1057
#endif /* _WANT_C99_TIME_FORMATS */
-
 
1058
	      len = snprintf (&s[count], maxsize - count,
-
 
1059
			      *format == CQ('I') ? CQ("%.2d") : CQ("%2d"), h12);
-
 
1060
	    CHECK_LENGTH ();
-
 
1061
	  }
-
 
1062
	  break;
-
 
1063
	case CQ('j'):
-
 
1064
	  len = snprintf (&s[count], maxsize - count, CQ("%.3d"),
-
 
1065
			  tim_p->tm_yday + 1);
-
 
1066
          CHECK_LENGTH ();
-
 
1067
	  break;
-
 
1068
	case CQ('m'):
-
 
1069
#ifdef _WANT_C99_TIME_FORMATS
-
 
1070
	  if (alt != CQ('O') || !*alt_digits
-
 
1071
	      || !(len = conv_to_alt_digits (&s[count], maxsize - count,
-
 
1072
					     tim_p->tm_mon + 1, *alt_digits)))
-
 
1073
#endif /* _WANT_C99_TIME_FORMATS */
-
 
1074
	    len = snprintf (&s[count], maxsize - count, CQ("%.2d"),
-
 
1075
			    tim_p->tm_mon + 1);
-
 
1076
          CHECK_LENGTH ();
-
 
1077
	  break;
-
 
1078
	case CQ('M'):
-
 
1079
#ifdef _WANT_C99_TIME_FORMATS
-
 
1080
	  if (alt != CQ('O') || !*alt_digits
-
 
1081
	      || !(len = conv_to_alt_digits (&s[count], maxsize - count,
-
 
1082
					     tim_p->tm_min, *alt_digits)))
-
 
1083
#endif /* _WANT_C99_TIME_FORMATS */
-
 
1084
	    len = snprintf (&s[count], maxsize - count, CQ("%.2d"),
-
 
1085
			    tim_p->tm_min);
-
 
1086
          CHECK_LENGTH ();
-
 
1087
	  break;
-
 
1088
	case CQ('n'):
-
 
1089
	  if (count < maxsize - 1)
-
 
1090
	    s[count++] = CQ('\n');
-
 
1091
	  else
-
 
1092
	    return 0;
-
 
1093
	  break;
-
 
1094
	case CQ('p'):
-
 
1095
	case CQ('P'):
-
 
1096
	  _ctloc (am_pm[tim_p->tm_hour < 12 ? 0 : 1]);
-
 
1097
	  for (i = 0; i < ctloclen; i++)
-
 
1098
	    {
-
 
1099
	      if (count < maxsize - 1)
-
 
1100
		s[count++] = (*format == CQ('P') ? TOLOWER (ctloc[i])
-
 
1101
						 : ctloc[i]);
-
 
1102
	      else
-
 
1103
		return 0;
-
 
1104
	    }
-
 
1105
	  break;
-
 
1106
	case CQ('R'):
-
 
1107
          len = snprintf (&s[count], maxsize - count, CQ("%.2d:%.2d"),
-
 
1108
			  tim_p->tm_hour, tim_p->tm_min);
-
 
1109
          CHECK_LENGTH ();
-
 
1110
          break;
-
 
1111
	case CQ('S'):
-
 
1112
#ifdef _WANT_C99_TIME_FORMATS
-
 
1113
	  if (alt != CQ('O') || !*alt_digits
-
 
1114
	      || !(len = conv_to_alt_digits (&s[count], maxsize - count,
-
 
1115
					     tim_p->tm_sec, *alt_digits)))
-
 
1116
#endif /* _WANT_C99_TIME_FORMATS */
-
 
1117
	    len = snprintf (&s[count], maxsize - count, CQ("%.2d"),
-
 
1118
			    tim_p->tm_sec);
-
 
1119
          CHECK_LENGTH ();
-
 
1120
	  break;
-
 
1121
	case CQ('t'):
-
 
1122
	  if (count < maxsize - 1)
-
 
1123
	    s[count++] = CQ('\t');
-
 
1124
	  else
-
 
1125
  return 0;
-
 
1126
	  break;
-
 
1127
	case CQ('T'):
-
 
1128
          len = snprintf (&s[count], maxsize - count, CQ("%.2d:%.2d:%.2d"),
-
 
1129
			  tim_p->tm_hour, tim_p->tm_min, tim_p->tm_sec);
-
 
1130
          CHECK_LENGTH ();
-
 
1131
          break;
-
 
1132
	case CQ('u'):
-
 
1133
#ifdef _WANT_C99_TIME_FORMATS
-
 
1134
	  if (alt == CQ('O') && *alt_digits)
-
 
1135
	    {
-
 
1136
	      len = conv_to_alt_digits (&s[count], maxsize - count,
-
 
1137
					tim_p->tm_wday == 0 ? 7
-
 
1138
							    : tim_p->tm_wday,
-
 
1139
					*alt_digits);
-
 
1140
	      CHECK_LENGTH ();
-
 
1141
	      if (len > 0)
-
 
1142
		break;
-
 
1143
	    }
-
 
1144
#endif /* _WANT_C99_TIME_FORMATS */
-
 
1145
          if (count < maxsize - 1)
-
 
1146
            {
-
 
1147
              if (tim_p->tm_wday == 0)
-
 
1148
                s[count++] = CQ('7');
-
 
1149
              else
-
 
1150
                s[count++] = CQ('0') + tim_p->tm_wday;
-
 
1151
            }
-
 
1152
          else
-
 
1153
            return 0;
-
 
1154
          break;
-
 
1155
	case CQ('U'):
-
 
1156
#ifdef _WANT_C99_TIME_FORMATS
-
 
1157
	  if (alt != CQ('O') || !*alt_digits
-
 
1158
	      || !(len = conv_to_alt_digits (&s[count], maxsize - count,
-
 
1159
					     (tim_p->tm_yday + 7 -
-
 
1160
					      tim_p->tm_wday) / 7,
-
 
1161
					     *alt_digits)))
-
 
1162
#endif /* _WANT_C99_TIME_FORMATS */
-
 
1163
	    len = snprintf (&s[count], maxsize - count, CQ("%.2d"),
-
 
1164
			 (tim_p->tm_yday + 7 -
-
 
1165
			  tim_p->tm_wday) / 7);
-
 
1166
          CHECK_LENGTH ();
-
 
1167
	  break;
-
 
1168
	case CQ('V'):
-
 
1169
	  {
-
 
1170
	    int adjust = iso_year_adjust (tim_p);
-
 
1171
	    int wday = (tim_p->tm_wday) ? tim_p->tm_wday - 1 : 6;
-
 
1172
	    int week = (tim_p->tm_yday + 10 - wday) / 7;
-
 
1173
	    if (adjust > 0)
-
 
1174
		week = 1;
-
 
1175
	    else if (adjust < 0)
-
 
1176
		/* Previous year has 53 weeks if current year starts on
-
 
1177
		   Fri, and also if current year starts on Sat and
-
 
1178
		   previous year was leap year.  */
-
 
1179
		week = 52 + (4 >= (wday - tim_p->tm_yday
-
 
1180
				   - isleap (tim_p->tm_year
-
 
1181
					     + (YEAR_BASE - 1
-
 
1182
						- (tim_p->tm_year < 0
-
 
1183
						   ? 0 : 2000)))));
-
 
1184
#ifdef _WANT_C99_TIME_FORMATS
-
 
1185
	    if (alt != CQ('O') || !*alt_digits
-
 
1186
		|| !(len = conv_to_alt_digits (&s[count], maxsize - count,
-
 
1187
					       week, *alt_digits)))
-
 
1188
#endif /* _WANT_C99_TIME_FORMATS */
-
 
1189
	      len = snprintf (&s[count], maxsize - count, CQ("%.2d"), week);
-
 
1190
            CHECK_LENGTH ();
-
 
1191
	  }
-
 
1192
          break;
-
 
1193
	case CQ('w'):
-
 
1194
#ifdef _WANT_C99_TIME_FORMATS
-
 
1195
	  if (alt == CQ('O') && *alt_digits)
-
 
1196
	    {
-
 
1197
	      len = conv_to_alt_digits (&s[count], maxsize - count,
-
 
1198
					tim_p->tm_wday, *alt_digits);
-
 
1199
	      CHECK_LENGTH ();
-
 
1200
	      if (len > 0)
-
 
1201
		break;
-
 
1202
	    }
-
 
1203
#endif /* _WANT_C99_TIME_FORMATS */
-
 
1204
	  if (count < maxsize - 1)
-
 
1205
            s[count++] = CQ('0') + tim_p->tm_wday;
-
 
1206
	  else
-
 
1207
	    return 0;
-
 
1208
	  break;
-
 
1209
	case CQ('W'):
-
 
1210
	  {
-
 
1211
	    int wday = (tim_p->tm_wday) ? tim_p->tm_wday - 1 : 6;
-
 
1212
	    wday = (tim_p->tm_yday + 7 - wday) / 7;
-
 
1213
#ifdef _WANT_C99_TIME_FORMATS
-
 
1214
	    if (alt != CQ('O') || !*alt_digits
-
 
1215
		|| !(len = conv_to_alt_digits (&s[count], maxsize - count,
-
 
1216
					       wday, *alt_digits)))
-
 
1217
#endif /* _WANT_C99_TIME_FORMATS */
-
 
1218
	      len = snprintf (&s[count], maxsize - count, CQ("%.2d"), wday);
-
 
1219
            CHECK_LENGTH ();
-
 
1220
	  }
-
 
1221
	  break;
-
 
1222
	case CQ('y'):
-
 
1223
	    {
-
 
1224
#ifdef _WANT_C99_TIME_FORMATS
-
 
1225
	      if (alt == 'E' && *era_info)
-
 
1226
		len = snprintf (&s[count], maxsize - count, CQ("%d"),
-
 
1227
				(*era_info)->year);
-
 
1228
	      else
-
 
1229
#endif /* _WANT_C99_TIME_FORMATS */
-
 
1230
		{
-
 
1231
		  /* Be careful of both overflow and negative years, thanks to
-
 
1232
		     the asymmetric range of years.  */
-
 
1233
		  int year = tim_p->tm_year >= 0 ? tim_p->tm_year % 100
-
 
1234
			     : abs (tim_p->tm_year + YEAR_BASE) % 100;
-
 
1235
#ifdef _WANT_C99_TIME_FORMATS
-
 
1236
		  if (alt != CQ('O') || !*alt_digits
-
 
1237
		      || !(len = conv_to_alt_digits (&s[count], maxsize - count,
-
 
1238
						     year, *alt_digits)))
-
 
1239
#endif /* _WANT_C99_TIME_FORMATS */
-
 
1240
		    len = snprintf (&s[count], maxsize - count, CQ("%.2d"),
-
 
1241
				    year);
-
 
1242
		}
-
 
1243
              CHECK_LENGTH ();
-
 
1244
	    }
-
 
1245
	  break;
-
 
1246
	case CQ('Y'):
-
 
1247
#ifdef _WANT_C99_TIME_FORMATS
-
 
1248
	  if (alt == 'E' && *era_info)
-
 
1249
	    {
-
 
1250
	      ctloc = (*era_info)->era_Y;
-
 
1251
	      goto recurse;
-
 
1252
	    }
-
 
1253
	  else
-
 
1254
#endif /* _WANT_C99_TIME_FORMATS */
-
 
1255
	    {
-
 
1256
	      CHAR fmtbuf[10], *fmt = fmtbuf;
-
 
1257
	      int sign = tim_p->tm_year < -YEAR_BASE;
-
 
1258
	      /* int potentially overflows, so use unsigned instead.  */
-
 
1259
	      register unsigned year = (unsigned) tim_p->tm_year
-
 
1260
				       + (unsigned) YEAR_BASE;
-
 
1261
	      if (sign)
-
 
1262
		{
-
 
1263
		  *fmt++ = CQ('-');
-
 
1264
		  year = UINT_MAX - year + 1;
-
 
1265
		}
-
 
1266
	      else if (pad == CQ('+') && year >= 10000)
-
 
1267
		{
-
 
1268
		  *fmt++ = CQ('+');
-
 
1269
		  sign = 1;
-
 
1270
		}
-
 
1271
	      if (width && sign)
-
 
1272
		--width;
-
 
1273
	      *fmt++ = CQ('%');
-
 
1274
	      if (pad)
-
 
1275
		*fmt++ = CQ('0');
-
 
1276
	      STRCPY (fmt, CQ(".*u"));
-
 
1277
	      len = snprintf (&s[count], maxsize - count, fmtbuf, width,
-
 
1278
			      year);
-
 
1279
	      CHECK_LENGTH ();
-
 
1280
	    }
-
 
1281
	  break;
-
 
1282
	case CQ('z'):
-
 
1283
          if (tim_p->tm_isdst >= 0)
-
 
1284
            {
-
 
1285
	      long offset;
-
 
1286
	      __tzinfo_type *tz = __gettzinfo ();
-
 
1287
	      TZ_LOCK;
-
 
1288
	      /* The sign of this is exactly opposite the envvar TZ.  We
-
 
1289
	         could directly use the global _timezone for tm_isdst==0,
-
 
1290
	         but have to use __tzrule for daylight savings.  */
-
 
1291
	      offset = -tz->__tzrule[tim_p->tm_isdst > 0].offset;
-
 
1292
	      TZ_UNLOCK;
-
 
1293
	      len = snprintf (&s[count], maxsize - count, CQ("%+03ld%.2ld"),
-
 
1294
			      offset / SECSPERHOUR,
-
 
1295
			      labs (offset / SECSPERMIN) % 60L);
-
 
1296
              CHECK_LENGTH ();
-
 
1297
            }
-
 
1298
          break;
-
 
1299
	case CQ('Z'):
-
 
1300
	  if (tim_p->tm_isdst >= 0)
-
 
1301
	    {
-
 
1302
	      int size;
-
 
1303
	      TZ_LOCK;
-
 
1304
	      size = strlen(_tzname[tim_p->tm_isdst > 0]);
-
 
1305
	      for (i = 0; i < size; i++)
-
 
1306
		{
-
 
1307
		  if (count < maxsize - 1)
-
 
1308
		    s[count++] = _tzname[tim_p->tm_isdst > 0][i];
327
	_CONST struct tm *tim_p)
1309
		  else
328
{
1310
		    {
-
 
1311
		      TZ_UNLOCK;
-
 
1312
		      return 0;
-
 
1313
		    }
-
 
1314
		}
-
 
1315
	      TZ_UNLOCK;
-
 
1316
	    }
-
 
1317
	  break;
-
 
1318
	case CQ('%'):
-
 
1319
	  if (count < maxsize - 1)
-
 
1320
	    s[count++] = CQ('%');
-
 
1321
	  else
-
 
1322
	    return 0;
-
 
1323
	  break;
-
 
1324
	default:
-
 
1325
	  return 0;
-
 
1326
	}
-
 
1327
      if (*format)
-
 
1328
	format++;
-
 
1329
      else
-
 
1330
	break;
-
 
1331
    }
-
 
1332
  if (maxsize)
-
 
1333
    s[count] = CQ('\0');
-
 
1334
 
-
 
1335
  return count;
-
 
1336
}
-
 
1337
 
-
 
1338
/* The remainder of this file can serve as a regression test.  Compile
-
 
1339
 *  with -D_REGRESSION_TEST.  */
-
 
1340
#if defined(_REGRESSION_TEST)	/* [Test code:  */
-
 
1341
 
-
 
1342
/* This test code relies on ANSI C features, in particular on the ability
-
 
1343
 * of adjacent strings to be pasted together into one string.  */
-
 
1344
 
-
 
1345
/* Test output buffer size (should be larger than all expected results) */
-
 
1346
#define OUTSIZE	256
-
 
1347
 
-
 
1348
struct test {
-
 
1349
	CHAR  *fmt;	/* Testing format */
-
 
1350
	size_t  max;	/* Testing maxsize */
-
 
1351
	size_t	ret;	/* Expected return value */
-
 
1352
	CHAR  *out;	/* Expected output string */
-
 
1353
	};
-
 
1354
struct list {
-
 
1355
	const struct tm  *tms;	/* Time used for these vectors */
-
 
1356
	const struct test *vec;	/* Test vectors */
-
 
1357
	int  cnt;		/* Number of vectors */
-
 
1358
	};
-
 
1359
 
-
 
1360
const char  TZ[]="TZ=EST5EDT";
-
 
1361
 
-
 
1362
/* Define list of test inputs and expected outputs, for the given time zone
-
 
1363
 * and time.  */
-
 
1364
const struct tm  tm0 = {
-
 
1365
	/* Tue Dec 30 10:53:47 EST 2008 (time_t=1230648827) */
-
 
1366
	.tm_sec 	= 47,
-
 
1367
	.tm_min 	= 53,
-
 
1368
	.tm_hour	= 9,
-
 
1369
	.tm_mday	= 30,
-
 
1370
	.tm_mon 	= 11,
-
 
1371
	.tm_year	= 108,
-
 
1372
	.tm_wday	= 2,
-
 
1373
	.tm_yday	= 364,
-
 
1374
	.tm_isdst	= 0
-
 
1375
	};
-
 
1376
const struct test  Vec0[] = {
-
 
1377
	/* Testing fields one at a time, expecting to pass, using exact
-
 
1378
	 * allowed length as what is needed.  */
-
 
1379
	/* Using tm0 for time: */
-
 
1380
	#define EXP(s)	sizeof(s)/sizeof(CHAR)-1, s
-
 
1381
	{ CQ("%a"), 3+1, EXP(CQ("Tue")) },
-
 
1382
	{ CQ("%A"), 7+1, EXP(CQ("Tuesday")) },
-
 
1383
	{ CQ("%b"), 3+1, EXP(CQ("Dec")) },
-
 
1384
	{ CQ("%B"), 8+1, EXP(CQ("December")) },
-
 
1385
	{ CQ("%c"), 24+1, EXP(CQ("Tue Dec 30 09:53:47 2008")) },
-
 
1386
	{ CQ("%C"), 2+1, EXP(CQ("20")) },
-
 
1387
	{ CQ("%d"), 2+1, EXP(CQ("30")) },
-
 
1388
	{ CQ("%D"), 8+1, EXP(CQ("12/30/08")) },
-
 
1389
	{ CQ("%e"), 2+1, EXP(CQ("30")) },
-
 
1390
	{ CQ("%F"), 10+1, EXP(CQ("2008-12-30")) },
-
 
1391
	{ CQ("%g"), 2+1, EXP(CQ("09")) },
-
 
1392
	{ CQ("%G"), 4+1, EXP(CQ("2009")) },
-
 
1393
	{ CQ("%h"), 3+1, EXP(CQ("Dec")) },
-
 
1394
	{ CQ("%H"), 2+1, EXP(CQ("09")) },
-
 
1395
	{ CQ("%I"), 2+1, EXP(CQ("09")) },
-
 
1396
	{ CQ("%j"), 3+1, EXP(CQ("365")) },
-
 
1397
	{ CQ("%k"), 2+1, EXP(CQ(" 9")) },
-
 
1398
	{ CQ("%l"), 2+1, EXP(CQ(" 9")) },
-
 
1399
	{ CQ("%m"), 2+1, EXP(CQ("12")) },
-
 
1400
	{ CQ("%M"), 2+1, EXP(CQ("53")) },
-
 
1401
	{ CQ("%n"), 1+1, EXP(CQ("\n")) },
-
 
1402
	{ CQ("%p"), 2+1, EXP(CQ("AM")) },
-
 
1403
	{ CQ("%r"), 11+1, EXP(CQ("09:53:47 AM")) },
-
 
1404
	{ CQ("%R"), 5+1, EXP(CQ("09:53")) },
-
 
1405
	{ CQ("%S"), 2+1, EXP(CQ("47")) },
-
 
1406
	{ CQ("%t"), 1+1, EXP(CQ("\t")) },
-
 
1407
	{ CQ("%T"), 8+1, EXP(CQ("09:53:47")) },
-
 
1408
	{ CQ("%u"), 1+1, EXP(CQ("2")) },
-
 
1409
	{ CQ("%U"), 2+1, EXP(CQ("52")) },
-
 
1410
	{ CQ("%V"), 2+1, EXP(CQ("01")) },
-
 
1411
	{ CQ("%w"), 1+1, EXP(CQ("2")) },
-
 
1412
	{ CQ("%W"), 2+1, EXP(CQ("52")) },
-
 
1413
	{ CQ("%x"), 8+1, EXP(CQ("12/30/08")) },
-
 
1414
	{ CQ("%X"), 8+1, EXP(CQ("09:53:47")) },
-
 
1415
	{ CQ("%y"), 2+1, EXP(CQ("08")) },
-
 
1416
	{ CQ("%Y"), 4+1, EXP(CQ("2008")) },
-
 
1417
	{ CQ("%z"), 5+1, EXP(CQ("-0500")) },
-
 
1418
	{ CQ("%Z"), 3+1, EXP(CQ("EST")) },
-
 
1419
	{ CQ("%%"), 1+1, EXP(CQ("%")) },
-
 
1420
	#undef EXP
-
 
1421
	};
-
 
1422
/* Define list of test inputs and expected outputs, for the given time zone
-
 
1423
 * and time.  */
-
 
1424
const struct tm  tm1 = {
-
 
1425
	/* Wed Jul  2 23:01:13 EDT 2008 (time_t=1215054073) */
-
 
1426
	.tm_sec 	= 13,
-
 
1427
	.tm_min 	= 1,
-
 
1428
	.tm_hour	= 23,
-
 
1429
	.tm_mday	= 2,
-
 
1430
	.tm_mon 	= 6,
-
 
1431
	.tm_year	= 108,
-
 
1432
	.tm_wday	= 3,
-
 
1433
	.tm_yday	= 183,
-
 
1434
	.tm_isdst	= 1
-
 
1435
	};
-
 
1436
const struct test  Vec1[] = {
-
 
1437
	/* Testing fields one at a time, expecting to pass, using exact
-
 
1438
	 * allowed length as what is needed.  */
-
 
1439
	/* Using tm1 for time: */
-
 
1440
	#define EXP(s)	sizeof(s)/sizeof(CHAR)-1, s
-
 
1441
	{ CQ("%a"), 3+1, EXP(CQ("Wed")) },
-
 
1442
	{ CQ("%A"), 9+1, EXP(CQ("Wednesday")) },
-
 
1443
	{ CQ("%b"), 3+1, EXP(CQ("Jul")) },
-
 
1444
	{ CQ("%B"), 4+1, EXP(CQ("July")) },
-
 
1445
	{ CQ("%c"), 24+1, EXP(CQ("Wed Jul  2 23:01:13 2008")) },
-
 
1446
	{ CQ("%C"), 2+1, EXP(CQ("20")) },
-
 
1447
	{ CQ("%d"), 2+1, EXP(CQ("02")) },
-
 
1448
	{ CQ("%D"), 8+1, EXP(CQ("07/02/08")) },
-
 
1449
	{ CQ("%e"), 2+1, EXP(CQ(" 2")) },
-
 
1450
	{ CQ("%F"), 10+1, EXP(CQ("2008-07-02")) },
-
 
1451
	{ CQ("%g"), 2+1, EXP(CQ("08")) },
-
 
1452
	{ CQ("%G"), 4+1, EXP(CQ("2008")) },
-
 
1453
	{ CQ("%h"), 3+1, EXP(CQ("Jul")) },
-
 
1454
	{ CQ("%H"), 2+1, EXP(CQ("23")) },
-
 
1455
	{ CQ("%I"), 2+1, EXP(CQ("11")) },
-
 
1456
	{ CQ("%j"), 3+1, EXP(CQ("184")) },
-
 
1457
	{ CQ("%k"), 2+1, EXP(CQ("23")) },
-
 
1458
	{ CQ("%l"), 2+1, EXP(CQ("11")) },
-
 
1459
	{ CQ("%m"), 2+1, EXP(CQ("07")) },
-
 
1460
	{ CQ("%M"), 2+1, EXP(CQ("01")) },
-
 
1461
	{ CQ("%n"), 1+1, EXP(CQ("\n")) },
-
 
1462
	{ CQ("%p"), 2+1, EXP(CQ("PM")) },
-
 
1463
	{ CQ("%r"), 11+1, EXP(CQ("11:01:13 PM")) },
-
 
1464
	{ CQ("%R"), 5+1, EXP(CQ("23:01")) },
-
 
1465
	{ CQ("%S"), 2+1, EXP(CQ("13")) },
-
 
1466
	{ CQ("%t"), 1+1, EXP(CQ("\t")) },
-
 
1467
	{ CQ("%T"), 8+1, EXP(CQ("23:01:13")) },
-
 
1468
	{ CQ("%u"), 1+1, EXP(CQ("3")) },
-
 
1469
	{ CQ("%U"), 2+1, EXP(CQ("26")) },
-
 
1470
	{ CQ("%V"), 2+1, EXP(CQ("27")) },
-
 
1471
	{ CQ("%w"), 1+1, EXP(CQ("3")) },
-
 
1472
	{ CQ("%W"), 2+1, EXP(CQ("26")) },
-
 
1473
	{ CQ("%x"), 8+1, EXP(CQ("07/02/08")) },
-
 
1474
	{ CQ("%X"), 8+1, EXP(CQ("23:01:13")) },
-
 
1475
	{ CQ("%y"), 2+1, EXP(CQ("08")) },
-
 
1476
	{ CQ("%Y"), 4+1, EXP(CQ("2008")) },
-
 
1477
	{ CQ("%z"), 5+1, EXP(CQ("-0400")) },
-
 
1478
	{ CQ("%Z"), 3+1, EXP(CQ("EDT")) },
-
 
1479
	{ CQ("%%"), 1+1, EXP(CQ("%")) },
-
 
1480
	#undef EXP
-
 
1481
	#define VEC(s)	s, sizeof(s)/sizeof(CHAR), sizeof(s)/sizeof(CHAR)-1, s
-
 
1482
	#define EXP(s)	sizeof(s)/sizeof(CHAR), sizeof(s)/sizeof(CHAR)-1, s
-
 
1483
	{ VEC(CQ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")) },
-
 
1484
	{ CQ("0123456789%%%h:`~"), EXP(CQ("0123456789%Jul:`~")) },
-
 
1485
	{ CQ("%R%h:`~ %x %w"), EXP(CQ("23:01Jul:`~ 07/02/08 3")) },
-
 
1486
	#undef VEC
-
 
1487
	#undef EXP
-
 
1488
	};
-
 
1489
 
-
 
1490
#if YEAR_BASE == 1900  /* ( */
-
 
1491
/* Checks for very large years.  YEAR_BASE value relied upon so that the
-
 
1492
 * answer strings can be predetermined.
-
 
1493
 * Years more than 4 digits are not mentioned in the standard for %C, so the
-
 
1494
 * test for those cases are based on the design intent (which is to print the
-
 
1495
 * whole number, being the century).  */
-
 
1496
const struct tm  tmyr0 = {
-
 
1497
	/* Wed Jul  2 23:01:13 EDT [HUGE#] */
-
 
1498
	.tm_sec 	= 13,
-
 
1499
	.tm_min 	= 1,
-
 
1500
	.tm_hour	= 23,
-
 
1501
	.tm_mday	= 2,
-
 
1502
	.tm_mon 	= 6,
-
 
1503
	.tm_year	= INT_MAX - YEAR_BASE/2,
-
 
1504
	.tm_wday	= 3,
-
 
1505
	.tm_yday	= 183,
-
 
1506
	.tm_isdst	= 1
-
 
1507
	};
-
 
1508
#if INT_MAX == 32767
-
 
1509
#  define YEAR	CQ("33717")		/* INT_MAX + YEAR_BASE/2 */
-
 
1510
#  define CENT	CQ("337")
-
 
1511
#  define Year	   CQ("17")
-
 
1512
# elif INT_MAX == 2147483647
-
 
1513
#  define YEAR	CQ("2147484597")
-
 
1514
#  define CENT	CQ("21474845")
-
 
1515
#  define Year	        CQ("97")
-
 
1516
# elif INT_MAX == 9223372036854775807
-
 
1517
#  define YEAR	CQ("9223372036854776757")
-
 
1518
#  define CENT	CQ("92233720368547777")
-
 
1519
#  define Year	                 CQ("57")
-
 
1520
# else
-
 
1521
#  error "Unrecognized INT_MAX value:  enhance me to recognize what you have"
-
 
1522
#endif
-
 
1523
const struct test  Vecyr0[] = {
-
 
1524
	/* Testing fields one at a time, expecting to pass, using a larger
-
 
1525
	 * allowed length than what is needed.  */
-
 
1526
	/* Using tmyr0 for time: */
-
 
1527
	#define EXP(s)	sizeof(s)/sizeof(CHAR)-1, s
-
 
1528
	{ CQ("%C"), OUTSIZE, EXP(CENT) },
-
 
1529
	{ CQ("%c"), OUTSIZE, EXP(CQ("Wed Jul  2 23:01:13 ")YEAR) },
-
 
1530
	{ CQ("%D"), OUTSIZE, EXP(CQ("07/02/")Year) },
-
 
1531
	{ CQ("%F"), OUTSIZE, EXP(YEAR CQ("-07-02")) },
-
 
1532
	{ CQ("%x"), OUTSIZE, EXP(CQ("07/02/")Year) },
-
 
1533
	{ CQ("%y"), OUTSIZE, EXP(Year) },
-
 
1534
	{ CQ("%Y"), OUTSIZE, EXP(YEAR) },
-
 
1535
	#undef EXP
-
 
1536
	};
-
 
1537
#undef YEAR
-
 
1538
#undef CENT
-
 
1539
#undef Year
-
 
1540
/* Checks for very large negative years.  YEAR_BASE value relied upon so that
-
 
1541
 * the answer strings can be predetermined.  */
-
 
1542
const struct tm  tmyr1 = {
-
 
1543
	/* Wed Jul  2 23:01:13 EDT [HUGE#] */
-
 
1544
	.tm_sec 	= 13,
-
 
1545
	.tm_min 	= 1,
-
 
1546
	.tm_hour	= 23,
-
 
1547
	.tm_mday	= 2,
-
 
1548
	.tm_mon 	= 6,
-
 
1549
	.tm_year	= INT_MIN,
-
 
1550
	.tm_wday	= 3,
-
 
1551
	.tm_yday	= 183,
-
 
1552
	.tm_isdst	= 1
-
 
1553
	};
-
 
1554
#if INT_MAX == 32767
-
 
1555
#  define YEAR	CQ("-30868")		/* INT_MIN + YEAR_BASE */
-
 
1556
#  define CENT	CQ("-308")
-
 
1557
#  define Year	    CQ("68")
-
 
1558
# elif INT_MAX == 2147483647
-
 
1559
#  define YEAR	CQ("-2147481748")
-
 
1560
#  define CENT	CQ("-21474817")
-
 
1561
#  define Year	         CQ("48")
-
 
1562
# elif INT_MAX == 9223372036854775807
-
 
1563
#  define YEAR	CQ("-9223372036854773908")
-
 
1564
#  define CENT	CQ("-92233720368547739")
-
 
1565
#  define Year	                  CQ("08")
-
 
1566
# else
-
 
1567
#  error "Unrecognized INT_MAX value:  enhance me to recognize what you have"
-
 
1568
#endif
-
 
1569
const struct test  Vecyr1[] = {
-
 
1570
	/* Testing fields one at a time, expecting to pass, using a larger
-
 
1571
	 * allowed length than what is needed.  */
-
 
1572
	/* Using tmyr1 for time: */
-
 
1573
	#define EXP(s)	sizeof(s)/sizeof(CHAR)-1, s
-
 
1574
	{ CQ("%C"), OUTSIZE, EXP(CENT) },
-
 
1575
	{ CQ("%c"), OUTSIZE, EXP(CQ("Wed Jul  2 23:01:13 ")YEAR) },
-
 
1576
	{ CQ("%D"), OUTSIZE, EXP(CQ("07/02/")Year) },
-
 
1577
	{ CQ("%F"), OUTSIZE, EXP(YEAR CQ("-07-02")) },
-
 
1578
	{ CQ("%x"), OUTSIZE, EXP(CQ("07/02/")Year) },
-
 
1579
	{ CQ("%y"), OUTSIZE, EXP(Year) },
-
 
1580
	{ CQ("%Y"), OUTSIZE, EXP(YEAR) },
-
 
1581
	#undef EXP
-
 
1582
	};
-
 
1583
#undef YEAR
-
 
1584
#undef CENT
-
 
1585
#undef Year
-
 
1586
#endif /* YEAR_BASE ) */
-
 
1587
 
-
 
1588
/* Checks for years just over zero (also test for s=60).
-
 
1589
 * Years less than 4 digits are not mentioned for %Y in the standard, so the
-
 
1590
 * test for that case is based on the design intent.  */
-
 
1591
const struct tm  tmyrzp = {
-
 
1592
	/* Wed Jul  2 23:01:60 EDT 0007 */
-
 
1593
	.tm_sec 	= 60,
-
 
1594
	.tm_min 	= 1,
-
 
1595
	.tm_hour	= 23,
-
 
1596
	.tm_mday	= 2,
-
 
1597
	.tm_mon 	= 6,
-
 
1598
	.tm_year	= 7-YEAR_BASE,
-
 
1599
	.tm_wday	= 3,
-
 
1600
	.tm_yday	= 183,
-
 
1601
	.tm_isdst	= 1
-
 
1602
	};
-
 
1603
#define YEAR	CQ("0007")	/* Design intent:  %Y=%C%y */
-
 
1604
#define CENT	CQ("00")
-
 
1605
#define Year	  CQ("07")
-
 
1606
const struct test  Vecyrzp[] = {
-
 
1607
	/* Testing fields one at a time, expecting to pass, using a larger
-
 
1608
	 * allowed length than what is needed.  */
-
 
1609
	/* Using tmyrzp for time: */
-
 
1610
	#define EXP(s)	sizeof(s)/sizeof(CHAR)-1, s
-
 
1611
	{ CQ("%C"), OUTSIZE, EXP(CENT) },
-
 
1612
	{ CQ("%c"), OUTSIZE, EXP(CQ("Wed Jul  2 23:01:60 ")YEAR) },
-
 
1613
	{ CQ("%D"), OUTSIZE, EXP(CQ("07/02/")Year) },
-
 
1614
	{ CQ("%F"), OUTSIZE, EXP(YEAR CQ("-07-02")) },
-
 
1615
	{ CQ("%x"), OUTSIZE, EXP(CQ("07/02/")Year) },
-
 
1616
	{ CQ("%y"), OUTSIZE, EXP(Year) },
-
 
1617
	{ CQ("%Y"), OUTSIZE, EXP(YEAR) },
-
 
1618
	#undef EXP
-
 
1619
	};
-
 
1620
#undef YEAR
-
 
1621
#undef CENT
-
 
1622
#undef Year
-
 
1623
/* Checks for years just under zero.
-
 
1624
 * Negative years are not handled by the standard, so the vectors here are
-
 
1625
 * verifying the chosen implemtation.  */
-
 
1626
const struct tm  tmyrzn = {
-
 
1627
	/* Wed Jul  2 23:01:00 EDT -004 */
-
 
1628
	.tm_sec 	= 00,
-
 
1629
	.tm_min 	= 1,
-
 
1630
	.tm_hour	= 23,
-
 
1631
	.tm_mday	= 2,
-
 
1632
	.tm_mon 	= 6,
-
 
1633
	.tm_year	= -4-YEAR_BASE,
-
 
1634
	.tm_wday	= 3,
-
 
1635
	.tm_yday	= 183,
-
 
1636
	.tm_isdst	= 1
-
 
1637
	};
-
 
1638
#define YEAR	CQ("-004")
-
 
1639
#define CENT	CQ("-0")
-
 
1640
#define Year	  CQ("04")
-
 
1641
const struct test  Vecyrzn[] = {
-
 
1642
	/* Testing fields one at a time, expecting to pass, using a larger
-
 
1643
	 * allowed length than what is needed.  */
-
 
1644
	/* Using tmyrzn for time: */
-
 
1645
	#define EXP(s)	sizeof(s)/sizeof(CHAR)-1, s
-
 
1646
	{ CQ("%C"), OUTSIZE, EXP(CENT) },
-
 
1647
	{ CQ("%c"), OUTSIZE, EXP(CQ("Wed Jul  2 23:01:00 ")YEAR) },
-
 
1648
	{ CQ("%D"), OUTSIZE, EXP(CQ("07/02/")Year) },
-
 
1649
	{ CQ("%F"), OUTSIZE, EXP(YEAR CQ("-07-02")) },
-
 
1650
	{ CQ("%x"), OUTSIZE, EXP(CQ("07/02/")Year) },
-
 
1651
	{ CQ("%y"), OUTSIZE, EXP(Year) },
-
 
1652
	{ CQ("%Y"), OUTSIZE, EXP(YEAR) },
-
 
1653
	#undef EXP
-
 
1654
	};
-
 
1655
#undef YEAR
-
 
1656
#undef CENT
-
 
1657
#undef Year
-
 
1658
 
-
 
1659
const struct list  ListYr[] = {
-
 
1660
	{ &tmyrzp, Vecyrzp, sizeof(Vecyrzp)/sizeof(Vecyrzp[0]) },
-
 
1661
	{ &tmyrzn, Vecyrzn, sizeof(Vecyrzn)/sizeof(Vecyrzn[0]) },
-
 
1662
	#if YEAR_BASE == 1900
-
 
1663
	{ &tmyr0, Vecyr0, sizeof(Vecyr0)/sizeof(Vecyr0[0]) },
-
 
1664
	{ &tmyr1, Vecyr1, sizeof(Vecyr1)/sizeof(Vecyr1[0]) },
-
 
1665
	#endif
-
 
1666
	};
-
 
1667
 
-
 
1668
 
-
 
1669
/* List of tests to be run */
-
 
1670
const struct list  List[] = {
-
 
1671
	{ &tm0, Vec0, sizeof(Vec0)/sizeof(Vec0[0]) },
-
 
1672
	{ &tm1, Vec1, sizeof(Vec1)/sizeof(Vec1[0]) },
-
 
1673
	};
-
 
1674
 
-
 
1675
#if defined(STUB_getenv_r)
-
 
1676
char *
-
 
1677
_getenv_r(struct _reent *p, const char *cp) { return getenv(cp); }
-
 
1678
#endif
-
 
1679
 
-
 
1680
int
-
 
1681
main(void)
-
 
1682
{
-
 
1683
int  i, l, errr=0, erro=0, tot=0;
-
 
1684
const char  *cp;
-
 
1685
CHAR  out[OUTSIZE];
-
 
1686
size_t  ret;
-
 
1687
 
-
 
1688
/* Set timezone so that %z and %Z tests come out right */
-
 
1689
cp = TZ;
-
 
1690
if((i=putenv(cp)))  {
-
 
1691
    printf( "putenv(%s) FAILED, ret %d\n", cp, i);
-
 
1692
    return(-1);
-
 
1693
    }
-
 
1694
if(strcmp(getenv("TZ"),strchr(TZ,'=')+1))  {
-
 
1695
    printf( "TZ not set properly in environment\n");
-
 
1696
    return(-2);
-
 
1697
    }
-
 
1698
tzset();
-
 
1699
 
-
 
1700
#if defined(VERBOSE)
-
 
1701
printf("_timezone=%d, _daylight=%d, _tzname[0]=%s, _tzname[1]=%s\n", _timezone, _daylight, _tzname[0], _tzname[1]);
-
 
1702
{
-
 
1703
long offset;
-
 
1704
__tzinfo_type *tz = __gettzinfo ();
-
 
1705
/* The sign of this is exactly opposite the envvar TZ.  We
-
 
1706
   could directly use the global _timezone for tm_isdst==0,
-
 
1707
   but have to use __tzrule for daylight savings.  */
-
 
1708
printf("tz->__tzrule[0].offset=%d, tz->__tzrule[1].offset=%d\n", tz->__tzrule[0].offset, tz->__tzrule[1].offset);
-
 
1709
}
-
 
1710
#endif
-
 
1711
 
-
 
1712
/* Run all of the exact-length tests as-given--results should match */
-
 
1713
for(l=0; l
-
 
1714
    const struct list  *test = &List[l];
-
 
1715
    for(i=0; icnt; i++)  {
-
 
1716
	tot++;	/* Keep track of number of tests */
-
 
1717
	ret = strftime(out, test->vec[i].max, test->vec[i].fmt, test->tms);
-
 
1718
	if(ret != test->vec[i].ret)  {
-
 
1719
	    errr++;
-
 
1720
	    fprintf(stderr,
-
 
1721
		"ERROR:  return %d != %d expected for List[%d].vec[%d]\n",
-
 
1722
						ret, test->vec[i].ret, l, i);
-
 
1723
	    }
-
 
1724
	if(strncmp(out, test->vec[i].out, test->vec[i].max-1))  {
-
 
1725
	    erro++;
-
 
1726
	    fprintf(stderr,
-
 
1727
		"ERROR:  \"%"SFLG"s\" != \"%"SFLG"s\" expected for List[%d].vec[%d]\n",
-
 
1728
						out, test->vec[i].out, l, i);
-
 
1729
	    }
-
 
1730
	}
-
 
1731
    }
-
 
1732
 
-
 
1733
/* Run all of the exact-length tests with the length made too short--expect to
-
 
1734
 * fail.  */
-
 
1735
for(l=0; l
-
 
1736
    const struct list  *test = &List[l];
-
 
1737
    for(i=0; icnt; i++)  {
-
 
1738
	tot++;	/* Keep track of number of tests */
-
 
1739
	ret = strftime(out, test->vec[i].max-1, test->vec[i].fmt, test->tms);
-
 
1740
	if(ret != 0)  {
-
 
1741
	    errr++;
-
 
1742
	    fprintf(stderr,
-
 
1743
		"ERROR:  return %d != %d expected for List[%d].vec[%d]\n",
-
 
1744
						ret, 0, l, i);
-
 
1745
	    }
-
 
1746
	/* Almost every conversion puts out as many characters as possible, so
-
 
1747
	 * go ahead and test the output even though have failed.  (The test
-
 
1748
	 * times chosen happen to not hit any of the cases that fail this, so it
-
 
1749
	 * works.)  */
-
 
1750
	if(strncmp(out, test->vec[i].out, test->vec[i].max-1-1))  {
-
 
1751
	    erro++;
-
 
1752
	    fprintf(stderr,
-
 
1753
		"ERROR:  \"%"SFLG"s\" != \"%"SFLG"s\" expected for List[%d].vec[%d]\n",
-
 
1754
						out, test->vec[i].out, l, i);
Line -... Line 1755...
-
 
1755
	    }
-
 
1756
	}
-
 
1757
    }
-
 
1758
 
-
 
1759
/* Run all of the special year test cases */
-
 
1760
for(l=0; l
-
 
1761
    const struct list  *test = &ListYr[l];
-
 
1762
    for(i=0; icnt; i++)  {
-
 
1763
	tot++;	/* Keep track of number of tests */
-
 
1764
	ret = strftime(out, test->vec[i].max, test->vec[i].fmt, test->tms);
-
 
1765
	if(ret != test->vec[i].ret)  {
-
 
1766
	    errr++;
-
 
1767
	    fprintf(stderr,
-
 
1768
		"ERROR:  return %d != %d expected for ListYr[%d].vec[%d]\n",
-
 
1769
						ret, test->vec[i].ret, l, i);
-
 
1770
	    }
-
 
1771
	if(strncmp(out, test->vec[i].out, test->vec[i].max-1))  {
-
 
1772
	    erro++;
-
 
1773
	    fprintf(stderr,
-
 
1774
		"ERROR:  \"%"SFLG"s\" != \"%"SFLG"s\" expected for ListYr[%d].vec[%d]\n",
-
 
1775
						out, test->vec[i].out, l, i);
-
 
1776
	    }
-
 
1777
	}
-
 
1778
    }
-
 
1779
 
-
 
1780
#define STRIZE(f)	#f
-
 
1781
#define NAME(f)	STRIZE(f)
Line -... Line 1782...
-
 
1782
printf(NAME(strftime) "() test ");
-
 
1783
if(errr || erro)  printf("FAILED %d/%d of", errr, erro);
-
 
1784
  else    printf("passed");