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

strftime.c

解説を見る。
00001 /* Copyright (C) 1991, 92, 93, 94, 95, 96 Free Software Foundation, Inc.
00002 
00003    NOTE: The canonical source of this file is maintained with the GNU C
00004    Library.  Bugs can be reported to bug-glibc@gnu.org.
00005 
00006    This program is free software; you can redistribute it and/or modify it
00007    under the terms of the GNU General Public License as published by the
00008    Free Software Foundation; either version 2, or (at your option) any
00009    later version.
00010 
00011    This program 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
00014    GNU General Public License for more details.
00015 
00016    You should have received a copy of the GNU General Public License
00017    along with this program; if not, write to the Free Software Foundation,
00018    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
00019 
00020 #ifdef HAVE_CONFIG_H
00021 # include <config.h>
00022 #endif
00023 
00024 #ifndef HAVE_STRFTIME
00025 
00026 #ifdef _LIBC
00027 # define HAVE_LIMITS_H 1
00028 # define HAVE_MBLEN 1
00029 # define HAVE_MBRLEN 1
00030 # define HAVE_STRUCT_ERA_ENTRY 1
00031 # define HAVE_TM_GMTOFF 1
00032 # define HAVE_STRUCT_TM_TM_ZONE 1
00033 # define MULTIBYTE_IS_FORMAT_SAFE 1
00034 # define STDC_HEADERS 1
00035 # include <ansidecl.h>
00036 # include "../locale/localeinfo.h"
00037 #endif
00038 
00039 #include <sys/types.h>          /* Some systems define `time_t' here.  */
00040 
00041 #ifdef TIME_WITH_SYS_TIME
00042 # include <sys/time.h>
00043 # include <time.h>
00044 #else
00045 # ifdef HAVE_SYS_TIME_H
00046 #  include <sys/time.h>
00047 # else
00048 #  include <time.h>
00049 # endif
00050 #endif
00051 
00052 #if HAVE_TZNAME
00053 extern char *tzname[];
00054 #endif
00055 
00056 /* Do multibyte processing if multibytes are supported, unless
00057    multibyte sequences are safe in formats.  Multibyte sequences are
00058    safe if they cannot contain byte sequences that look like format
00059    conversion specifications.  The GNU C Library uses UTF8 multibyte
00060    encoding, which is safe for formats, but strftime.c can be used
00061    with other C libraries that use unsafe encodings.  */
00062 #define DO_MULTIBYTE (HAVE_MBLEN && ! MULTIBYTE_IS_FORMAT_SAFE)
00063 
00064 #if DO_MULTIBYTE
00065 # if HAVE_MBRLEN
00066 #  include <wchar.h>
00067 # else
00068    /* Simulate mbrlen with mblen as best we can.  */
00069 #  define mbstate_t int
00070 #  define mbrlen(s, n, ps) mblen (s, n)
00071 #  define mbsinit(ps) (*(ps) == 0)
00072 # endif
00073   static const mbstate_t mbstate_zero;
00074 #endif
00075 
00076 #if HAVE_LIMITS_H
00077 # include <limits.h>
00078 #endif
00079 
00080 #if STDC_HEADERS
00081 # include <stddef.h>
00082 # include <stdlib.h>
00083 # include <string.h>
00084 #else
00085 # define memcpy(d, s, n) bcopy (s, d, n)
00086 #endif
00087 
00088 #ifndef __P
00089 #if defined (__GNUC__) || (defined (__STDC__) && __STDC__)
00090 #define __P(args) args
00091 #else
00092 #define __P(args) ()
00093 #endif  /* GCC.  */
00094 #endif  /* Not __P.  */
00095 
00096 #ifndef PTR
00097 #ifdef __STDC__
00098 #define PTR void *
00099 #else
00100 #define PTR char *
00101 #endif
00102 #endif
00103 
00104 #ifndef CHAR_BIT
00105 #define CHAR_BIT 8
00106 #endif
00107 
00108 #define TYPE_SIGNED(t) ((t) -1 < 0)
00109 
00110 /* Bound on length of the string representing an integer value of type t.
00111    Subtract one for the sign bit if t is signed;
00112    302 / 1000 is log10 (2) rounded up;
00113    add one for integer division truncation;
00114    add one more for a minus sign if t is signed.  */
00115 #define INT_STRLEN_BOUND(t) \
00116   ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 100 + 1 + TYPE_SIGNED (t))
00117 
00118 #define TM_YEAR_BASE 1900
00119 
00120 #ifndef __isleap
00121 /* Nonzero if YEAR is a leap year (every 4 years,
00122    except every 100th isn't, and every 400th is).  */
00123 #define __isleap(year)  \
00124   ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
00125 #endif
00126 
00127 
00128 #ifdef _LIBC
00129 # define gmtime_r __gmtime_r
00130 # define localtime_r __localtime_r
00131 #else
00132 # if ! HAVE_LOCALTIME_R
00133 #  if ! HAVE_TM_GMTOFF
00134 /* Approximate gmtime_r as best we can in its absence.  */
00135 #define gmtime_r my_gmtime_r
00136 static struct tm *gmtime_r __P ((const time_t *, struct tm *));
00137 static struct tm *
00138 gmtime_r (t, tp)
00139      const time_t *t;
00140      struct tm *tp;
00141 {
00142   struct tm *l = gmtime (t);
00143   if (! l)
00144     return 0;
00145   *tp = *l;
00146   return tp;
00147 }
00148 #  endif /* ! HAVE_TM_GMTOFF */
00149 
00150 /* Approximate localtime_r as best we can in its absence.  */
00151 #define localtime_r my_localtime_r
00152 static struct tm *localtime_r __P ((const time_t *, struct tm *));
00153 static struct tm *
00154 localtime_r (t, tp)
00155      const time_t *t;
00156      struct tm *tp;
00157 {
00158   struct tm *l = localtime (t);
00159   if (! l)
00160     return 0;
00161   *tp = *l;
00162   return tp;
00163 }
00164 # endif /* ! HAVE_LOCALTIME_R */
00165 #endif /* ! defined (_LIBC) */
00166 
00167 
00168 #define add(n, f)                                                             \
00169   do                                                                          \
00170     {                                                                         \
00171       i += (n);                                                               \
00172       if (i >= maxsize)                                                       \
00173         return 0;                                                             \
00174       else                                                                    \
00175         if (p)                                                                \
00176           {                                                                   \
00177             f;                                                                \
00178             p += (n);                                                         \
00179           }                                                                   \
00180     } while (0)
00181 #define cpy(n, s)       add ((n), memcpy((PTR) p, (PTR) (s), (n)))
00182 
00183 #if ! HAVE_TM_GMTOFF
00184 /* Yield the difference between *A and *B,
00185    measured in seconds, ignoring leap seconds.  */
00186 static int tm_diff __P ((const struct tm *, const struct tm *));
00187 static int
00188 tm_diff (a, b)
00189      const struct tm *a;
00190      const struct tm *b;
00191 {
00192   /* Compute intervening leap days correctly even if year is negative.
00193      Take care to avoid int overflow in leap day calculations,
00194      but it's OK to assume that A and B are close to each other.  */
00195   int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3);
00196   int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3);
00197   int a100 = a4 / 25 - (a4 % 25 < 0);
00198   int b100 = b4 / 25 - (b4 % 25 < 0);
00199   int a400 = a100 >> 2;
00200   int b400 = b100 >> 2;
00201   int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
00202   int years = a->tm_year - b->tm_year;
00203   int days = (365 * years + intervening_leap_days
00204               + (a->tm_yday - b->tm_yday));
00205   return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
00206                 + (a->tm_min - b->tm_min))
00207           + (a->tm_sec - b->tm_sec));
00208 }
00209 #endif /* ! HAVE_TM_GMTOFF */
00210 
00211 
00212 
00213 /* The number of days from the first day of the first ISO week of this
00214    year to the year day YDAY with week day WDAY.  ISO weeks start on
00215    Monday; the first ISO week has the year's first Thursday.  YDAY may
00216    be as small as YDAY_MINIMUM.  */
00217 #define ISO_WEEK_START_WDAY 1 /* Monday */
00218 #define ISO_WEEK1_WDAY 4 /* Thursday */
00219 #define YDAY_MINIMUM (-366)
00220 static int iso_week_days __P ((int, int));
00221 #ifdef __GNUC__
00222 inline
00223 #endif
00224 static int
00225 iso_week_days (yday, wday)
00226      int yday;
00227      int wday;
00228 {
00229   /* Add enough to the first operand of % to make it nonnegative.  */
00230   int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
00231   return (yday
00232           - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
00233           + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
00234 }
00235 
00236 
00237 #ifndef _NL_CURRENT
00238 static char const weekday_name[][10] =
00239   {
00240     "Sunday", "Monday", "Tuesday", "Wednesday",
00241     "Thursday", "Friday", "Saturday"
00242   };
00243 static char const month_name[][10] =
00244   {
00245     "January", "February", "March", "April", "May", "June",
00246     "July", "August", "September", "October", "November", "December"
00247   };
00248 #endif
00249 
00250 /* Write information from TP into S according to the format
00251    string FORMAT, writing no more that MAXSIZE characters
00252    (including the terminating '\0') and returning number of
00253    characters written.  If S is NULL, nothing will be written
00254    anywhere, so to determine how many characters would be
00255    written, use NULL for S and (size_t) UINT_MAX for MAXSIZE.  */
00256 size_t
00257 strftime (s, maxsize, format, tp)
00258       char *s;
00259       size_t maxsize;
00260       const char *format;
00261       register const struct tm *tp;
00262 {
00263   int hour12 = tp->tm_hour;
00264 #ifdef _NL_CURRENT
00265   const char *const a_wkday = _NL_CURRENT (LC_TIME, ABDAY_1 + tp->tm_wday);
00266   const char *const f_wkday = _NL_CURRENT (LC_TIME, DAY_1 + tp->tm_wday);
00267   const char *const a_month = _NL_CURRENT (LC_TIME, ABMON_1 + tp->tm_mon);
00268   const char *const f_month = _NL_CURRENT (LC_TIME, MON_1 + tp->tm_mon);
00269   const char *const ampm = _NL_CURRENT (LC_TIME,
00270                                         hour12 > 11 ? PM_STR : AM_STR);
00271   size_t aw_len = strlen (a_wkday);
00272   size_t am_len = strlen (a_month);
00273   size_t ap_len = strlen (ampm);
00274 #else
00275   const char *const f_wkday = weekday_name[tp->tm_wday];
00276   const char *const f_month = month_name[tp->tm_mon];
00277   const char *const a_wkday = f_wkday;
00278   const char *const a_month = f_month;
00279   const char *const ampm = "AMPM" + 2 * (hour12 > 11);
00280   size_t aw_len = 3;
00281   size_t am_len = 3;
00282   size_t ap_len = 2;
00283 #endif
00284   size_t wkday_len = strlen (f_wkday);
00285   size_t month_len = strlen (f_month);
00286   const char *zone;
00287   size_t zonelen;
00288   register size_t i = 0;
00289   register char *p = s;
00290   register const char *f;
00291 
00292   zone = 0;
00293 #if HAVE_STRUCT_TM_TM_ZONE
00294   zone = (const char *) tp->tm_zone;
00295 #endif
00296 #if HAVE_TZNAME
00297   if (!(zone && *zone) && tp->tm_isdst >= 0)
00298     zone = tzname[tp->tm_isdst];
00299 #endif
00300   if (! zone)
00301     zone = "";          /* POSIX.2 requires the empty string here.  */
00302 
00303   zonelen = strlen (zone);
00304 
00305   if (hour12 > 12)
00306     hour12 -= 12;
00307   else
00308     if (hour12 == 0) hour12 = 12;
00309 
00310   for (f = format; *f != '\0'; ++f)
00311     {
00312       int pad;                  /* Padding for number ('-', '_', or 0).  */
00313       int modifier;             /* Field modifier ('E', 'O', or 0).  */
00314       int digits;               /* Max digits for numeric format.  */
00315       int number_value;         /* Numeric value to be printed.  */
00316       int negative_number;      /* 1 if the number is negative.  */
00317       const char *subfmt;
00318       char *bufp;
00319       char buf[1 + (sizeof (int) < sizeof (time_t)
00320                     ? INT_STRLEN_BOUND (time_t)
00321                     : INT_STRLEN_BOUND (int))];
00322 
00323 #if DO_MULTIBYTE
00324 
00325        switch (*f)
00326         {
00327         case '%':
00328           break;
00329 
00330         case '\a': case '\b': case '\t': case '\n':
00331         case '\v': case '\f': case '\r':
00332         case ' ': case '!': case '"': case '#': case '&': case'\'':
00333         case '(': case ')': case '*': case '+': case ',': case '-':
00334         case '.': case '/': case '0': case '1': case '2': case '3':
00335         case '4': case '5': case '6': case '7': case '8': case '9':
00336         case ':': case ';': case '<': case '=': case '>': case '?':
00337         case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
00338         case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
00339         case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
00340         case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
00341         case 'Y': case 'Z': case '[': case'\\': case ']': case '^':
00342         case '_': case 'a': case 'b': case 'c': case 'd': case 'e':
00343         case 'f': case 'g': case 'h': case 'i': case 'j': case 'k':
00344         case 'l': case 'm': case 'n': case 'o': case 'p': case 'q':
00345         case 'r': case 's': case 't': case 'u': case 'v': case 'w':
00346         case 'x': case 'y': case 'z': case '{': case '|': case '}':
00347         case '~':
00348           /* The C Standard requires these 98 characters (plus '%') to
00349              be in the basic execution character set.  None of these
00350              characters can start a multibyte sequence, so they need
00351              not be analyzed further.  */
00352           add (1, *p = *f);
00353           continue;
00354 
00355         default:
00356           /* Copy this multibyte sequence until we reach its end, find
00357              an error, or come back to the initial shift state.  */
00358           {
00359             mbstate_t mbstate = mbstate_zero;
00360             size_t len = 0;
00361 
00362             do
00363               {
00364                 size_t bytes = mbrlen (f + len, (size_t) -1, &mbstate);
00365 
00366                 if (bytes == 0)
00367                   break;
00368 
00369                 if (bytes == (size_t) -2 || bytes == (size_t) -1)
00370                   {
00371                     len++;
00372                     break;
00373                   }
00374 
00375                 len += bytes;
00376               }
00377             while (! mbsinit (&mbstate));
00378 
00379             cpy (len, f);
00380             continue;
00381           }
00382         }
00383 
00384 #else /* ! DO_MULTIBYTE */
00385 
00386       /* Either multibyte encodings are not supported, or they are
00387          safe for formats, so any non-'%' byte can be copied through.  */
00388       if (*f != '%')
00389         {
00390           add (1, *p = *f);
00391           continue;
00392         }
00393 
00394 #endif /* ! DO_MULTIBYTE */
00395 
00396       /* Check for flags that can modify a number format.  */
00397       ++f;
00398       switch (*f)
00399         {
00400         case '_':
00401         case '-':
00402           pad = *f++;
00403           break;
00404 
00405         default:
00406           pad = 0;
00407           break;
00408         }
00409 
00410       /* Check for modifiers.  */
00411       switch (*f)
00412         {
00413         case 'E':
00414         case 'O':
00415           modifier = *f++;
00416           break;
00417 
00418         default:
00419           modifier = 0;
00420           break;
00421         }
00422 
00423       /* Now do the specified format.  */
00424       switch (*f)
00425         {
00426 #define DO_NUMBER(d, v) \
00427           digits = d; number_value = v; goto do_number
00428 #define DO_NUMBER_SPACEPAD(d, v) \
00429           digits = d; number_value = v; goto do_number_spacepad
00430 
00431         case '%':
00432           if (modifier != 0)
00433             goto bad_format;
00434           add (1, *p = *f);
00435           break;
00436 
00437         case 'a':
00438           if (modifier != 0)
00439             goto bad_format;
00440           cpy (aw_len, a_wkday);
00441           break;
00442 
00443         case 'A':
00444           if (modifier != 0)
00445             goto bad_format;
00446           cpy (wkday_len, f_wkday);
00447           break;
00448 
00449         case 'b':
00450         case 'h':               /* POSIX.2 extension.  */
00451           if (modifier != 0)
00452             goto bad_format;
00453           cpy (am_len, a_month);
00454           break;
00455 
00456         case 'B':
00457           if (modifier != 0)
00458             goto bad_format;
00459           cpy (month_len, f_month);
00460           break;
00461 
00462         case 'c':
00463           if (modifier == 'O')
00464             goto bad_format;
00465 #ifdef _NL_CURRENT
00466           if (! (modifier == 'E'
00467                  && *(subfmt = _NL_CURRENT (LC_TIME, ERA_D_T_FMT)) != '\0'))
00468             subfmt = _NL_CURRENT (LC_TIME, D_T_FMT);
00469 #else
00470           subfmt = "%a %b %e %H:%M:%S %Y";
00471 #endif
00472 
00473         subformat:
00474           {
00475             size_t len = strftime (p, maxsize - i, subfmt, tp);
00476             if (len == 0 && *subfmt)
00477               return 0;
00478             add (len, ;);
00479           }
00480           break;
00481 
00482         case 'C':               /* POSIX.2 extension.  */
00483           if (modifier == 'O')
00484             goto bad_format;
00485 #if HAVE_STRUCT_ERA_ENTRY
00486           if (modifier == 'E')
00487             {
00488               struct era_entry *era = _nl_get_era_entry (tp);
00489               if (era)
00490                 {
00491                   size_t len = strlen (era->name_fmt);
00492                   cpy (len, era->name_fmt);
00493                   break;
00494                 }
00495             }
00496 #endif
00497           {
00498             int year = tp->tm_year + TM_YEAR_BASE;
00499             DO_NUMBER (1, year / 100 - (year % 100 < 0));
00500           }
00501 
00502         case 'x':
00503           if (modifier == 'O')
00504             goto bad_format;
00505 #ifdef _NL_CURRENT
00506           if (! (modifier == 'E'
00507                  && *(subfmt = _NL_CURRENT (LC_TIME, ERA_D_FMT)) != '\0'))
00508             subfmt = _NL_CURRENT (LC_TIME, D_FMT);
00509           goto subformat;
00510 #endif
00511           /* Fall through.  */
00512         case 'D':               /* POSIX.2 extension.  */
00513           if (modifier != 0)
00514             goto bad_format;
00515           subfmt = "%m/%d/%y";
00516           goto subformat;
00517 
00518         case 'd':
00519           if (modifier == 'E')
00520             goto bad_format;
00521 
00522           DO_NUMBER (2, tp->tm_mday);
00523 
00524         case 'e':               /* POSIX.2 extension.  */
00525           if (modifier == 'E')
00526             goto bad_format;
00527 
00528           DO_NUMBER_SPACEPAD (2, tp->tm_mday);
00529 
00530           /* All numeric formats set DIGITS and NUMBER_VALUE and then
00531              jump to one of these two labels.  */
00532 
00533         do_number_spacepad:
00534           /* Force `_' flag.  */
00535           pad = '_';
00536 
00537         do_number:
00538           /* Format the number according to the MODIFIER flag.  */
00539 
00540 #ifdef _NL_CURRENT
00541           if (modifier == 'O' && 0 <= number_value)
00542             {
00543               /* Get the locale specific alternate representation of
00544                  the number NUMBER_VALUE.  If none exist NULL is returned.  */
00545               const char *cp = _nl_get_alt_digit (number_value);
00546 
00547               if (cp != NULL)
00548                 {
00549                   size_t digitlen = strlen (cp);
00550                   if (digitlen != 0)
00551                     {
00552                       cpy (digitlen, cp);
00553                       break;
00554                     }
00555                 }
00556             }
00557 #endif
00558           {
00559             unsigned int u = number_value;
00560 
00561             bufp = buf + sizeof (buf);
00562             negative_number = number_value < 0;
00563 
00564             if (negative_number)
00565               u = -u;
00566 
00567             do
00568               *--bufp = u % 10 + '0';
00569             while ((u /= 10) != 0);
00570           }
00571 
00572         do_number_sign_and_padding:
00573           if (negative_number)
00574             *--bufp = '-';
00575 
00576           if (pad != '-')
00577             {
00578               int padding = digits - (buf + sizeof (buf) - bufp);
00579 
00580               if (pad == '_')
00581                 {
00582                   while (0 < padding--)
00583                     *--bufp = ' ';
00584                 }
00585               else
00586                 {
00587                   bufp += negative_number;
00588                   while (0 < padding--)
00589                     *--bufp = '0';
00590                   if (negative_number)
00591                     *--bufp = '-';
00592                 }
00593             }
00594 
00595           cpy (buf + sizeof (buf) - bufp, bufp);
00596           break;
00597 
00598 
00599         case 'H':
00600           if (modifier == 'E')
00601             goto bad_format;
00602 
00603           DO_NUMBER (2, tp->tm_hour);
00604 
00605         case 'I':
00606           if (modifier == 'E')
00607             goto bad_format;
00608 
00609           DO_NUMBER (2, hour12);
00610 
00611         case 'k':               /* GNU extension.  */
00612           if (modifier == 'E')
00613             goto bad_format;
00614 
00615           DO_NUMBER_SPACEPAD (2, tp->tm_hour);
00616 
00617         case 'l':               /* GNU extension.  */
00618           if (modifier == 'E')
00619             goto bad_format;
00620 
00621           DO_NUMBER_SPACEPAD (2, hour12);
00622 
00623         case 'j':
00624           if (modifier == 'E')
00625             goto bad_format;
00626 
00627           DO_NUMBER (3, 1 + tp->tm_yday);
00628 
00629         case 'M':
00630           if (modifier == 'E')
00631             goto bad_format;
00632 
00633           DO_NUMBER (2, tp->tm_min);
00634 
00635         case 'm':
00636           if (modifier == 'E')
00637             goto bad_format;
00638 
00639           DO_NUMBER (2, tp->tm_mon + 1);
00640 
00641         case 'n':               /* POSIX.2 extension.  */
00642           add (1, *p = '\n');
00643           break;
00644 
00645         case 'p':
00646           cpy (ap_len, ampm);
00647           break;
00648 
00649         case 'R':               /* GNU extension.  */
00650           subfmt = "%H:%M";
00651           goto subformat;
00652 
00653         case 'r':               /* POSIX.2 extension.  */
00654 #ifdef _NL_CURRENT
00655           if (*(subfmt = _NL_CURRENT (LC_TIME, T_FMT_AMPM)) == '\0')
00656 #endif
00657             subfmt = "%I:%M:%S %p";
00658           goto subformat;
00659 
00660         case 'S':
00661           if (modifier == 'E')
00662             goto bad_format;
00663 
00664           DO_NUMBER (2, tp->tm_sec);
00665 
00666         case 's':               /* GNU extension.  */
00667           {
00668             struct tm ltm;
00669             time_t t;
00670 
00671             ltm = *tp;
00672             t = mktime (&ltm);
00673 
00674             /* Generate string value for T using time_t arithmetic;
00675                this works even if sizeof (long) < sizeof (time_t).  */
00676 
00677             bufp = buf + sizeof (buf);
00678             negative_number = t < 0;
00679 
00680             do
00681               {
00682                 int d = t % 10;
00683                 t /= 10;
00684 
00685                 if (negative_number)
00686                   {
00687                     d = -d;
00688 
00689                     /* Adjust if division truncates to minus infinity.  */
00690                     if (0 < -1 % 10 && d < 0)
00691                       {
00692                         t++;
00693                         d += 10;
00694                       }
00695                   }
00696 
00697                 *--bufp = d + '0';
00698               }
00699             while (t != 0);
00700 
00701             digits = 1;
00702             goto do_number_sign_and_padding;
00703           }
00704 
00705         case 'X':
00706           if (modifier == 'O')
00707             goto bad_format;
00708 #ifdef _NL_CURRENT
00709           if (! (modifier == 'E'
00710                  && *(subfmt = _NL_CURRENT (LC_TIME, ERA_T_FMT)) != '\0'))
00711             subfmt = _NL_CURRENT (LC_TIME, T_FMT);
00712           goto subformat;
00713 #endif
00714           /* Fall through.  */
00715         case 'T':               /* POSIX.2 extension.  */
00716           subfmt = "%H:%M:%S";
00717           goto subformat;
00718 
00719         case 't':               /* POSIX.2 extension.  */
00720           add (1, *p = '\t');
00721           break;
00722 
00723         case 'u':               /* POSIX.2 extension.  */
00724           DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
00725 
00726         case 'U':
00727           if (modifier == 'E')
00728             goto bad_format;
00729 
00730           DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
00731 
00732         case 'V':
00733         case 'g':               /* GNU extension.  */
00734         case 'G':               /* GNU extension.  */
00735           if (modifier == 'E')
00736             goto bad_format;
00737           {
00738             int year = tp->tm_year + TM_YEAR_BASE;
00739             int days = iso_week_days (tp->tm_yday, tp->tm_wday);
00740 
00741             if (days < 0)
00742               {
00743                 /* This ISO week belongs to the previous year.  */
00744                 year--;
00745                 days = iso_week_days (tp->tm_yday + (365 + __isleap (year)),
00746                                       tp->tm_wday);
00747               }
00748             else
00749               {
00750                 int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
00751                                        tp->tm_wday);
00752                 if (0 <= d)
00753                   {
00754                     /* This ISO week belongs to the next year.  */
00755                     year++;
00756                     days = d;
00757                   }
00758               }
00759 
00760             switch (*f)
00761               {
00762               case 'g':
00763                 DO_NUMBER (2, (year % 100 + 100) % 100);
00764 
00765               case 'G':
00766                 DO_NUMBER (1, year);
00767 
00768               default:
00769                 DO_NUMBER (2, days / 7 + 1);
00770               }
00771           }
00772 
00773         case 'W':
00774           if (modifier == 'E')
00775             goto bad_format;
00776 
00777           DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
00778 
00779         case 'w':
00780           if (modifier == 'E')
00781             goto bad_format;
00782 
00783           DO_NUMBER (1, tp->tm_wday);
00784 
00785         case 'Y':
00786 #if HAVE_STRUCT_ERA_ENTRY
00787           if (modifier == 'E')
00788             {
00789               struct era_entry *era = _nl_get_era_entry (tp);
00790               if (era)
00791                 {
00792                   subfmt = strchr (era->name_fmt, '\0') + 1;
00793                   goto subformat;
00794                 }
00795             }
00796 #endif
00797           if (modifier == 'O')
00798             goto bad_format;
00799           else
00800             DO_NUMBER (1, tp->tm_year + TM_YEAR_BASE);
00801 
00802         case 'y':
00803 #if HAVE_STRUCT_ERA_ENTRY
00804           if (modifier == 'E')
00805             {
00806               struct era_entry *era = _nl_get_era_entry (tp);
00807               if (era)
00808                 {
00809                   int delta = tp->tm_year - era->start_date[0];
00810                   DO_NUMBER (1, (era->offset
00811                                  + (era->direction == '-' ? -delta : delta)));
00812                 }
00813             }
00814 #endif
00815           DO_NUMBER (2, (tp->tm_year % 100 + 100) % 100);
00816 
00817         case 'Z':
00818           cpy (zonelen, zone);
00819           break;
00820 
00821         case 'z':               /* GNU extension.  */
00822           if (tp->tm_isdst < 0)
00823             break;
00824 
00825           {
00826             int diff;
00827 #if HAVE_TM_GMTOFF
00828             diff = tp->tm_gmtoff;
00829 #else
00830             struct tm gtm;
00831             struct tm ltm;
00832             time_t lt;
00833 
00834             ltm = *tp;
00835             lt = mktime (&ltm);
00836 
00837             if (lt == (time_t) -1)
00838               {
00839                 /* mktime returns -1 for errors, but -1 is also a
00840                    valid time_t value.  Check whether an error really
00841                    occurred.  */
00842                 struct tm tm;
00843                 localtime_r (&lt, &tm);
00844 
00845                 if ((ltm.tm_sec ^ tm.tm_sec)
00846                     | (ltm.tm_min ^ tm.tm_min)
00847                     | (ltm.tm_hour ^ tm.tm_hour)
00848                     | (ltm.tm_mday ^ tm.tm_mday)
00849                     | (ltm.tm_mon ^ tm.tm_mon)
00850                     | (ltm.tm_year ^ tm.tm_year))
00851                   break;
00852               }
00853 
00854             if (! gmtime_r (&lt, &gtm))
00855               break;
00856 
00857             diff = tm_diff (&ltm, &gtm);
00858 #endif
00859 
00860             if (diff < 0)
00861               {
00862                 add (1, *p = '-');
00863                 diff = -diff;
00864               }
00865             else
00866               add (1, *p = '+');
00867 
00868             diff /= 60;
00869             DO_NUMBER (4, (diff / 60) * 100 + diff % 60);
00870           }
00871 
00872         case '\0':              /* GNU extension: % at end of format.  */
00873             --f;
00874             /* Fall through.  */
00875         default:
00876           /* Unknown format; output the format, including the '%',
00877              since this is most likely the right thing to do if a
00878              multibyte string has been misparsed.  */
00879         bad_format:
00880           {
00881             int flen;
00882             for (flen = 1; f[1 - flen] != '%'; flen++)
00883               continue;
00884             cpy (flen, &f[1 - flen]);
00885           }
00886           break;
00887         }
00888     }
00889 
00890   if (p)
00891     *p = '\0';
00892   return i;
00893 }
00894 
00895 #endif

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