View | Details | Raw Unified | Return to bug 10871 | Differences between
and this patch

Collapse All | Expand All

(-)a/time/strftime_l.c (-1 / +154 lines)
Lines 72-77 extern char *tzname[]; Link Here
72
#  define mbstate_t int
72
#  define mbstate_t int
73
#  define mbrlen(s, n, ps) mblen (s, n)
73
#  define mbrlen(s, n, ps) mblen (s, n)
74
#  define mbsinit(ps) (*(ps) == 0)
74
#  define mbsinit(ps) (*(ps) == 0)
75
#  define mbrtowc(pwc, s, n, ps) mbtowc (pwc, s, n)
75
# endif
76
# endif
76
  static const mbstate_t mbstate_zero;
77
  static const mbstate_t mbstate_zero;
77
#endif
78
#endif
Lines 432-437 static CHAR_T const month_name[][10] = Link Here
432
# define ut 0
433
# define ut 0
433
#endif
434
#endif
434
435
436
/* Check if the characters pointed to by S are a valid suffix: if they
437
   start with a valid letter (in the current locale) or a single
438
   punctuation character (a dash, an apostrophe, etc.) followed by
439
   a letter, and they are not a format specifier. If a suffix is appended
440
   at the end of a month name then probably a caller already tries to
441
   workaround the problem of missing genitive forms so we should not
442
   interfere with that.  */
443
static bool is_suffix (const CHAR_T *s)
444
{
445
#if defined COMPILE_WIDE || DO_MULTIBYTE
446
# define ISALPHA iswalpha
447
# define ISPUNCT iswpunct
448
#else
449
# define ISALPHA isalpha
450
# define ISPUNCT ispunct
451
#endif
452
453
#if DO_MULTIBYTE && !defined COMPILE_WIDE
454
  wchar_t c, next_char;
455
  size_t mb_char_len, mb_next_char_len;
456
  mbstate_t mbstate = mbstate_zero;
457
458
  mb_char_len = mbrtowc (&c, s, strlen (s), &mbstate);
459
  if ((ssize_t) mb_char_len <= 0)
460
    c = L_('\0');
461
462
  if (c == L_('\0'))
463
    {
464
      next_char = L_('\0');
465
      mb_next_char_len = 0;
466
    }
467
  else
468
    {
469
      mbsinit (&mbstate);
470
      mb_next_char_len = mbrtowc (&next_char, s + mb_char_len,
471
				  strlen (s + mb_char_len), &mbstate);
472
      if ((ssize_t) mb_next_char_len <= 0)
473
        next_char = L_('\0');
474
    }
475
# define NEXT_CHAR_OFFSET mb_char_len
476
# define NEXT_NEXT_CHAR_OFFSET (mb_char_len + mb_next_char_len)
477
#else
478
  const CHAR_T c = s[0];
479
  const CHAR_T next_char = c == L_('\0') ? L_('\0') : s[1];
480
# define NEXT_CHAR_OFFSET 1
481
# define NEXT_NEXT_CHAR_OFFSET 2
482
#endif
483
484
  if (ISALPHA (c))
485
    return true;
486
487
  if (c == L_('%'))
488
    {
489
      if (next_char == L_('%'))
490
	return is_suffix (s + NEXT_NEXT_CHAR_OFFSET);
491
      else
492
	return false;
493
    }
494
495
  if (ISPUNCT (c))
496
    return is_suffix (s + NEXT_CHAR_OFFSET);
497
498
  return false;
499
}
500
501
/* Checks if the nearest format specifier in the format string pointed
502
   to by Sis a day of the month specifier: "%e" or "%d". The format
503
   specifier may be preceded with any number of other characters and may
504
   contain modifiers. This function does not check if the modifiers are
505
   valid and actually produce the day number so the result may be sometimes
506
   wrong but in these cases the output will be wrong anyway because the
507
   format is wrong.  */
