lib/replace/strptime.c

説明を見る。
00001 /* Convert a string representation of time to a time value.
00002    Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Library General Public License as
00008    published by the Free Software Foundation; either version 2 of the
00009    License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Library General Public License for more details.
00015 
00016    You should have received a copy of the GNU Library General Public
00017    License along with the GNU C Library; see the file COPYING.LIB.  If not,
00018    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00019    Boston, MA 02111-1307, USA.  */
00020 
00021 /* XXX This version of the implementation is not really complete.
00022    Some of the fields cannot add information alone.  But if seeing
00023    some of them in the same format (such as year, week and weekday)
00024    this is enough information for determining the date.  */
00025 
00026 #include "replace.h"
00027 #include "system/locale.h"
00028 #include "system/time.h"
00029 
00030 #ifndef __P
00031 # if defined (__GNUC__) || (defined (__STDC__) && __STDC__)
00032 #  define __P(args) args
00033 # else
00034 #  define __P(args) ()
00035 # endif  /* GCC.  */
00036 #endif  /* Not __P.  */
00037 
00038 #if ! HAVE_LOCALTIME_R && ! defined localtime_r
00039 # ifdef _LIBC
00040 #  define localtime_r __localtime_r
00041 # else
00042 /* Approximate localtime_r as best we can in its absence.  */
00043 #  define localtime_r my_localtime_r
00044 static struct tm *localtime_r __P ((const time_t *, struct tm *));
00045 static struct tm *
00046 localtime_r (t, tp)
00047      const time_t *t;
00048      struct tm *tp;
00049 {
00050   struct tm *l = localtime (t);
00051   if (! l)
00052     return 0;
00053   *tp = *l;
00054   return tp;
00055 }
00056 # endif /* ! _LIBC */
00057 #endif /* ! HAVE_LOCALTIME_R && ! defined (localtime_r) */
00058 
00059 
00060 #define match_char(ch1, ch2) if (ch1 != ch2) return NULL
00061 #if defined __GNUC__ && __GNUC__ >= 2
00062 # define match_string(cs1, s2) \
00063   ({ size_t len = strlen (cs1);                                               \
00064      int result = strncasecmp ((cs1), (s2), len) == 0;                        \
00065      if (result) (s2) += len;                                                 \
00066      result; })
00067 #else
00068 /* Oh come on.  Get a reasonable compiler.  */
00069 # define match_string(cs1, s2) \
00070   (strncasecmp ((cs1), (s2), strlen (cs1)) ? 0 : ((s2) += strlen (cs1), 1))
00071 #endif
00072 /* We intentionally do not use isdigit() for testing because this will
00073    lead to problems with the wide character version.  */
00074 #define get_number(from, to, n) \
00075   do {                                                                        \
00076     int __n = n;                                                              \
00077     val = 0;                                                                  \
00078     while (*rp == ' ')                                                        \
00079       ++rp;                                                                   \
00080     if (*rp < '0' || *rp > '9')                                               \
00081       return NULL;                                                            \
00082     do {                                                                      \
00083       val *= 10;                                                              \
00084       val += *rp++ - '0';                                                     \
00085     } while (--__n > 0 && val * 10 <= to && *rp >= '0' && *rp <= '9');        \
00086     if (val < from || val > to)                                               \
00087       return NULL;                                                            \
00088   } while (0)
00089 #ifdef _NL_CURRENT
00090 # define get_alt_number(from, to, n) \
00091   ({                                                                          \
00092     __label__ do_normal;                                                      \
00093     if (*decided != raw)                                                      \
00094       {                                                                       \
00095         const char *alts = _NL_CURRENT (LC_TIME, ALT_DIGITS);                 \
00096         int __n = n;                                                          \
00097         int any = 0;                                                          \
00098         while (*rp == ' ')                                                    \
00099           ++rp;                                                               \
00100         val = 0;                                                              \
00101         do {                                                                  \
00102           val *= 10;                                                          \
00103           while (*alts != '\0')                                               \
00104             {                                                                 \
00105               size_t len = strlen (alts);                                     \
00106               if (strncasecmp (alts, rp, len) == 0)                           \
00107                 break;                                                        \
00108               alts += len + 1;                                                \
00109               ++val;                                                          \
00110             }                                                                 \
00111           if (*alts == '\0')                                                  \
00112             {                                                                 \
00113               if (*decided == not && ! any)                                   \
00114                 goto do_normal;                                               \
00115               /* If we haven't read anything it's an error.  */               \
00116               if (! any)                                                      \
00117                 return NULL;                                                  \
00118               /* Correct the premature multiplication.  */                    \
00119               val /= 10;                                                      \
00120               break;                                                          \
00121             }                                                                 \
00122           else                                                                \
00123             *decided = loc;                                                   \
00124         } while (--__n > 0 && val * 10 <= to);                                \
00125         if (val < from || val > to)                                           \
00126           return NULL;                                                        \
00127       }                                                                       \
00128     else                                                                      \
00129       {                                                                       \
00130        do_normal:                                                             \
00131         get_number (from, to, n);                                             \
00132       }                                                                       \
00133     0;                                                                        \
00134   })
00135 #else
00136 # define get_alt_number(from, to, n) \
00137   /* We don't have the alternate representation.  */                          \
00138   get_number(from, to, n)
00139 #endif
00140 #define recursive(new_fmt) \
00141   (*(new_fmt) != '\0'                                                         \
00142    && (rp = strptime_internal (rp, (new_fmt), tm, decided, era_cnt)) != NULL)
00143 
00144 
00145 #ifdef _LIBC
00146 /* This is defined in locale/C-time.c in the GNU libc.  */
00147 extern const struct locale_data _nl_C_LC_TIME;
00148 extern const unsigned short int __mon_yday[2][13];
00149 
00150 # define weekday_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (DAY_1)].string)
00151 # define ab_weekday_name \
00152   (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABDAY_1)].string)
00153 # define month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (MON_1)].string)
00154 # define ab_month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABMON_1)].string)
00155 # define HERE_D_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_T_FMT)].string)
00156 # define HERE_D_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_FMT)].string)
00157 # define HERE_AM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (AM_STR)].string)
00158 # define HERE_PM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (PM_STR)].string)
00159 # define HERE_T_FMT_AMPM \
00160   (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT_AMPM)].string)
00161 # define HERE_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT)].string)
00162 
00163 # define strncasecmp(s1, s2, n) __strncasecmp (s1, s2, n)
00164 #else
00165 static char const weekday_name[][10] =
00166   {
00167     "Sunday", "Monday", "Tuesday", "Wednesday",
00168     "Thursday", "Friday", "Saturday"
00169   };
00170 static char const ab_weekday_name[][4] =
00171   {
00172     "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
00173   };
00174 static char const month_name[][10] =
00175   {
00176     "January", "February", "March", "April", "May", "June",
00177     "July", "August", "September", "October", "November", "December"
00178   };
00179 static char const ab_month_name[][4] =
00180   {
00181     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
00182     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
00183   };
00184 # define HERE_D_T_FMT "%a %b %e %H:%M:%S %Y"
00185 # define HERE_D_FMT "%m/%d/%y"
00186 # define HERE_AM_STR "AM"
00187 # define HERE_PM_STR "PM"
00188 # define HERE_T_FMT_AMPM "%I:%M:%S %p"
00189 # define HERE_T_FMT "%H:%M:%S"
00190 
00191 static const unsigned short int __mon_yday[2][13] =
00192   {
00193     /* Normal years.  */
00194     { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
00195     /* Leap years.  */
00196     { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
00197   };
00198 #endif
00199 
00200 /* Status of lookup: do we use the locale data or the raw data?  */
00201 enum locale_status { not, loc, raw };
00202 
00203 
00204 #ifndef __isleap
00205 /* Nonzero if YEAR is a leap year (every 4 years,
00206    except every 100th isn't, and every 400th is).  */
00207 # define __isleap(year) \
00208   ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
00209 #endif
00210 
00211 /* Compute the day of the week.  */
00212 static void
00213 day_of_the_week (struct tm *tm)
00214 {
00215   /* We know that January 1st 1970 was a Thursday (= 4).  Compute the
00216      the difference between this data in the one on TM and so determine
00217      the weekday.  */
00218   int corr_year = 1900 + tm->tm_year - (tm->tm_mon < 2);
00219   int wday = (-473
00220               + (365 * (tm->tm_year - 70))
00221               + (corr_year / 4)
00222               - ((corr_year / 4) / 25) + ((corr_year / 4) % 25 < 0)
00223               + (((corr_year / 4) / 25) / 4)
00224               + __mon_yday[0][tm->tm_mon]
00225               + tm->tm_mday - 1);
00226   tm->tm_wday = ((wday % 7) + 7) % 7;
00227 }
00228 
00229 /* Compute the day of the year.  */
00230 static void
00231 day_of_the_year (struct tm *tm)
00232 {
00233   tm->tm_yday = (__mon_yday[__isleap (1900 + tm->tm_year)][tm->tm_mon]
00234                  + (tm->tm_mday - 1));
00235 }
00236 
00237 static char *
00238 #ifdef _LIBC
00239 internal_function
00240 #endif
00241 strptime_internal __P ((const char *rp, const char *fmt, struct tm *tm,
00242                         enum locale_status *decided, int era_cnt));
00243 
00244 static char *
00245 #ifdef _LIBC
00246 internal_function
00247 #endif
00248 strptime_internal (rp, fmt, tm, decided, era_cnt)
00249      const char *rp;
00250      const char *fmt;
00251      struct tm *tm;
00252      enum locale_status *decided;
00253      int era_cnt;
00254 {
00255   const char *rp_backup;
00256   int cnt;
00257   size_t val;
00258   int have_I, is_pm;
00259   int century, want_century;
00260   int want_era;
00261   int have_wday, want_xday;
00262   int have_yday;
00263   int have_mon, have_mday;
00264 #ifdef _NL_CURRENT
00265   size_t num_eras;
00266 #endif
00267   struct era_entry *era;
00268 
00269   have_I = is_pm = 0;
00270   century = -1;
00271   want_century = 0;
00272   want_era = 0;
00273   era = NULL;
00274 
00275   have_wday = want_xday = have_yday = have_mon = have_mday = 0;
00276 
00277   while (*fmt != '\0')
00278     {
00279       /* A white space in the format string matches 0 more or white
00280          space in the input string.  */
00281       if (isspace (*fmt))
00282         {
00283           while (isspace (*rp))
00284             ++rp;
00285           ++fmt;
00286           continue;
00287         }
00288 
00289       /* Any character but `%' must be matched by the same character
00290          in the iput string.  */
00291       if (*fmt != '%')
00292         {
00293           match_char (*fmt++, *rp++);
00294           continue;
00295         }
00296 
00297       ++fmt;
00298 #ifndef _NL_CURRENT
00299       /* We need this for handling the `E' modifier.  */
00300     start_over:
00301 #endif
00302 
00303       /* Make back up of current processing pointer.  */
00304       rp_backup = rp;
00305 
00306       switch (*fmt++)
00307         {
00308         case '%':
00309           /* Match the `%' character itself.  */
00310           match_char ('%', *rp++);
00311           break;
00312         case 'a':
00313         case 'A':
00314           /* Match day of week.  */
00315           for (cnt = 0; cnt < 7; ++cnt)
00316             {
00317 #ifdef _NL_CURRENT
00318               if (*decided !=raw)
00319                 {
00320                   if (match_string (_NL_CURRENT (LC_TIME, DAY_1 + cnt), rp))
00321                     {
00322                       if (*decided == not
00323                           && strcmp (_NL_CURRENT (LC_TIME, DAY_1 + cnt),
00324                                      weekday_name[cnt]))
00325                         *decided = loc;
00326                       break;
00327                     }
00328                   if (match_string (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt), rp))
00329                     {
00330                       if (*decided == not
00331                           && strcmp (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt),
00332                                      ab_weekday_name[cnt]))
00333                         *decided = loc;
00334                       break;
00335                     }
00336                 }
00337 #endif
00338               if (*decided != loc
00339                   && (match_string (weekday_name[cnt], rp)
00340                       || match_string (ab_weekday_name[cnt], rp)))
00341                 {
00342                   *decided = raw;
00343                   break;
00344                 }
00345             }
00346           if (cnt == 7)
00347             /* Does not match a weekday name.  */
00348             return NULL;
00349           tm->tm_wday = cnt;
00350           have_wday = 1;
00351           break;
00352         case 'b':
00353         case 'B':
00354         case 'h':
00355           /* Match month name.  */
00356           for (cnt = 0; cnt < 12; ++cnt)
00357             {
00358 #ifdef _NL_CURRENT
00359               if (*decided !=raw)
00360                 {
00361                   if (match_string (_NL_CURRENT (LC_TIME, MON_1 + cnt), rp))
00362                     {
00363                       if (*decided == not
00364                           && strcmp (_NL_CURRENT (LC_TIME, MON_1 + cnt),
00365                                      month_name[cnt]))
00366                         *decided = loc;
00367                       break;
00368                     }
00369                   if (match_string (_NL_CURRENT (LC_TIME, ABMON_1 + cnt), rp))
00370                     {
00371                       if (*decided == not
00372                           && strcmp (_NL_CURRENT (LC_TIME, ABMON_1 + cnt),
00373                                      ab_month_name[cnt]))
00374                         *decided = loc;
00375                       break;
00376                     }
00377                 }
00378 #endif
00379               if (match_string (month_name[cnt], rp)
00380                   || match_string (ab_month_name[cnt], rp))
00381                 {
00382                   *decided = raw;
00383                   break;
00384                 }
00385             }
00386           if (cnt == 12)
00387             /* Does not match a month name.  */
00388             return NULL;
00389           tm->tm_mon = cnt;
00390           want_xday = 1;
00391           break;
00392         case 'c':
00393           /* Match locale's date and time format.  */
00394 #ifdef _NL_CURRENT
00395           if (*decided != raw)
00396             {
00397               if (!recursive (_NL_CURRENT (LC_TIME, D_T_FMT)))
00398                 {
00399                   if (*decided == loc)
00400                     return NULL;
00401                   else
00402                     rp = rp_backup;
00403                 }
00404               else
00405                 {
00406                   if (*decided == not &&
00407                       strcmp (_NL_CURRENT (LC_TIME, D_T_FMT), HERE_D_T_FMT))
00408                     *decided = loc;
00409                   want_xday = 1;
00410                   break;
00411                 }
00412               *decided = raw;
00413             }
00414 #endif
00415           if (!recursive (HERE_D_T_FMT))
00416             return NULL;
00417           want_xday = 1;
00418           break;
00419         case 'C':
00420           /* Match century number.  */
00421 #ifdef _NL_CURRENT
00422         match_century:
00423 #endif
00424           get_number (0, 99, 2);
00425           century = val;
00426           want_xday = 1;
00427           break;
00428         case 'd':
00429         case 'e':
00430           /* Match day of month.  */
00431           get_number (1, 31, 2);
00432           tm->tm_mday = val;
00433           have_mday = 1;
00434           want_xday = 1;
00435           break;
00436         case 'F':
00437           if (!recursive ("%Y-%m-%d"))
00438             return NULL;
00439           want_xday = 1;
00440           break;
00441         case 'x':
00442 #ifdef _NL_CURRENT
00443           if (*decided != raw)
00444             {
00445               if (!recursive (_NL_CURRENT (LC_TIME, D_FMT)))
00446                 {
00447                   if (*decided == loc)
00448                     return NULL;
00449                   else
00450                     rp = rp_backup;
00451                 }
00452               else
00453                 {
00454                   if (*decided == not
00455                       && strcmp (_NL_CURRENT (LC_TIME, D_FMT), HERE_D_FMT))
00456                     *decided = loc;
00457                   want_xday = 1;
00458                   break;
00459                 }
00460               *decided = raw;
00461             }
00462 #endif
00463           /* Fall through.  */
00464         case 'D':
00465           /* Match standard day format.  */
00466           if (!recursive (HERE_D_FMT))
00467             return NULL;
00468           want_xday = 1;
00469           break;
00470         case 'k':
00471         case 'H':
00472           /* Match hour in 24-hour clock.  */
00473           get_number (0, 23, 2);
00474           tm->tm_hour = val;
00475           have_I = 0;
00476           break;
00477         case 'I':
00478           /* Match hour in 12-hour clock.  */
00479           get_number (1, 12, 2);
00480           tm->tm_hour = val % 12;
00481           have_I = 1;
00482           break;
00483         case 'j':
00484           /* Match day number of year.  */
00485           get_number (1, 366, 3);
00486           tm->tm_yday = val - 1;
00487           have_yday = 1;
00488           break;
00489         case 'm':
00490           /* Match number of month.  */
00491           get_number (1, 12, 2);
00492           tm->tm_mon = val - 1;
00493           have_mon = 1;
00494           want_xday = 1;
00495           break;
00496         case 'M':
00497           /* Match minute.  */
00498           get_number (0, 59, 2);
00499           tm->tm_min = val;
00500           break;
00501         case 'n':
00502         case 't':
00503           /* Match any white space.  */
00504           while (isspace (*rp))
00505             ++rp;
00506           break;
00507         case 'p':
00508           /* Match locale's equivalent of AM/PM.  */
00509 #ifdef _NL_CURRENT
00510           if (*decided != raw)
00511             {
00512               if (match_string (_NL_CURRENT (LC_TIME, AM_STR), rp))
00513                 {
00514                   if (strcmp (_NL_CURRENT (LC_TIME, AM_STR), HERE_AM_STR))
00515                     *decided = loc;
00516                   break;
00517                 }
00518               if (match_string (_NL_CURRENT (LC_TIME, PM_STR), rp))
00519                 {
00520                   if (strcmp (_NL_CURRENT (LC_TIME, PM_STR), HERE_PM_STR))
00521                     *decided = loc;
00522                   is_pm = 1;
00523                   break;
00524                 }
00525               *decided = raw;
00526             }
00527 #endif
00528           if (!match_string (HERE_AM_STR, rp)) {
00529             if (match_string (HERE_PM_STR, rp)) {
00530               is_pm = 1;
00531             } else {
00532               return NULL;
00533             }
00534           }
00535           break;
00536         case 'r':
00537 #ifdef _NL_CURRENT
00538           if (*decided != raw)
00539             {
00540               if (!recursive (_NL_CURRENT (LC_TIME, T_FMT_AMPM)))
00541                 {
00542                   if (*decided == loc)
00543                     return NULL;
00544                   else
00545                     rp = rp_backup;
00546                 }
00547               else
00548                 {
00549                   if (*decided == not &&
00550                       strcmp (_NL_CURRENT (LC_TIME, T_FMT_AMPM),
00551                               HERE_T_FMT_AMPM))
00552                     *decided = loc;
00553                   break;
00554                 }
00555               *decided = raw;
00556             }
00557 #endif
00558           if (!recursive (HERE_T_FMT_AMPM))
00559             return NULL;
00560           break;
00561         case 'R':
00562           if (!recursive ("%H:%M"))
00563             return NULL;
00564           break;
00565         case 's':
00566           {
00567             /* The number of seconds may be very high so we cannot use
00568                the `get_number' macro.  Instead read the number
00569                character for character and construct the result while
00570                doing this.  */
00571             time_t secs = 0;
00572             if (*rp < '0' || *rp > '9')
00573               /* We need at least one digit.  */
00574               return NULL;
00575 
00576             do
00577               {
00578                 secs *= 10;
00579                 secs += *rp++ - '0';
00580               }
00581             while (*rp >= '0' && *rp <= '9');
00582 
00583             if (localtime_r (&secs, tm) == NULL)
00584               /* Error in function.  */
00585               return NULL;
00586           }
00587           break;
00588         case 'S':
00589           get_number (0, 61, 2);
00590           tm->tm_sec = val;
00591           break;
00592         case 'X':
00593 #ifdef _NL_CURRENT
00594           if (*decided != raw)
00595             {
00596               if (!recursive (_NL_CURRENT (LC_TIME, T_FMT)))
00597                 {
00598                   if (*decided == loc)
00599                     return NULL;
00600                   else
00601                     rp = rp_backup;
00602                 }
00603               else
00604                 {
00605                   if (strcmp (_NL_CURRENT (LC_TIME, T_FMT), HERE_T_FMT))
00606                     *decided = loc;
00607                   break;
00608                 }
00609               *decided = raw;
00610             }
00611 #endif
00612           /* Fall through.  */
00613         case 'T':
00614           if (!recursive (HERE_T_FMT))
00615             return NULL;
00616           break;
00617         case 'u':
00618           get_number (1, 7, 1);
00619           tm->tm_wday = val % 7;
00620           have_wday = 1;
00621           break;
00622         case 'g':
00623           get_number (0, 99, 2);
00624           /* XXX This cannot determine any field in TM.  */
00625           break;
00626         case 'G':
00627           if (*rp < '0' || *rp > '9')
00628             return NULL;
00629           /* XXX Ignore the number since we would need some more
00630              information to compute a real date.  */
00631           do
00632             ++rp;
00633           while (*rp >= '0' && *rp <= '9');
00634           break;
00635         case 'U':
00636         case 'V':
00637         case 'W':
00638           get_number (0, 53, 2);
00639           /* XXX This cannot determine any field in TM without some
00640              information.  */
00641           break;
00642         case 'w':
00643           /* Match number of weekday.  */
00644           get_number (0, 6, 1);
00645           tm->tm_wday = val;
00646           have_wday = 1;
00647           break;
00648         case 'y':
00649 #ifdef _NL_CURRENT
00650         match_year_in_century:
00651 #endif
00652           /* Match year within century.  */
00653           get_number (0, 99, 2);
00654           /* The "Year 2000: The Millennium Rollover" paper suggests that
00655              values in the range 69-99 refer to the twentieth century.  */
00656           tm->tm_year = val >= 69 ? val : val + 100;
00657           /* Indicate that we want to use the century, if specified.  */
00658           want_century = 1;
00659           want_xday = 1;
00660           break;
00661         case 'Y':
00662           /* Match year including century number.  */
00663           get_number (0, 9999, 4);
00664           tm->tm_year = val - 1900;
00665           want_century = 0;
00666           want_xday = 1;
00667           break;
00668         case 'Z':
00669           /* XXX How to handle this?  */
00670           break;
00671         case 'E':
00672 #ifdef _NL_CURRENT
00673           switch (*fmt++)
00674             {
00675             case 'c':
00676               /* Match locale's alternate date and time format.  */
00677               if (*decided != raw)
00678                 {
00679                   const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_T_FMT);
00680 
00681                   if (*fmt == '\0')
00682                     fmt = _NL_CURRENT (LC_TIME, D_T_FMT);
00683 
00684                   if (!recursive (fmt))
00685                     {
00686                       if (*decided == loc)
00687                         return NULL;
00688                       else
00689                         rp = rp_backup;
00690                     }
00691                   else
00692                     {
00693                       if (strcmp (fmt, HERE_D_T_FMT))
00694                         *decided = loc;
00695                       want_xday = 1;
00696                       break;
00697                     }
00698                   *decided = raw;
00699                 }
00700               /* The C locale has no era information, so use the
00701                  normal representation.  */
00702               if (!recursive (HERE_D_T_FMT))
00703                 return NULL;
00704               want_xday = 1;
00705               break;
00706             case 'C':
00707               if (*decided != raw)
00708                 {
00709                   if (era_cnt >= 0)
00710                     {
00711                       era = _nl_select_era_entry (era_cnt);
00712                       if (match_string (era->era_name, rp))
00713                         {
00714                           *decided = loc;
00715                           break;
00716                         }
00717                       else
00718                         return NULL;
00719                     }
00720                   else
00721                     {
00722                       num_eras = _NL_CURRENT_WORD (LC_TIME,
00723                                                    _NL_TIME_ERA_NUM_ENTRIES);
00724                       for (era_cnt = 0; era_cnt < (int) num_eras;
00725                            ++era_cnt, rp = rp_backup)
00726                         {
00727                           era = _nl_select_era_entry (era_cnt);
00728                           if (match_string (era->era_name, rp))
00729                             {
00730                               *decided = loc;
00731                               break;
00732                             }
00733                         }
00734                       if (era_cnt == (int) num_eras)
00735                         {
00736                           era_cnt = -1;
00737                           if (*decided == loc)
00738                             return NULL;
00739                         }
00740                       else
00741                         break;
00742                     }
00743 
00744                   *decided = raw;
00745                 }
00746               /* The C locale has no era information, so use the
00747                  normal representation.  */
00748               goto match_century;
00749             case 'y':
00750               if (*decided == raw)
00751                 goto match_year_in_century;
00752 
00753               get_number(0, 9999, 4);
00754               tm->tm_year = val;
00755               want_era = 1;
00756               want_xday = 1;
00757               break;
00758             case 'Y':
00759               if (*decided != raw)
00760                 {
00761                   num_eras = _NL_CURRENT_WORD (LC_TIME,
00762                                                _NL_TIME_ERA_NUM_ENTRIES);
00763                   for (era_cnt = 0; era_cnt < (int) num_eras;
00764                        ++era_cnt, rp = rp_backup)
00765                     {
00766                       era = _nl_select_era_entry (era_cnt);
00767                       if (recursive (era->era_format))
00768                         break;
00769                     }
00770                   if (era_cnt == (int) num_eras)
00771                     {
00772                       era_cnt = -1;
00773                       if (*decided == loc)
00774                         return NULL;
00775                       else
00776                         rp = rp_backup;
00777                     }
00778                   else
00779                     {
00780                       *decided = loc;
00781                       era_cnt = -1;
00782                       break;
00783                     }
00784 
00785                   *decided = raw;
00786                 }
00787               get_number (0, 9999, 4);
00788               tm->tm_year = val - 1900;
00789               want_century = 0;
00790               want_xday = 1;
00791               break;
00792             case 'x':
00793               if (*decided != raw)
00794                 {
00795                   const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_FMT);
00796 
00797                   if (*fmt == '\0')
00798                     fmt = _NL_CURRENT (LC_TIME, D_FMT);
00799 
00800                   if (!recursive (fmt))
00801                     {
00802                       if (*decided == loc)
00803                         return NULL;
00804                       else
00805                         rp = rp_backup;
00806                     }
00807                   else
00808                     {
00809                       if (strcmp (fmt, HERE_D_FMT))
00810                         *decided = loc;
00811                       break;
00812                     }
00813                   *decided = raw;
00814                 }
00815               if (!recursive (HERE_D_FMT))
00816                 return NULL;
00817               break;
00818             case 'X':
00819               if (*decided != raw)
00820                 {
00821                   const char *fmt = _NL_CURRENT (LC_TIME, ERA_T_FMT);
00822 
00823                   if (*fmt == '\0')
00824                     fmt = _NL_CURRENT (LC_TIME, T_FMT);
00825 
00826                   if (!recursive (fmt))
00827                     {
00828                       if (*decided == loc)
00829                         return NULL;
00830                       else
00831                         rp = rp_backup;
00832                     }
00833                   else
00834                     {
00835                       if (strcmp (fmt, HERE_T_FMT))
00836                         *decided = loc;
00837                       break;
00838                     }
00839                   *decided = raw;
00840                 }
00841               if (!recursive (HERE_T_FMT))
00842                 return NULL;
00843               break;
00844             default:
00845               return NULL;
00846             }
00847           break;
00848 #else
00849           /* We have no information about the era format.  Just use
00850              the normal format.  */
00851           if (*fmt != 'c' && *fmt != 'C' && *fmt != 'y' && *fmt != 'Y'
00852               && *fmt != 'x' && *fmt != 'X')
00853             /* This is an illegal format.  */
00854             return NULL;
00855 
00856           goto start_over;
00857 #endif
00858         case 'O':
00859           switch (*fmt++)
00860             {
00861             case 'd':
00862             case 'e':
00863               /* Match day of month using alternate numeric symbols.  */
00864               get_alt_number (1, 31, 2);
00865               tm->tm_mday = val;
00866               have_mday = 1;
00867               want_xday = 1;
00868               break;
00869             case 'H':
00870               /* Match hour in 24-hour clock using alternate numeric
00871                  symbols.  */
00872               get_alt_number (0, 23, 2);
00873               tm->tm_hour = val;
00874               have_I = 0;
00875               break;
00876             case 'I':
00877               /* Match hour in 12-hour clock using alternate numeric
00878                  symbols.  */
00879               get_alt_number (1, 12, 2);
00880               tm->tm_hour = val - 1;
00881               have_I = 1;
00882               break;
00883             case 'm':
00884               /* Match month using alternate numeric symbols.  */
00885               get_alt_number (1, 12, 2);
00886               tm->tm_mon = val - 1;
00887               have_mon = 1;
00888               want_xday = 1;
00889               break;
00890             case 'M':
00891               /* Match minutes using alternate numeric symbols.  */
00892               get_alt_number (0, 59, 2);
00893               tm->tm_min = val;
00894               break;
00895             case 'S':
00896               /* Match seconds using alternate numeric symbols.  */
00897               get_alt_number (0, 61, 2);
00898               tm->tm_sec = val;
00899               break;
00900             case 'U':
00901             case 'V':
00902             case 'W':
00903               get_alt_number (0, 53, 2);
00904               /* XXX This cannot determine any field in TM without
00905                  further information.  */
00906               break;
00907             case 'w':
00908               /* Match number of weekday using alternate numeric symbols.  */
00909               get_alt_number (0, 6, 1);
00910               tm->tm_wday = val;
00911               have_wday = 1;
00912               break;
00913             case 'y':
00914               /* Match year within century using alternate numeric symbols.  */
00915               get_alt_number (0, 99, 2);
00916               tm->tm_year = val >= 69 ? val : val + 100;
00917               want_xday = 1;
00918               break;
00919             default:
00920               return NULL;
00921             }
00922           break;
00923         default:
00924           return NULL;
00925         }
00926     }
00927 
00928   if (have_I && is_pm)
00929     tm->tm_hour += 12;
00930 
00931   if (century != -1)
00932     {
00933       if (want_century)
00934         tm->tm_year = tm->tm_year % 100 + (century - 19) * 100;
00935       else
00936         /* Only the century, but not the year.  Strange, but so be it.  */
00937         tm->tm_year = (century - 19) * 100;
00938     }
00939 
00940 #ifdef _NL_CURRENT
00941   if (era_cnt != -1)
00942     {
00943       era = _nl_select_era_entry(era_cnt);
00944       if (want_era)
00945         tm->tm_year = (era->start_date[0]
00946                        + ((tm->tm_year - era->offset)
00947                           * era->absolute_direction));
00948       else
00949         /* Era start year assumed.  */
00950         tm->tm_year = era->start_date[0];
00951     }
00952   else
00953 #endif
00954     if (want_era)
00955       return NULL;
00956 
00957   if (want_xday && !have_wday)
00958     {
00959       if ( !(have_mon && have_mday) && have_yday)
00960         {
00961           /* We don't have tm_mon and/or tm_mday, compute them.  */
00962           int t_mon = 0;
00963           while (__mon_yday[__isleap(1900 + tm->tm_year)][t_mon] <= tm->tm_yday)
00964               t_mon++;
00965           if (!have_mon)
00966               tm->tm_mon = t_mon - 1;
00967           if (!have_mday)
00968               tm->tm_mday =
00969                 (tm->tm_yday
00970                  - __mon_yday[__isleap(1900 + tm->tm_year)][t_mon - 1] + 1);
00971         }
00972       day_of_the_week (tm);
00973     }
00974   if (want_xday && !have_yday)
00975     day_of_the_year (tm);
00976 
00977   return discard_const_p(char, rp);
00978 }
00979 
00980 
00981 char *rep_strptime(const char *buf, const char *format, struct tm *tm)
00982 {
00983   enum locale_status decided;
00984 
00985 #ifdef _NL_CURRENT
00986   decided = not;
00987 #else
00988   decided = raw;
00989 #endif
00990   return strptime_internal (buf, format, tm, &decided, -1);
00991 }

Sambaに対してSat Aug 29 21:22:59 2009に生成されました。  doxygen 1.4.7