メインページ   クラス階層   構成   ファイル一覧   構成メンバ   ファイルメンバ  

strptime.c

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

Wed Dec 29 11:52:20 2004に生成されました。 doxygen1.2.18
SEO [PR] 爆速!無料ブログ 無料ホームページ開設 無料ライブ放送