508
static bool next_is_day (const CHAR_T *s)
509
{
510
  /* Skip until the percent sign is found.  */
511
  while (1)
512
    {
513
      switch (*s++)
514
	{
515
	case L_('\0'):
516
	    return false;
517
	case L_('%'):
518
	    if (*s == L_('%'))
519
	      {
520
		++s;
521
		continue;
522
	      }
523
	    break;
524
	default:
525
	    continue;
526
	}
527
      break;
528
    }
529
530
  while (1)
531
    {
532
      switch (*s++)
533
	{
534
	/* Skip the modifiers. Here we don't check if they are valid.  */
535
	case L_('_'):
536
	case L_('-'):
537
	case L_('^'):
538
	case L_('#'):
539
	case L_('E'): case L_('O'):
540
	case L_('0'): case L_('1'): case L_('2'): case L_('3'): case L_('4'):
541
	case L_('5'): case L_('6'): case L_('7'): case L_('8'): case L_('9'):
542
	    continue;
543
544
	/* Day found.  */
545
	case L_('d'): case L_('e'):
546
	    return true;
547
548
	/* Something else found, including the terminating zero.  */
549
	default:
550
	    return false;
551
	}
552
    }
553
}
554
435
static size_t __strftime_internal (CHAR_T *, size_t, const CHAR_T *,
555
static size_t __strftime_internal (CHAR_T *, size_t, const CHAR_T *,
436
				   const struct tm *, bool *
556
				   const struct tm *, bool *
437
				   ut_argument_spec
557
				   ut_argument_spec
Lines 492-497 __strftime_internal (CHAR_T *s, size_t maxsize, const CHAR_T *format, Link Here
492
# define f_month \
612
# define f_month \
493
  ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11			     \
613
  ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11			     \
494
		     ? "?" : _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon)))
614
		     ? "?" : _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon)))
615
# define f_altmonth \
616
  ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11			     \
617
		     ? "?" : _NL_CURRENT (LC_TIME, NLW(ALTMON_1) + tp->tm_mon)))
495
# define ampm \
618
# define ampm \
496
  ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11		      \
619
  ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11		      \
497
				 ? NLW(PM_STR) : NLW(AM_STR)))
620
				 ? NLW(PM_STR) : NLW(AM_STR)))
Lines 499-504 __strftime_internal (CHAR_T *s, size_t maxsize, const CHAR_T *format, Link Here
499
# define aw_len STRLEN (a_wkday)
622
# define aw_len STRLEN (a_wkday)
500
# define am_len STRLEN (a_month)
623
# define am_len STRLEN (a_month)
501
# define ap_len STRLEN (ampm)
624
# define ap_len STRLEN (ampm)
625
# define day_month_order \
626
  (current->values[_NL_ITEM_INDEX (_NL_DAY_MONTH_ORDER)].string[0])
502
#else
627
#else
503
# if !HAVE_STRFTIME
628
# if !HAVE_STRFTIME
504
#  define f_wkday (tp->tm_wday < 0 || tp->tm_wday > 6	\
629
#  define f_wkday (tp->tm_wday < 0 || tp->tm_wday > 6	\
Lines 507-519 __strftime_internal (CHAR_T *s, size_t maxsize, const CHAR_T *format, Link Here
507
		   ? "?" : month_name[tp->tm_mon])
632
		   ? "?" : month_name[tp->tm_mon])
508
#  define a_wkday f_wkday
633
#  define a_wkday f_wkday
509
#  define a_month f_month
634
#  define a_month f_month
635
#  define f_altmonth (L_(""))
510
#  define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11))
636
#  define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11))
511
637
512
  size_t aw_len = 3;
638
  size_t aw_len = 3;
513
  size_t am_len = 3;
639
  size_t am_len = 3;
514
  size_t ap_len = 2;
640
  size_t ap_len = 2;
641
# define day_month_order 2
515
# endif
642
# endif
516
#endif
643
#endif
644
  int last_was_day = 0;
517
  const char *zone;
645
  const char *zone;
518
  size_t i = 0;
646
  size_t i = 0;
519
  CHAR_T *p = s;
647
  CHAR_T *p = s;
Lines 783-789 __strftime_internal (CHAR_T *s, size_t maxsize, const CHAR_T *format, Link Here
783
	      to_lowcase = 0;
911
	      to_lowcase = 0;
784
	    }
912
	    }
785
#if defined _NL_CURRENT || !HAVE_STRFTIME
913
#if defined _NL_CURRENT || !HAVE_STRFTIME
786
	  cpy (STRLEN (f_month), f_month);
914
	  /* Use f_altmonth only if f_altmonth is provided.  */
915
	  if (f_altmonth[0]
916
	  /* Don't use f_altmonth if there is a suffix after %B because
917
	     it means that a caller already provides its own workaround.  */
918
	      && !is_suffix (f + 1)
919
	  /* Use f_altmonth if the day-month order is valid and the last
920
	     format specifier was a day specifier.  */
921
	      && ( (day_month_order <= 2 && last_was_day)
922
	  /* Use f_altmonth if the month-day order is valid and the next
923
	     format specifier will be a day specifier.  */
924
		  || (day_month_order >= 2 && next_is_day (f + 1)) ))
925
	    cpy (STRLEN (f_altmonth), f_altmonth);
926
	  else
927
	    cpy (STRLEN (f_month), f_month);
