emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: problem report #102


From: Dan Nicolaescu
Subject: Re: problem report #102
Date: Mon, 1 Dec 2008 10:34:46 -0800 (PST)

Andreas Schwab <address@hidden> writes:

  > Dan Nicolaescu <address@hidden> writes:
  > 
  > > Event negative_returns: Negative constant "-1" was passed to a negative 
sink. [model]
  > 
  > What's a "negative sink"??

Thanks for looking at these.

negative_sink: The checker reports this event when it determines that a value 
is used in an operation that would have a bad effect if that value were 
negative. The checker then tracks the value used to see if it is subsequently 
compared against a negative value.


[model] are links to other pages with further explanations for the
checker's action. Following those links:

At conditional (1): "s != 0" taking true path

1605          if (s)
1606            s[0] = '\1';
1607    

Event neg_sink_parm_call: Parameter "maxsize" passed to negative sink 
"emacs_strftimeu" [model]

1608          result = emacs_strftimeu (s, maxsize, format, tp, ut);
1609    


1484    size_t
1485    emacs_strftimeu (s, maxsize, format, tp, ut)
1486          char *s;
1487          size_t maxsize;
1488          const char *format;
1489          const struct tm *tp;
1490          int ut;
1491    {

Event neg_sink_parm_call: Parameter "maxsize" passed to negative sink 
"nstrftime" [model]

1492      return my_strftime (s, maxsize, format, tp, ut, 0);
1493    }
1494    #endif

521     /* Write information from TP into S according to the format
522        string FORMAT, writing no more that MAXSIZE characters
523        (including the terminating '\0') and returning number of
524        characters written.  If S is NULL, nothing will be written
525        anywhere, so to determine how many characters would be
526        written, use NULL for S and (size_t) UINT_MAX for MAXSIZE.  */
527     size_t
528     my_strftime (s, maxsize, format, tp extra_args LOCALE_PARAM)
529           CHAR_T *s;

Event sizet: size_t parameter "maxsize" detected

530           size_t maxsize;
531           const CHAR_T *format;
532           const struct tm *tp;
533           extra_args_spec
534           LOCALE_PARAM_DECL
535     {
536     #if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
537       struct locale_data *const current = loc->__locales[LC_TIME];
538     #endif
539     
540       int hour12 = tp->tm_hour;
541     #ifdef _NL_CURRENT
542       /* We cannot make the following values variables since we must delay
543          the evaluation of these values until really needed since some
544          expressions might not be valid in every situation.  The `struct tm'
545          might be generated by a strptime() call that initialized
546          only a few elements.  Dereference the pointers only if the format
547          requires this.  Then it is ok to fail if the pointers are invalid. 
 */
548     # define a_wkday \
549       ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday))
550     # define f_wkday \
551       ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday))
552     # define a_month \
553       ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon))
554     # define f_month \
555       ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon))
556     # define ampm \
557       ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11              
      \
558                                      ? NLW(PM_STR) : NLW(AM_STR)))
559     
560     # define aw_len STRLEN (a_wkday)
561     # define am_len STRLEN (a_month)
562     # define ap_len STRLEN (ampm)
563     #else
564     # if !HAVE_STRFTIME
565     #  define f_wkday (weekday_name[tp->tm_wday])
566     #  define f_month (month_name[tp->tm_mon])
567     #  define a_wkday f_wkday
568     #  define a_month f_month
569     #  define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11))
570     
571       size_t aw_len = 3;
572       size_t am_len = 3;
573       size_t ap_len = 2;
574     # endif
575     #endif
576       const char *zone;
577       size_t i = 0;
578       CHAR_T *p = s;
579       const CHAR_T *f;
580     #if DO_MULTIBYTE && !defined COMPILE_WIDE
581       const char *format_end = NULL;
582     #endif
583     
584       zone = NULL;
585     #if HAVE_TM_ZONE
586       /* The POSIX test suite assumes that setting
587          the environment variable TZ to a new value before calling 
strftime()
588          will influence the result (the %Z format) even if the information 
in
589          TP is computed with a totally different time zone.
590          This is bogus: though POSIX allows bad behavior like this,
591          POSIX does not require it.  Do the right thing instead.  */
592       zone = (const char *) tp->tm_zone;
593     #endif
594     #if HAVE_TZNAME
595       if (ut)
596         {
597           if (! (zone && *zone))
598             zone = "GMT";
599         }
600       else
601         {
602           /* POSIX.1 requires that local time zone information be used as
603              though strftime called tzset.  */
604     # if HAVE_TZSET
605           tzset ();
606     # endif
607         }
608     #endif
609     
610       if (hour12 > 12)
611         hour12 -= 12;
612       else
613         if (hour12 == 0)
614           hour12 = 12;
615     
616       for (f = format; *f != '\0'; ++f)
617         {
618           int pad = 0;              /* Padding for number ('-', '_', or 0). 
 */
619           int modifier;             /* Field modifier ('E', 'O', or 0).  */
620           int digits;               /* Max digits for numeric format.  */
621           int number_value;         /* Numeric value to be printed.  */
622           int negative_number;      /* 1 if the number is negative.  */
623           const CHAR_T *subfmt;
624           CHAR_T *bufp;
625           CHAR_T buf[1 + (sizeof (int) < sizeof (time_t)
626                           ? INT_STRLEN_BOUND (time_t)
627                           : INT_STRLEN_BOUND (int))];
628           int width = -1;
629           int to_lowcase = 0;
630           int to_uppcase = 0;
631           int change_case = 0;
632           int format_char;
633     
634     #if DO_MULTIBYTE && !defined COMPILE_WIDE
635           switch (*f)
636             {
637             case L_('%'):
638               break;
639     
640             case L_('\b'): case L_('\t'): case L_('\n'):
641             case L_('\v'): case L_('\f'): case L_('\r'):
642             case L_(' '): case L_('!'): case L_('"'): case L_('#'): case 
L_('&'):
643             case L_('\''): case L_('('): case L_(')'): case L_('*'): case 
L_('+'):
644             case L_(','): case L_('-'): case L_('.'): case L_('/'): case 
L_('0'):
645             case L_('1'): case L_('2'): case L_('3'): case L_('4'): case 
L_('5'):
646             case L_('6'): case L_('7'): case L_('8'): case L_('9'): case 
L_(':'):
647             case L_(';'): case L_('<'): case L_('='): case L_('>'): case 
L_('?'):
648             case L_('A'): case L_('B'): case L_('C'): case L_('D'): case 
L_('E'):
649             case L_('F'): case L_('G'): case L_('H'): case L_('I'): case 
L_('J'):
650             case L_('K'): case L_('L'): case L_('M'): case L_('N'): case 
L_('O'):
651             case L_('P'): case L_('Q'): case L_('R'): case L_('S'): case 
L_('T'):
652             case L_('U'): case L_('V'): case L_('W'): case L_('X'): case 
L_('Y'):
653             case L_('Z'): case L_('['): case L_('\\'): case L_(']'): case 
L_('^'):
654             case L_('_'): case L_('a'): case L_('b'): case L_('c'): case 
L_('d'):
655             case L_('e'): case L_('f'): case L_('g'): case L_('h'): case 
L_('i'):
656             case L_('j'): case L_('k'): case L_('l'): case L_('m'): case 
L_('n'):
657             case L_('o'): case L_('p'): case L_('q'): case L_('r'): case 
L_('s'):
658             case L_('t'): case L_('u'): case L_('v'): case L_('w'): case 
L_('x'):
659             case L_('y'): case L_('z'): case L_('{'): case L_('|'): case 
L_('}'):
660             case L_('~'):
661               /* The C Standard requires these 98 characters (plus '%') to
662                  be in the basic execution character set.  None of these
663                  characters can start a multibyte sequence, so they need
664                  not be analyzed further.  */
665               add (1, *p = *f);
666               continue;
667     
668             default:
669               /* Copy this multibyte sequence until we reach its end, find
670                  an error, or come back to the initial shift state.  */
671               {
672                 mbstate_t mbstate = mbstate_zero;
673                 size_t len = 0;
674                 size_t fsize;
675     
676                 if (! format_end)
677                   format_end = f + strlen (f) + 1;
678                 fsize = format_end - f;
679     
680                 do
681                   {
682                     size_t bytes = mbrlen (f + len, fsize - len, &mbstate);
683     
684                     if (bytes == 0)
685                       break;
686     
687                     if (bytes == (size_t) -2)
688                       {
689                         len += strlen (f + len);
690                         break;
691                       }
692     
693                     if (bytes == (size_t) -1)
694                       {
695                         len++;
696                         break;
697                       }
698     
699                     len += bytes;
700                   }
701                 while (! mbsinit (&mbstate));
702     
703                 cpy (len, f);
704                 f += len - 1;
705                 continue;
706               }
707             }
708     
709     #else /* ! DO_MULTIBYTE */
710     
711           /* Either multibyte encodings are not supported, they are
712              safe for formats, so any non-'%' byte can be copied through,
713              or this is the wide character version.  */
714           if (*f != L_('%'))
715             {
716               add (1, *p = *f);
717               continue;
718             }
719     
720     #endif /* ! DO_MULTIBYTE */
721     
722           /* Check for flags that can modify a format.  */
723           while (1)
724             {
725               switch (*++f)
726                 {
727                   /* This influences the number formats.  */
728                 case L_('_'):
729                 case L_('-'):
730                 case L_('0'):
731                   pad = *f;
732                   continue;
733     
734                   /* This changes textual output.  */
735                 case L_('^'):
736                   to_uppcase = 1;
737                   continue;
738                 case L_('#'):
739                   change_case = 1;
740                   continue;
741     
742                 default:
743                   break;
744                 }
745               break;
746             }
747     
748           /* As a GNU extension we allow to specify the field width.  */
749           if (ISDIGIT (*f))
750             {
751               width = 0;
752               do
753                 {

At conditional (1): "width == 214748364" taking false path
At conditional (3): "width > 214748364" taking true path
At conditional (5): "width > 214748364" taking false path
At conditional (6): "width == 214748364" taking false path
At conditional (8): "width > 214748364" taking false path
At conditional (9): "width == 214748364" taking true path
At conditional (10): "(*f - 48) > 7" taking false path
At conditional (12): "width > 214748364" taking true path

754                   if (width > INT_MAX / 10
755                       || (width == INT_MAX / 10 && *f - L_('0') > INT_MAX % 
10))
756                     /* Avoid overflow.  */
757                     width = INT_MAX;
758                   else
759                     {
760                       width *= 10;
761                       width += *f - L_('0');
762                     }
763                   ++f;

At conditional (2): "(*f - 48) <= 9" taking true path
At conditional (4): "(*f - 48) <= 9" taking true path
At conditional (7): "(*f - 48) <= 9" taking true path
At conditional (11): "(*f - 48) <= 9" taking true path
At conditional (13): "(*f - 48) <= 9" taking false path

764                 }
765               while (ISDIGIT (*f));
766             }
767     
768           /* Check for modifiers.  */
769           switch (*f)
770             {

At conditional (14): "*f == 69" taking true path

771             case L_('E'):
772             case L_('O'):
773               modifier = *f++;
774               break;
775     
776             default:
777               modifier = 0;
778               break;
779             }
780     
781           /* Now do the specified format.  */
782           format_char = *f;
783           switch (format_char)
784             {
785     #define DO_NUMBER(d, v) \
786               digits = d > width ? d : width;                               
      \
787               number_value = v; goto do_number
788     #define DO_NUMBER_SPACEPAD(d, v) \
789               digits = d > width ? d : width;                               
      \
790               number_value = v; goto do_number_spacepad
791     
792             case L_('%'):
793               if (modifier != 0)
794                 goto bad_format;
795               add (1, *p = *f);
796               break;
797     
798             case L_('a'):
799               if (modifier != 0)
800                 goto bad_format;
801               if (change_case)
802                 {
803                   to_uppcase = 1;
804                   to_lowcase = 0;
805                 }
806     #if defined _NL_CURRENT || !HAVE_STRFTIME
807               cpy (aw_len, a_wkday);
808               break;
809     #else
810               goto underlying_strftime;
811     #endif
812     
813             case 'A':
814               if (modifier != 0)
815                 goto bad_format;
816               if (change_case)
817                 {
818                   to_uppcase = 1;
819                   to_lowcase = 0;
820                 }
821     #if defined _NL_CURRENT || !HAVE_STRFTIME
822               cpy (STRLEN (f_wkday), f_wkday);
823               break;
824     #else
825               goto underlying_strftime;
826     #endif
827     
828             case L_('b'):
829             case L_('h'):
830               if (change_case)
831                 {
832                   to_uppcase = 1;
833                   to_lowcase = 0;
834                 }
835               if (modifier != 0)
836                 goto bad_format;
837     #if defined _NL_CURRENT || !HAVE_STRFTIME
838               cpy (am_len, a_month);
839               break;
840     #else
841               goto underlying_strftime;
842     #endif
843     
844             case L_('B'):
845               if (modifier != 0)
846                 goto bad_format;
847               if (change_case)
848                 {
849                   to_uppcase = 1;
850                   to_lowcase = 0;
851                 }
852     #if defined _NL_CURRENT || !HAVE_STRFTIME
853               cpy (STRLEN (f_month), f_month);
854               break;
855     #else
856               goto underlying_strftime;
857     #endif
858     
859             case L_('c'):
860               if (modifier == L_('O'))
861                 goto bad_format;
862     #ifdef _NL_CURRENT
863               if (! (modifier == 'E'
864                      && (*(subfmt =
865                            (const CHAR_T *) _NL_CURRENT (LC_TIME,
866                                                          NLW(ERA_D_T_FMT)))
867                          != '\0')))
868                 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, 
NLW(D_T_FMT));
869     #else
870     # if HAVE_STRFTIME
871               goto underlying_strftime;
872     # else
873               subfmt = L_("%a %b %e %H:%M:%S %Y");
874     # endif
875     #endif
876     
877             subformat:
878               {
879                 CHAR_T *old_start = p;
880                 size_t len = my_strftime (NULL, (size_t) -1, subfmt,
881                                           tp extra_args LOCALE_ARG);
882                 add (len, my_strftime (p, maxsize - i, subfmt,
883                                        tp extra_args LOCALE_ARG));
884     
885                 if (to_uppcase)
886                   while (old_start < p)
887                     {
888                       *old_start = TOUPPER ((UCHAR_T) *old_start, loc);
889                       ++old_start;
890                     }
891               }
892               break;
893     
894     #if HAVE_STRFTIME && ! (defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY)
895             underlying_strftime:
896               {
897                 /* The relevant information is available only via the
898                    underlying strftime implementation, so use that.  */
899                 char ufmt[4];
900                 char *u = ufmt;
901                 char ubuf[1024]; /* enough for any single format in 
practice */
902                 size_t len;
903                 /* Make sure we're calling the actual underlying strftime.
904                    In some cases, config.h contains something like
905                    "#define strftime rpl_strftime".  */
906     # ifdef strftime
907     #  undef strftime
908                 size_t strftime ();
909     # endif
910     
911     #ifdef STRFTIME_NO_POSIX2
912                 /* Some system libraries do not support the POSIX.2 
extensions.
913                    In those cases, convert %h to %b, and strip modifiers.  
*/
914                 modifier = 0;
915                 if (format_char == 'h')
916                   format_char = 'b';
917     #endif
918                 *u++ = '%';
919                 if (modifier != 0)
920                   *u++ = modifier;
921                 *u++ = format_char;
922                 *u = '\0';
923                 len = strftime (ubuf, sizeof ubuf, ufmt, tp);
924                 if (len == 0 && ubuf[0] != '\0')
925                   return 0;
926                 cpy (len, ubuf);
927               }
928               break;
929     #endif
930     
931             case L_('C'):
932               if (modifier == L_('O'))
933                 goto bad_format;
934               if (modifier == L_('E'))
935                 {
936     #if HAVE_STRUCT_ERA_ENTRY
937                   struct era_entry *era = _nl_get_era_entry (tp 
HELPER_LOCALE_ARG);
938                   if (era)
939                     {
940     # ifdef COMPILE_WIDE
941                       size_t len = __wcslen (era->era_wname);
942                       cpy (len, era->era_wname);
943     # else
944                       size_t len = strlen (era->era_name);
945                       cpy (len, era->era_name);
946     # endif
947                       break;
948                     }
949     #else
950     # if HAVE_STRFTIME
951                   goto underlying_strftime;
952     # endif
953     #endif
954                 }
955     
956               {
957                 int year = tp->tm_year + TM_YEAR_BASE;
958                 DO_NUMBER (1, year / 100 - (year % 100 < 0));
959               }
960     
961             case L_('x'):
962               if (modifier == L_('O'))
963                 goto bad_format;
964     #ifdef _NL_CURRENT
965               if (! (modifier == L_('E')
966                      && (*(subfmt =
967                            (const CHAR_T *)_NL_CURRENT (LC_TIME, 
NLW(ERA_D_FMT)))
968                          != L_('\0'))))
969                 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
970               goto subformat;
971     #else
972     # if HAVE_STRFTIME
973               goto underlying_strftime;
974     # else
975               /* Fall through.  */
976     # endif
977     #endif
978             case L_('D'):
979               if (modifier != 0)
980                 goto bad_format;
981               subfmt = L_("%m/%d/%y");
982               goto subformat;
983     
984             case L_('d'):
985               if (modifier == L_('E'))
986                 goto bad_format;
987     
988               DO_NUMBER (2, tp->tm_mday);
989     
990             case L_('e'):
991               if (modifier == L_('E'))
992                 goto bad_format;
993     
994               DO_NUMBER_SPACEPAD (2, tp->tm_mday);
995     
996               /* All numeric formats set DIGITS and NUMBER_VALUE and then
997                  jump to one of these two labels.  */
998     
999             do_number_spacepad:
1000              /* Force `_' flag unless overridden by `0' or `-' flag.  */
1001              if (pad != L_('0') && pad != L_('-'))
1002                pad = L_('_');
1003    
1004            do_number:
1005              /* Format the number according to the MODIFIER flag.  */
1006    
1007              if (modifier == L_('O') && 0 <= number_value)
1008                {
1009    #ifdef _NL_CURRENT
1010                  /* Get the locale specific alternate representation of
1011                     the number NUMBER_VALUE.  If none exist NULL is 
returned.  */
1012                  const CHAR_T *cp = nl_get_alt_digit (number_value
1013                                                       HELPER_LOCALE_ARG);
1014    
1015                  if (cp != NULL)
1016                    {
1017                      size_t digitlen = STRLEN (cp);
1018                      if (digitlen != 0)
1019                        {
1020                          cpy (digitlen, cp);
1021                          break;
1022                        }
1023                    }
1024    #else
1025    # if HAVE_STRFTIME
1026                  goto underlying_strftime;
1027    # endif
1028    #endif
1029                }
1030              {
1031                unsigned int u = number_value;
1032    
1033                bufp = buf + sizeof (buf) / sizeof (buf[0]);
1034                negative_number = number_value < 0;
1035    
1036                if (negative_number)
1037                  u = -u;
1038    
1039                do
1040                  *--bufp = u % 10 + L_('0');
1041                while ((u /= 10) != 0);
1042              }
1043    
1044            do_number_sign_and_padding:
1045              if (negative_number)
1046                *--bufp = L_('-');
1047    
1048              if (pad != L_('-'))
1049                {
1050                  int padding = digits - (buf + (sizeof (buf) / sizeof 
(buf[0]))
1051                                          - bufp);
1052    
1053                  if (padding > 0)
1054                    {
1055                      if (pad == L_('_'))
1056                        {
1057                          if ((size_t) padding >= maxsize - i)
1058                            return 0;
1059    
1060                          if (p)
1061                            memset_space (p, padding);
1062                          i += padding;
1063                          width = width > padding ? width - padding : 0;
1064                        }
1065                      else
1066                        {
1067                          if ((size_t) digits >= maxsize - i)
1068                            return 0;
1069    
1070                          if (negative_number)
1071                            {
1072                              ++bufp;
1073    
1074                              if (p)
1075                                *p++ = L_('-');
1076                              ++i;
1077                            }
1078    
1079                          if (p)
1080                            memset_zero (p, padding);
1081                          i += padding;
1082                          width = 0;
1083                        }
1084                    }
1085                }
1086    
1087              cpy (buf + sizeof (buf) / sizeof (buf[0]) - bufp, bufp);
1088              break;
1089    
1090            case L_('F'):
1091              if (modifier != 0)
1092                goto bad_format;
1093              subfmt = L_("%Y-%m-%d");
1094              goto subformat;
1095    
1096            case L_('H'):
1097              if (modifier == L_('E'))
1098                goto bad_format;
1099    
1100              DO_NUMBER (2, tp->tm_hour);
1101    
1102            case L_('I'):
1103              if (modifier == L_('E'))
1104                goto bad_format;
1105    
1106              DO_NUMBER (2, hour12);
1107    
1108            case L_('k'):           /* GNU extension.  */
1109              if (modifier == L_('E'))
1110                goto bad_format;
1111    
1112              DO_NUMBER_SPACEPAD (2, tp->tm_hour);
1113    
1114            case L_('l'):           /* GNU extension.  */
1115              if (modifier == L_('E'))
1116                goto bad_format;
1117    
1118              DO_NUMBER_SPACEPAD (2, hour12);
1119    
1120            case L_('j'):
1121              if (modifier == L_('E'))
1122                goto bad_format;
1123    
1124              DO_NUMBER (3, 1 + tp->tm_yday);
1125    
1126            case L_('M'):
1127              if (modifier == L_('E'))
1128                goto bad_format;
1129    
1130              DO_NUMBER (2, tp->tm_min);
1131    
1132            case L_('m'):
1133              if (modifier == L_('E'))
1134                goto bad_format;
1135    
1136              DO_NUMBER (2, tp->tm_mon + 1);
1137    
1138    #ifndef _LIBC
1139            case L_('N'):           /* GNU extension.  */
1140              if (modifier == L_('E'))
1141                goto bad_format;
1142    
1143              number_value = ns;
1144              if (width != -1)
1145                {
1146                  /* Take an explicit width less than 9 as a precision.  */
1147                  int j;
1148                  for (j = width; j < 9; j++)
1149                    number_value /= 10;
1150                }
1151    
1152              DO_NUMBER (9, number_value);
1153    #endif
1154    
1155            case L_('n'):
1156              add (1, *p = L_('\n'));
1157              break;
1158    
1159            case L_('P'):
1160              to_lowcase = 1;
1161    #if !defined _NL_CURRENT && HAVE_STRFTIME
1162              format_char = L_('p');
1163    #endif
1164              /* FALLTHROUGH */
1165    
1166            case L_('p'):
1167              if (change_case)
1168                {
1169                  to_uppcase = 0;
1170                  to_lowcase = 1;
1171                }
1172    #if defined _NL_CURRENT || !HAVE_STRFTIME
1173              cpy (ap_len, ampm);
1174              break;
1175    #else
1176              goto underlying_strftime;
1177    #endif
1178    
1179            case L_('R'):
1180              subfmt = L_("%H:%M");
1181              goto subformat;
1182    
1183            case L_('r'):
1184    #ifdef _NL_CURRENT
1185              if (*(subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME,
1186                                                           NLW(T_FMT_AMPM)))
1187                  == L_('\0'))
1188    #endif
1189                subfmt = L_("%I:%M:%S %p");
1190              goto subformat;
1191    
1192            case L_('S'):
1193              if (modifier == L_('E'))
1194                goto bad_format;
1195    
1196              DO_NUMBER (2, tp->tm_sec);
1197    
1198            case L_('s'):           /* GNU extension.  */
1199              {
1200                struct tm ltm;
1201                time_t t;
1202    
1203                ltm = *tp;
1204                t = mktime (&ltm);
1205    
1206                /* Generate string value for T using time_t arithmetic;
1207                   this works even if sizeof (long) < sizeof (time_t).  */
1208    
1209                bufp = buf + sizeof (buf) / sizeof (buf[0]);
1210                negative_number = t < 0;
1211    
1212                do
1213                  {
1214                    int d = t % 10;
1215                    t /= 10;
1216    
1217                    if (negative_number)
1218                      {
1219                        d = -d;
1220    
1221                        /* Adjust if division truncates to minus infinity.  
*/
1222                        if (0 < -1 % 10 && d < 0)
1223                          {
1224                            t++;
1225                            d += 10;
1226                          }
1227                      }
1228    
1229                    *--bufp = d + L_('0');
1230                  }
1231                while (t != 0);
1232    
1233                digits = 1;
1234                goto do_number_sign_and_padding;
1235              }
1236    
1237            case L_('X'):
1238              if (modifier == L_('O'))
1239                goto bad_format;
1240    #ifdef _NL_CURRENT
1241              if (! (modifier == L_('E')
1242                     && (*(subfmt =
1243                           (const CHAR_T *) _NL_CURRENT (LC_TIME, 
NLW(ERA_T_FMT)))
1244                         != L_('\0'))))
1245                subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT));
1246              goto subformat;
1247    #else
1248    # if HAVE_STRFTIME
1249              goto underlying_strftime;
1250    # else
1251              /* Fall through.  */
1252    # endif
1253    #endif
1254            case L_('T'):
1255              subfmt = L_("%H:%M:%S");
1256              goto subformat;
1257    
1258            case L_('t'):
1259              add (1, *p = L_('\t'));
1260              break;
1261    
1262            case L_('u'):
1263              DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
1264    
1265            case L_('U'):
1266              if (modifier == L_('E'))
1267                goto bad_format;
1268    
1269              DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
1270    
1271            case L_('V'):
1272            case L_('g'):
1273            case L_('G'):
1274              if (modifier == L_('E'))
1275                goto bad_format;
1276              {
1277                int year = tp->tm_year + TM_YEAR_BASE;
1278                int days = iso_week_days (tp->tm_yday, tp->tm_wday);
1279    
1280                if (days < 0)
1281                  {
1282                    /* This ISO week belongs to the previous year.  */
1283                    year--;
1284                    days = iso_week_days (tp->tm_yday + (365 + __isleap 
(year)),
1285                                          tp->tm_wday);
1286                  }
1287                else
1288                  {
1289                    int d = iso_week_days (tp->tm_yday - (365 + __isleap 
(year)),
1290                                           tp->tm_wday);
1291                    if (0 <= d)
1292                      {
1293                        /* This ISO week belongs to the next year.  */
1294                        year++;
1295                        days = d;
1296                      }
1297                  }
1298    
1299                switch (*f)
1300                  {
1301                  case L_('g'):
1302                    DO_NUMBER (2, (year % 100 + 100) % 100);
1303    
1304                  case L_('G'):
1305                    DO_NUMBER (1, year);
1306    
1307                  default:
1308                    DO_NUMBER (2, days / 7 + 1);
1309                  }
1310              }
1311    
1312            case L_('W'):
1313              if (modifier == L_('E'))
1314                goto bad_format;
1315    
1316              DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 
7);
1317    
1318            case L_('w'):
1319              if (modifier == L_('E'))
1320                goto bad_format;
1321    
1322              DO_NUMBER (1, tp->tm_wday);
1323    
1324            case L_('Y'):
1325              if (modifier == 'E')
1326                {
1327    #if HAVE_STRUCT_ERA_ENTRY
1328                  struct era_entry *era = _nl_get_era_entry (tp 
HELPER_LOCALE_ARG);
1329                  if (era)
1330                    {
1331    # ifdef COMPILE_WIDE
1332                      subfmt = era->era_wformat;
1333    # else
1334                      subfmt = era->era_format;
1335    # endif
1336                      goto subformat;
1337                    }
1338    #else
1339    # if HAVE_STRFTIME
1340                  goto underlying_strftime;
1341    # endif
1342    #endif
1343                }
1344              if (modifier == L_('O'))
1345                goto bad_format;
1346              else
1347                DO_NUMBER (1, tp->tm_year + TM_YEAR_BASE);
1348    
1349            case L_('y'):
1350              if (modifier == L_('E'))
1351                {
1352    #if HAVE_STRUCT_ERA_ENTRY
1353                  struct era_entry *era = _nl_get_era_entry (tp 
HELPER_LOCALE_ARG);
1354                  if (era)
1355                    {
1356                      int delta = tp->tm_year - era->start_date[0];
1357                      DO_NUMBER (1, (era->offset
1358                                     + delta * era->absolute_direction));
1359                    }
1360    #else
1361    # if HAVE_STRFTIME
1362                  goto underlying_strftime;
1363    # endif
1364    #endif
1365                }
1366              DO_NUMBER (2, (tp->tm_year % 100 + 100) % 100);
1367    
1368            case L_('Z'):
1369              if (change_case)
1370                {
1371                  to_uppcase = 0;
1372                  to_lowcase = 1;
1373                }
1374    
1375    #if HAVE_TZNAME
1376              /* The tzset() call might have changed the value.  */
1377              if (!(zone && *zone) && tp->tm_isdst >= 0)
1378                zone = tzname[tp->tm_isdst];
1379    #endif
1380              if (! zone)
1381                zone = "";
1382    
1383    #ifdef COMPILE_WIDE
1384              {
1385                /* The zone string is always given in multibyte form.  We 
have
1386                   to transform it first.  */
1387                wchar_t *wczone;
1388                size_t len;
1389                widen (zone, wczone, len);
1390                cpy (len, wczone);
1391              }
1392    #else
1393              cpy (strlen (zone), zone);
1394    #endif
1395              break;
1396    
1397            case L_('z'):
1398              if (tp->tm_isdst < 0)
1399                break;
1400    
1401              {
1402                int diff;
1403    #if HAVE_TM_GMTOFF
1404                diff = tp->tm_gmtoff;
1405    #else
1406                if (ut)
1407                  diff = 0;
1408                else
1409                  {
1410                    struct tm gtm;
1411                    struct tm ltm;
1412                    time_t lt;
1413    
1414                    ltm = *tp;
1415                    lt = mktime (&ltm);
1416    
1417                    if (lt == (time_t) -1)
1418                      {
1419                        /* mktime returns -1 for errors, but -1 is also a
1420                           valid time_t value.  Check whether an error 
really
1421                           occurred.  */
1422                        struct tm tm;
1423    
1424                        if (! my_strftime_localtime_r (&lt, &tm)
1425                            || ((ltm.tm_sec ^ tm.tm_sec)
1426                                | (ltm.tm_min ^ tm.tm_min)
1427                                | (ltm.tm_hour ^ tm.tm_hour)
1428                                | (ltm.tm_mday ^ tm.tm_mday)
1429                                | (ltm.tm_mon ^ tm.tm_mon)
1430                                | (ltm.tm_year ^ tm.tm_year)))
1431                          break;
1432                      }
1433    
1434                    if (! my_strftime_gmtime_r (&lt, &gtm))
1435                      break;
1436    
1437                    diff = tm_diff (&ltm, &gtm);
1438                  }
1439    #endif
1440    
1441                if (diff < 0)
1442                  {
1443                    add (1, *p = L_('-'));
1444                    diff = -diff;
1445                  }
1446                else
1447                  add (1, *p = L_('+'));
1448    
1449                diff /= 60;
1450                DO_NUMBER (4, (diff / 60) * 100 + diff % 60);
1451              }
1452    
1453            case L_('\0'):          /* GNU extension: % at end of format.  
*/
1454                --f;
1455                /* Fall through.  */

At conditional (15): "default" taking true path

1456            default:
1457              /* Unknown format; output the format, including the '%',
1458                 since this is most likely the right thing to do if a
1459                 multibyte string has been misparsed.  */
1460            bad_format:
1461              {
1462                int flen;

At conditional (16): "*(f + (1 - flen)) != 37" taking true path
At conditional (17): "*(f + (1 - flen)) != 37" taking true path
At conditional (18): "*(f + (1 - flen)) != 37" taking true path
At conditional (19): "*(f + (1 - flen)) != 37" taking false path

1463                for (flen = 1; f[1 - flen] != L_('%'); flen++)
1464                  continue;

At conditional (20): "_delta > 0" taking true path
At conditional (21): "_incr >= (maxsize - i)" taking true path

1465                cpy (flen, &f[1 - flen]);
1466              }
1467              break;
1468            }
1469        }
1470    




reply via email to

[Prev in Thread] Current Thread [Next in Thread]