787
	  break;
928
	  break;
788
#else
929
#else
789
	  goto underlying_strftime;
930
	  goto underlying_strftime;
Lines 1400-1405 __strftime_internal (CHAR_T *s, size_t maxsize, const CHAR_T *format, Link Here
1400
	  }
1541
	  }
1401
	  break;
1542
	  break;
1402
	}
1543
	}
1544
1545
      /* Update the previous_was_day flag. */
1546
      switch (format_char)
1547
	{
1548
	case L_('d'):
1549
	case L_('e'):
1550
	  last_was_day = 1;
1551
	  break;
1552
	default:
1553
	  last_was_day = 0;
1554
	  break;
1555
	}
1403
    }
1556
    }
1404
1557
1405
  if (p && maxsize != 0)
1558
  if (p && maxsize != 0)
(-)a/time/strptime_l.c (-1 / +25 lines)
Lines 124-129 extern const struct __locale_data _nl_C_LC_TIME attribute_hidden; Link Here
124
  (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABDAY_1)].string)
124
  (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABDAY_1)].string)
125
# define month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (MON_1)].string)
125
# define month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (MON_1)].string)
126
# define ab_month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABMON_1)].string)
126
# define ab_month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABMON_1)].string)
127
# define alt_month_name \
128
  (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ALTMON_1)].string)
127
# define HERE_D_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_T_FMT)].string)
129
# define HERE_D_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_T_FMT)].string)
128
# define HERE_D_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_FMT)].string)
130
# define HERE_D_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_FMT)].string)
129
# define HERE_AM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (AM_STR)].string)
131
# define HERE_AM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (AM_STR)].string)
Lines 153-158 static char const ab_month_name[][4] = Link Here
153
    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
155
    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
154
    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
156
    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
155
  };
157
  };
158
static char const alt_month_name[][10] =
159
  {
160
    "January", "February", "March", "April", "May", "June",
161
    "July", "August", "September", "October", "November", "December"
162
  };
156
# define HERE_D_T_FMT "%a %b %e %H:%M:%S %Y"
163
# define HERE_D_T_FMT "%a %b %e %H:%M:%S %Y"
157
# define HERE_D_FMT "%m/%d/%y"
164
# define HERE_D_FMT "%m/%d/%y"
158
# define HERE_AM_STR "AM"
165
# define HERE_AM_STR "AM"
Lines 403-408 __strptime_internal (const char *rp, const char *fmt, struct tm *tmp, Link Here
403
	      if (s.decided !=raw)
410
	      if (s.decided !=raw)
404
		{
411
		{
405
		  trp = rp;
412
		  trp = rp;
413
		  /* First check if the alt month is provided.  */
414
		  if (_NL_CURRENT (LC_TIME, ALTMON_1 + cnt)
415
		      && * (_NL_CURRENT (LC_TIME, ALTMON_1 + cnt))
416
		      && match_string (_NL_CURRENT (LC_TIME, ALTMON_1 + cnt), trp)
417
		      && trp > rp_longest)
418
		    {
419
		      rp_longest = trp;
420
		      cnt_longest = cnt;
421
		      if (s.decided == not
422
			  && strcmp (_NL_CURRENT (LC_TIME, ALTMON_1 + cnt),
423
				     alt_month_name[cnt]))
424
			decided_longest = loc;
425
		    }
426
		  trp = rp;
406
		  if (match_string (_NL_CURRENT (LC_TIME, MON_1 + cnt), trp)
427
		  if (match_string (_NL_CURRENT (LC_TIME, MON_1 + cnt), trp)
407
		      && trp > rp_longest)
428
		      && trp > rp_longest)
408
		    {
429
		    {
Lines 429-434 __strptime_internal (const char *rp, const char *fmt, struct tm *tmp, Link Here
429
	      if (s.decided != loc
450
	      if (s.decided != loc
430
		  && (((trp = rp, match_string (month_name[cnt], trp))
451
		  && (((trp = rp, match_string (month_name[cnt], trp))
431
		       && trp > rp_longest)
452
		       && trp > rp_longest)
453
		      || ((trp = rp, alt_month_name[cnt]
454
			  && alt_month_name[cnt][0]
455
			  && match_string (alt_month_name[cnt], trp))
456
			  && trp > rp_longest)
432
		      || ((trp = rp, match_string (ab_month_name[cnt], trp))
457
		      || ((trp = rp, match_string (ab_month_name[cnt], trp))
433
			  && trp > rp_longest)))
458
			  && trp > rp_longest)))
434
		{
459
		{
435
- 

Return to bug 10871