~peter-pearse/ubuntu/natty/diffutils/prop001

« back to all changes in this revision

Viewing changes to lib/strftime.c

  • Committer: Bazaar Package Importer
  • Author(s): Santiago Vila
  • Date: 2010-05-04 20:38:00 UTC
  • mfrom: (2.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20100504203800-f67xd9rsa9xl9qqj
Tags: 1:3.0-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 1991-1999, 2000, 2001 Free Software Foundation, Inc.
 
1
/* Copyright (C) 1991-2001, 2003-2007, 2009-2010 Free Software Foundation, Inc.
2
2
 
3
3
   NOTE: The canonical source of this file is maintained with the GNU C Library.
4
4
   Bugs can be reported to bug-glibc@prep.ai.mit.edu.
5
5
 
6
 
   This program is free software; you can redistribute it and/or modify it
7
 
   under the terms of the GNU General Public License as published by the
8
 
   Free Software Foundation; either version 2, or (at your option) any
9
 
   later version.
 
6
   This program is free software: you can redistribute it and/or modify
 
7
   it under the terms of the GNU General Public License as published by
 
8
   the Free Software Foundation; either version 3 of the License, or
 
9
   (at your option) any later version.
10
10
 
11
11
   This program is distributed in the hope that it will be useful,
12
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 
   Library General Public License for more details.
 
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
   GNU General Public License for more details.
15
15
 
16
16
   You should have received a copy of the GNU General Public License
17
 
   along with this program; if not, write to the Free Software
18
 
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19
 
   USA.  */
20
 
 
21
 
#ifdef HAVE_CONFIG_H
22
 
# include <config.h>
23
 
#endif
 
17
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
24
18
 
25
19
#ifdef _LIBC
26
 
# define HAVE_LIMITS_H 1
27
 
# define HAVE_MBLEN 1
28
 
# define HAVE_MBRLEN 1
29
20
# define HAVE_STRUCT_ERA_ENTRY 1
30
21
# define HAVE_TM_GMTOFF 1
31
22
# define HAVE_TM_ZONE 1
32
23
# define HAVE_TZNAME 1
33
24
# define HAVE_TZSET 1
34
 
# define MULTIBYTE_IS_FORMAT_SAFE 1
35
 
# define STDC_HEADERS 1
36
25
# include "../locale/localeinfo.h"
37
 
#endif
38
 
 
39
 
#if defined emacs && !defined HAVE_BCOPY
40
 
# define HAVE_MEMCPY 1
 
26
#else
 
27
# include <config.h>
 
28
# if FPRINTFTIME
 
29
#  include "ignore-value.h"
 
30
#  include "fprintftime.h"
 
31
# else
 
32
#  include "strftime.h"
 
33
# endif
41
34
#endif
42
35
 
43
36
#include <ctype.h>
44
 
#include <sys/types.h>          /* Some systems define `time_t' here.  */
 
37
#include <time.h>
45
38
 
46
 
#ifdef TIME_WITH_SYS_TIME
47
 
# include <sys/time.h>
48
 
# include <time.h>
49
 
#else
50
 
# ifdef HAVE_SYS_TIME_H
51
 
#  include <sys/time.h>
52
 
# else
53
 
#  include <time.h>
54
 
# endif
55
 
#endif
56
 
#if HAVE_TZNAME
 
39
#if HAVE_TZNAME && !HAVE_DECL_TZNAME
57
40
extern char *tzname[];
58
41
#endif
59
42
 
60
43
/* Do multibyte processing if multibytes are supported, unless
61
44
   multibyte sequences are safe in formats.  Multibyte sequences are
62
45
   safe if they cannot contain byte sequences that look like format
63
 
   conversion specifications.  The GNU C Library uses UTF8 multibyte
64
 
   encoding, which is safe for formats, but strftime.c can be used
65
 
   with other C libraries that use unsafe encodings.  */
66
 
#define DO_MULTIBYTE (HAVE_MBLEN && ! MULTIBYTE_IS_FORMAT_SAFE)
 
46
   conversion specifications.  The multibyte encodings used by the
 
47
   C library on the various platforms (UTF-8, GB2312, GBK, CP936,
 
48
   GB18030, EUC-TW, BIG5, BIG5-HKSCS, CP950, EUC-JP, EUC-KR, CP949,
 
49
   SHIFT_JIS, CP932, JOHAB) are safe for formats, because the byte '%'
 
50
   cannot occur in a multibyte character except in the first byte.
 
51
   But this does not hold for the DEC-HANYU encoding used on OSF/1.  */
 
52
#if !defined __osf__
 
53
# define MULTIBYTE_IS_FORMAT_SAFE 1
 
54
#endif
 
55
#define DO_MULTIBYTE (! MULTIBYTE_IS_FORMAT_SAFE)
67
56
 
68
57
#if DO_MULTIBYTE
69
 
# if HAVE_MBRLEN
70
 
#  include <wchar.h>
71
 
# else
72
 
   /* Simulate mbrlen with mblen as best we can.  */
73
 
#  define mbstate_t int
74
 
#  define mbrlen(s, n, ps) mblen (s, n)
75
 
#  define mbsinit(ps) (*(ps) == 0)
76
 
# endif
 
58
# include <wchar.h>
77
59
  static const mbstate_t mbstate_zero;
78
60
#endif
79
61
 
80
 
#if HAVE_LIMITS_H
81
 
# include <limits.h>
82
 
#endif
83
 
 
84
 
#if STDC_HEADERS
85
 
# include <stddef.h>
86
 
# include <stdlib.h>
87
 
# include <string.h>
88
 
#else
89
 
# ifndef HAVE_MEMCPY
90
 
#  define memcpy(d, s, n) bcopy ((s), (d), (n))
91
 
# endif
92
 
#endif
 
62
#include <limits.h>
 
63
#include <stdbool.h>
 
64
#include <stddef.h>
 
65
#include <stdlib.h>
 
66
#include <string.h>
93
67
 
94
68
#ifdef COMPILE_WIDE
95
69
# include <endian.h>
107
81
# define L_(Str) Str
108
82
# define NLW(Sym) Sym
109
83
 
110
 
# if !defined STDC_HEADERS && !defined HAVE_MEMCPY
111
 
#  define MEMCPY(d, s, n) bcopy ((s), (d), (n))
112
 
# else
113
 
#  define MEMCPY(d, s, n) memcpy ((d), (s), (n))
114
 
# endif
 
84
# define MEMCPY(d, s, n) memcpy (d, s, n)
115
85
# define STRLEN(s) strlen (s)
116
86
 
117
 
# ifdef _LIBC
118
 
#  define MEMPCPY(d, s, n) __mempcpy (d, s, n)
119
 
# else
120
 
#  ifndef HAVE_MEMPCPY
121
 
#   define MEMPCPY(d, s, n) ((void *) ((char *) memcpy (d, s, n) + (n)))
122
 
#  endif
123
 
# endif
124
 
#endif
125
 
 
126
 
#ifndef __P
127
 
# if defined __GNUC__ || (defined __STDC__ && __STDC__)
128
 
#  define __P(args) args
129
 
# else
130
 
#  define __P(args) ()
131
 
# endif  /* GCC.  */
132
 
#endif  /* Not __P.  */
133
 
 
134
 
#ifndef PTR
135
 
# ifdef __STDC__
136
 
#  define PTR void *
137
 
# else
138
 
#  define PTR char *
139
 
# endif
140
 
#endif
141
 
 
142
 
#ifndef CHAR_BIT
143
 
# define CHAR_BIT 8
144
 
#endif
145
 
 
146
 
#ifndef NULL
147
 
# define NULL 0
148
 
#endif
149
 
 
150
 
#define TYPE_SIGNED(t) ((t) -1 < 0)
151
 
 
152
 
/* Bound on length of the string representing an integer value of type t.
153
 
   Subtract one for the sign bit if t is signed;
154
 
   302 / 1000 is log10 (2) rounded up;
155
 
   add one for integer division truncation;
156
 
   add one more for a minus sign if t is signed.  */
 
87
#endif
 
88
 
 
89
/* Shift A right by B bits portably, by dividing A by 2**B and
 
90
   truncating towards minus infinity.  A and B should be free of side
 
91
   effects, and B should be in the range 0 <= B <= INT_BITS - 2, where
 
92
   INT_BITS is the number of useful bits in an int.  GNU code can
 
93
   assume that INT_BITS is at least 32.
 
94
 
 
95
   ISO C99 says that A >> B is implementation-defined if A < 0.  Some
 
96
   implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift
 
97
   right in the usual way when A < 0, so SHR falls back on division if
 
98
   ordinary A >> B doesn't seem to be the usual signed shift.  */
 
99
#define SHR(a, b)       \
 
100
  (-1 >> 1 == -1        \
 
101
   ? (a) >> (b)         \
 
102
   : (a) / (1 << (b)) - ((a) % (1 << (b)) < 0))
 
103
 
 
104
/* Bound on length of the string representing an integer type or expression T.
 
105
   Subtract 1 for the sign bit if t is signed; log10 (2.0) < 146/485;
 
106
   add 1 for integer division truncation; add 1 more for a minus sign
 
107
   if needed.  */
157
108
#define INT_STRLEN_BOUND(t) \
158
 
 ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 + 1 + TYPE_SIGNED (t))
 
109
  ((sizeof (t) * CHAR_BIT - 1) * 146 / 485 + 2)
159
110
 
160
111
#define TM_YEAR_BASE 1900
161
112
 
162
113
#ifndef __isleap
163
114
/* Nonzero if YEAR is a leap year (every 4 years,
164
115
   except every 100th isn't, and every 400th is).  */
165
 
# define __isleap(year) \
 
116
# define __isleap(year) \
166
117
  ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
167
118
#endif
168
119
 
169
120
 
170
121
#ifdef _LIBC
171
 
# define my_strftime_gmtime_r __gmtime_r
172
 
# define my_strftime_localtime_r __localtime_r
173
122
# define tzname __tzname
174
123
# define tzset __tzset
175
 
#else
176
 
 
177
 
/* If we're a strftime substitute in a GNU program, then prefer gmtime
178
 
   to gmtime_r, since many gmtime_r implementations are buggy.
179
 
   Similarly for localtime_r.  */
180
 
 
181
 
# if ! HAVE_TM_GMTOFF
182
 
static struct tm *my_strftime_gmtime_r __P ((const time_t *, struct tm *));
183
 
static struct tm *
184
 
my_strftime_gmtime_r (t, tp)
185
 
     const time_t *t;
186
 
     struct tm *tp;
187
 
{
188
 
  struct tm *l = gmtime (t);
189
 
  if (! l)
190
 
    return 0;
191
 
  *tp = *l;
192
 
  return tp;
193
 
}
194
 
 
195
 
static struct tm *my_strftime_localtime_r __P ((const time_t *, struct tm *));
196
 
static struct tm *
197
 
my_strftime_localtime_r (t, tp)
198
 
     const time_t *t;
199
 
     struct tm *tp;
200
 
{
201
 
  struct tm *l = localtime (t);
202
 
  if (! l)
203
 
    return 0;
204
 
  *tp = *l;
205
 
  return tp;
206
 
}
207
 
# endif /* ! HAVE_TM_GMTOFF */
208
 
#endif /* ! defined _LIBC */
209
 
 
210
 
 
211
 
#if !defined memset && !defined HAVE_MEMSET && !defined _LIBC
212
 
/* Some systems lack the `memset' function and we don't want to
213
 
   introduce additional dependencies.  */
214
 
/* The SGI compiler reportedly barfs on the trailing null
215
 
   if we use a string constant as the initializer.  28 June 1997, rms.  */
216
 
static const CHAR_T spaces[16] = /* "                " */
217
 
{
218
 
  L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),
219
 
  L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' ')
220
 
};
221
 
static const CHAR_T zeroes[16] = /* "0000000000000000" */
222
 
{
223
 
  L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),
224
 
  L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0')
225
 
};
226
 
 
227
 
# define memset_space(P, Len) \
228
 
  do {                                                                        \
229
 
    int _len = (Len);                                                         \
230
 
                                                                              \
231
 
    do                                                                        \
232
 
      {                                                                       \
233
 
        int _this = _len > 16 ? 16 : _len;                                    \
234
 
        (P) = MEMPCPY ((P), spaces, _this * sizeof (CHAR_T));                 \
235
 
        _len -= _this;                                                        \
236
 
      }                                                                       \
237
 
    while (_len > 0);                                                         \
238
 
  } while (0)
239
 
 
240
 
# define memset_zero(P, Len) \
241
 
  do {                                                                        \
242
 
    int _len = (Len);                                                         \
243
 
                                                                              \
244
 
    do                                                                        \
245
 
      {                                                                       \
246
 
        int _this = _len > 16 ? 16 : _len;                                    \
247
 
        (P) = MEMPCPY ((P), zeroes, _this * sizeof (CHAR_T));                 \
248
 
        _len -= _this;                                                        \
249
 
      }                                                                       \
250
 
    while (_len > 0);                                                         \
251
 
  } while (0)
252
 
#else
253
 
# ifdef COMPILE_WIDE
254
 
#  define memset_space(P, Len) (wmemset ((P), L' ', (Len)), (P) += (Len))
255
 
#  define memset_zero(P, Len) (wmemset ((P), L'0', (Len)), (P) += (Len))
256
 
# else
257
 
#  define memset_space(P, Len) (memset ((P), ' ', (Len)), (P) += (Len))
258
 
#  define memset_zero(P, Len) (memset ((P), '0', (Len)), (P) += (Len))
259
 
# endif
260
 
#endif
261
 
 
262
 
#define add(n, f)                                                             \
263
 
  do                                                                          \
264
 
    {                                                                         \
265
 
      int _n = (n);                                                           \
266
 
      int _delta = width - _n;                                                \
267
 
      int _incr = _n + (_delta > 0 ? _delta : 0);                             \
268
 
      if (i + _incr >= maxsize)                                               \
269
 
        return 0;                                                             \
270
 
      if (p)                                                                  \
271
 
        {                                                                     \
272
 
          if (_delta > 0)                                                     \
273
 
            {                                                                 \
274
 
              if (pad == L_('0'))                                             \
275
 
                memset_zero (p, _delta);                                      \
276
 
              else                                                            \
277
 
                memset_space (p, _delta);                                     \
278
 
            }                                                                 \
279
 
          f;                                                                  \
280
 
          p += _n;                                                            \
281
 
        }                                                                     \
282
 
      i += _incr;                                                             \
 
124
#endif
 
125
 
 
126
#if !HAVE_TM_GMTOFF
 
127
/* Portable standalone applications should supply a "time.h" that
 
128
   declares a POSIX-compliant localtime_r, for the benefit of older
 
129
   implementations that lack localtime_r or have a nonstandard one.
 
130
   See the gnulib time_r module for one way to implement this.  */
 
131
# undef __gmtime_r
 
132
# undef __localtime_r
 
133
# define __gmtime_r gmtime_r
 
134
# define __localtime_r localtime_r
 
135
#endif
 
136
 
 
137
 
 
138
#ifndef FPRINTFTIME
 
139
# define FPRINTFTIME 0
 
140
#endif
 
141
 
 
142
#if FPRINTFTIME
 
143
# define STREAM_OR_CHAR_T FILE
 
144
# define STRFTIME_ARG(x) /* empty */
 
145
#else
 
146
# define STREAM_OR_CHAR_T CHAR_T
 
147
# define STRFTIME_ARG(x) x,
 
148
#endif
 
149
 
 
150
#if FPRINTFTIME
 
151
# define memset_byte(P, Len, Byte) \
 
152
  do { size_t _i; for (_i = 0; _i < Len; _i++) fputc (Byte, P); } while (0)
 
153
# define memset_space(P, Len) memset_byte (P, Len, ' ')
 
154
# define memset_zero(P, Len) memset_byte (P, Len, '0')
 
155
#elif defined COMPILE_WIDE
 
156
# define memset_space(P, Len) (wmemset (P, L' ', Len), (P) += (Len))
 
157
# define memset_zero(P, Len) (wmemset (P, L'0', Len), (P) += (Len))
 
158
#else
 
159
# define memset_space(P, Len) (memset (P, ' ', Len), (P) += (Len))
 
160
# define memset_zero(P, Len) (memset (P, '0', Len), (P) += (Len))
 
161
#endif
 
162
 
 
163
#if FPRINTFTIME
 
164
# define advance(P, N)
 
165
#else
 
166
# define advance(P, N) ((P) += (N))
 
167
#endif
 
168
 
 
169
#define add(n, f)                                                             \
 
170
  do                                                                          \
 
171
    {                                                                         \
 
172
      int _n = (n);                                                           \
 
173
      int _delta = width - _n;                                                \
 
174
      int _incr = _n + (_delta > 0 ? _delta : 0);                             \
 
175
      if ((size_t) _incr >= maxsize - i)                                      \
 
176
        return 0;                                                             \
 
177
      if (p)                                                                  \
 
178
        {                                                                     \
 
179
          if (digits == 0 && _delta > 0)                                      \
 
180
            {                                                                 \
 
181
              if (pad == L_('0'))                                             \
 
182
                memset_zero (p, _delta);                                      \
 
183
              else                                                            \
 
184
                memset_space (p, _delta);                                     \
 
185
            }                                                                 \
 
186
          f;                                                                  \
 
187
          advance (p, _n);                                                    \
 
188
        }                                                                     \
 
189
      i += _incr;                                                             \
283
190
    } while (0)
284
191
 
285
 
#define cpy(n, s) \
286
 
    add ((n),                                                                 \
287
 
         if (to_lowcase)                                                      \
288
 
           memcpy_lowcase (p, (s), _n);                                       \
289
 
         else if (to_uppcase)                                                 \
290
 
           memcpy_uppcase (p, (s), _n);                                       \
291
 
         else                                                                 \
292
 
           MEMCPY ((PTR) p, (const PTR) (s), _n))
 
192
#if FPRINTFTIME
 
193
# define add1(C) add (1, fputc (C, p))
 
194
#else
 
195
# define add1(C) add (1, *p = C)
 
196
#endif
 
197
 
 
198
#if FPRINTFTIME
 
199
# define cpy(n, s) \
 
200
    add ((n),                                                                 \
 
201
     do                                                                       \
 
202
       {                                                                      \
 
203
         if (to_lowcase)                                                      \
 
204
           fwrite_lowcase (p, (s), _n);                                       \
 
205
         else if (to_uppcase)                                                 \
 
206
           fwrite_uppcase (p, (s), _n);                                       \
 
207
         else                                                                 \
 
208
           {                                                                  \
 
209
             /* We are ignoring the value of fwrite here, in spite of the     \
 
210
                fact that technically, that may not be valid: the fwrite      \
 
211
                specification in POSIX 2008 defers to that of fputc, which    \
 
212
                is intended to be consistent with the one from ISO C,         \
 
213
                which permits failure due to ENOMEM *without* setting the     \
 
214
                stream's error indicator.  */                                 \
 
215
             ignore_value (fwrite ((s), _n, 1, p));                           \
 
216
           }                                                                  \
 
217
       }                                                                      \
 
218
     while (0)                                                                \
 
219
    )
 
220
#else
 
221
# define cpy(n, s)                                                            \
 
222
    add ((n),                                                                 \
 
223
         if (to_lowcase)                                                      \
 
224
           memcpy_lowcase (p, (s), _n LOCALE_ARG);                            \
 
225
         else if (to_uppcase)                                                 \
 
226
           memcpy_uppcase (p, (s), _n LOCALE_ARG);                            \
 
227
         else                                                                 \
 
228
           MEMCPY ((void *) p, (void const *) (s), _n))
 
229
#endif
293
230
 
294
231
#ifdef COMPILE_WIDE
 
232
# ifndef USE_IN_EXTENDED_LOCALE_MODEL
 
233
#  undef __mbsrtowcs_l
 
234
#  define __mbsrtowcs_l(d, s, l, st, loc) __mbsrtowcs (d, s, l, st)
 
235
# endif
295
236
# define widen(os, ws, l) \
296
 
  {                                                                           \
297
 
    mbstate_t __st;                                                           \
298
 
    const char *__s = os;                                                     \
299
 
    memset (&__st, '\0', sizeof (__st));                                      \
300
 
    l = __mbsrtowcs (NULL, &__s, 0, &__st);                                   \
301
 
    ws = alloca ((l + 1) * sizeof (wchar_t));                                 \
302
 
    (void) __mbsrtowcs (ws, &__s, l, &__st);                                  \
 
237
  {                                                                           \
 
238
    mbstate_t __st;                                                           \
 
239
    const char *__s = os;                                                     \
 
240
    memset (&__st, '\0', sizeof (__st));                                      \
 
241
    l = __mbsrtowcs_l (NULL, &__s, 0, &__st, loc);                            \
 
242
    ws = (wchar_t *) alloca ((l + 1) * sizeof (wchar_t));                     \
 
243
    (void) __mbsrtowcs_l (ws, &__s, l, &__st, loc);                           \
303
244
  }
304
245
#endif
305
246
 
306
247
 
 
248
#if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
 
249
/* We use this code also for the extended locale handling where the
 
250
   function gets as an additional argument the locale which has to be
 
251
   used.  To access the values we have to redefine the _NL_CURRENT
 
252
   macro.  */
 
253
# define strftime               __strftime_l
 
254
# define wcsftime               __wcsftime_l
 
255
# undef _NL_CURRENT
 
256
# define _NL_CURRENT(category, item) \
 
257
  (current->values[_NL_ITEM_INDEX (item)].string)
 
258
# define LOCALE_ARG , loc
 
259
# define LOCALE_PARAM_PROTO , __locale_t loc
 
260
# define HELPER_LOCALE_ARG  , current
 
261
#else
 
262
# define LOCALE_PARAM_PROTO
 
263
# define LOCALE_ARG
 
264
# ifdef _LIBC
 
265
#  define HELPER_LOCALE_ARG , _NL_CURRENT_DATA (LC_TIME)
 
266
# else
 
267
#  define HELPER_LOCALE_ARG
 
268
# endif
 
269
#endif
 
270
 
307
271
#ifdef COMPILE_WIDE
308
 
# define TOUPPER(Ch) towupper (Ch)
309
 
# define TOLOWER(Ch) towlower (Ch)
 
272
# ifdef USE_IN_EXTENDED_LOCALE_MODEL
 
273
#  define TOUPPER(Ch, L) __towupper_l (Ch, L)
 
274
#  define TOLOWER(Ch, L) __towlower_l (Ch, L)
 
275
# else
 
276
#  define TOUPPER(Ch, L) towupper (Ch)
 
277
#  define TOLOWER(Ch, L) towlower (Ch)
 
278
# endif
310
279
#else
311
 
# ifdef _LIBC
312
 
#  define TOUPPER(Ch) toupper (Ch)
313
 
#  define TOLOWER(Ch) tolower (Ch)
 
280
# ifdef USE_IN_EXTENDED_LOCALE_MODEL
 
281
#  define TOUPPER(Ch, L) __toupper_l (Ch, L)
 
282
#  define TOLOWER(Ch, L) __tolower_l (Ch, L)
314
283
# else
315
 
#  define TOUPPER(Ch) (islower (Ch) ? toupper (Ch) : (Ch))
316
 
#  define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
 
284
#  define TOUPPER(Ch, L) toupper (Ch)
 
285
#  define TOLOWER(Ch, L) tolower (Ch)
317
286
# endif
318
287
#endif
319
288
/* We don't use `isdigit' here since the locale dependent
322
291
   more reliable way to accept other sets of digits.  */
323
292
#define ISDIGIT(Ch) ((unsigned int) (Ch) - L_('0') <= 9)
324
293
 
325
 
static CHAR_T *memcpy_lowcase __P ((CHAR_T *dest, const CHAR_T *src,
326
 
                                    size_t len));
327
 
 
328
 
static CHAR_T *
329
 
memcpy_lowcase (dest, src, len)
330
 
     CHAR_T *dest;
331
 
     const CHAR_T *src;
332
 
     size_t len;
333
 
{
334
 
  while (len-- > 0)
335
 
    dest[len] = TOLOWER ((UCHAR_T) src[len]);
336
 
  return dest;
337
 
}
338
 
 
339
 
static CHAR_T *memcpy_uppcase __P ((CHAR_T *dest, const CHAR_T *src,
340
 
                                    size_t len));
341
 
 
342
 
static CHAR_T *
343
 
memcpy_uppcase (dest, src, len)
344
 
     CHAR_T *dest;
345
 
     const CHAR_T *src;
346
 
     size_t len;
347
 
{
348
 
  while (len-- > 0)
349
 
    dest[len] = TOUPPER ((UCHAR_T) src[len]);
350
 
  return dest;
351
 
}
 
294
#if FPRINTFTIME
 
295
static void
 
296
fwrite_lowcase (FILE *fp, const CHAR_T *src, size_t len)
 
297
{
 
298
  while (len-- > 0)
 
299
    {
 
300
      fputc (TOLOWER ((UCHAR_T) *src, loc), fp);
 
301
      ++src;
 
302
    }
 
303
}
 
304
 
 
305
static void
 
306
fwrite_uppcase (FILE *fp, const CHAR_T *src, size_t len)
 
307
{
 
308
  while (len-- > 0)
 
309
    {
 
310
      fputc (TOUPPER ((UCHAR_T) *src, loc), fp);
 
311
      ++src;
 
312
    }
 
313
}
 
314
#else
 
315
static CHAR_T *
 
316
memcpy_lowcase (CHAR_T *dest, const CHAR_T *src,
 
317
                size_t len LOCALE_PARAM_PROTO)
 
318
{
 
319
  while (len-- > 0)
 
320
    dest[len] = TOLOWER ((UCHAR_T) src[len], loc);
 
321
  return dest;
 
322
}
 
323
 
 
324
static CHAR_T *
 
325
memcpy_uppcase (CHAR_T *dest, const CHAR_T *src,
 
326
                size_t len LOCALE_PARAM_PROTO)
 
327
{
 
328
  while (len-- > 0)
 
329
    dest[len] = TOUPPER ((UCHAR_T) src[len], loc);
 
330
  return dest;
 
331
}
 
332
#endif
352
333
 
353
334
 
354
335
#if ! HAVE_TM_GMTOFF
355
336
/* Yield the difference between *A and *B,
356
337
   measured in seconds, ignoring leap seconds.  */
357
338
# define tm_diff ftime_tm_diff
358
 
static int tm_diff __P ((const struct tm *, const struct tm *));
359
339
static int
360
 
tm_diff (a, b)
361
 
     const struct tm *a;
362
 
     const struct tm *b;
 
340
tm_diff (const struct tm *a, const struct tm *b)
363
341
{
364
342
  /* Compute intervening leap days correctly even if year is negative.
365
343
     Take care to avoid int overflow in leap day calculations,
366
344
     but it's OK to assume that A and B are close to each other.  */
367
 
  int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3);
368
 
  int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3);
 
345
  int a4 = SHR (a->tm_year, 2) + SHR (TM_YEAR_BASE, 2) - ! (a->tm_year & 3);
 
346
  int b4 = SHR (b->tm_year, 2) + SHR (TM_YEAR_BASE, 2) - ! (b->tm_year & 3);
369
347
  int a100 = a4 / 25 - (a4 % 25 < 0);
370
348
  int b100 = b4 / 25 - (b4 % 25 < 0);
371
 
  int a400 = a100 >> 2;
372
 
  int b400 = b100 >> 2;
 
349
  int a400 = SHR (a100, 2);
 
350
  int b400 = SHR (b100, 2);
373
351
  int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
374
352
  int years = a->tm_year - b->tm_year;
375
353
  int days = (365 * years + intervening_leap_days
376
 
              + (a->tm_yday - b->tm_yday));
 
354
              + (a->tm_yday - b->tm_yday));
377
355
  return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
378
 
                + (a->tm_min - b->tm_min))
379
 
          + (a->tm_sec - b->tm_sec));
 
356
                + (a->tm_min - b->tm_min))
 
357
          + (a->tm_sec - b->tm_sec));
380
358
}
381
359
#endif /* ! HAVE_TM_GMTOFF */
382
360
 
389
367
#define ISO_WEEK_START_WDAY 1 /* Monday */
390
368
#define ISO_WEEK1_WDAY 4 /* Thursday */
391
369
#define YDAY_MINIMUM (-366)
392
 
static int iso_week_days __P ((int, int));
393
370
#ifdef __GNUC__
394
371
__inline__
395
372
#endif
396
373
static int
397
 
iso_week_days (yday, wday)
398
 
     int yday;
399
 
     int wday;
 
374
iso_week_days (int yday, int wday)
400
375
{
401
376
  /* Add enough to the first operand of % to make it nonnegative.  */
402
377
  int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
403
378
  return (yday
404
 
          - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
405
 
          + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
 
379
          - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
 
380
          + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
406
381
}
407
382
 
408
383
 
409
 
#if !(defined _NL_CURRENT || HAVE_STRFTIME)
410
 
static CHAR_T const weekday_name[][10] =
411
 
  {
412
 
    L_("Sunday"), L_("Monday"), L_("Tuesday"), L_("Wednesday"),
413
 
    L_("Thursday"), L_("Friday"), L_("Saturday")
414
 
  };
415
 
static CHAR_T const month_name[][10] =
416
 
  {
417
 
    L_("January"), L_("February"), L_("March"), L_("April"), L_("May"),
418
 
    L_("June"), L_("July"), L_("August"), L_("September"), L_("October"),
419
 
    L_("November"), L_("December")
420
 
  };
421
 
#endif
422
 
 
423
 
 
424
384
/* When compiling this file, GNU applications can #define my_strftime
425
385
   to a symbol (typically nstrftime) to get an extended strftime with
426
386
   extra arguments UT and NS.  Emacs is a special case for now, but
430
390
# define my_strftime nstrftime
431
391
#endif
432
392
 
 
393
#if FPRINTFTIME
 
394
# undef my_strftime
 
395
# define my_strftime fprintftime
 
396
#endif
 
397
 
433
398
#ifdef my_strftime
434
399
# define extra_args , ut, ns
435
 
# define extra_args_spec int ut; int ns;
436
 
# define extra_args_spec_iso , int ut, int ns
 
400
# define extra_args_spec , int ut, int ns
437
401
#else
438
 
# ifdef COMPILE_WIDE
 
402
# if defined COMPILE_WIDE
439
403
#  define my_strftime wcsftime
 
404
#  define nl_get_alt_digit _nl_get_walt_digit
440
405
# else
441
406
#  define my_strftime strftime
 
407
#  define nl_get_alt_digit _nl_get_alt_digit
442
408
# endif
443
409
# define extra_args
444
410
# define extra_args_spec
445
 
# define extra_args_spec_iso
446
411
/* We don't have this information in general.  */
447
412
# define ut 0
448
413
# define ns 0
449
414
#endif
450
415
 
451
 
#if !defined _LIBC && HAVE_TZNAME && HAVE_TZSET
452
 
  /* Solaris 2.5 tzset sometimes modifies the storage returned by localtime.
453
 
     Work around this bug by copying *tp before it might be munged.  */
454
 
  size_t _strftime_copytm __P ((char *, size_t, const char *,
455
 
                                const struct tm * extra_args_spec_iso));
456
 
  size_t
457
 
  my_strftime (s, maxsize, format, tp extra_args)
458
 
      CHAR_T *s;
459
 
      size_t maxsize;
460
 
      const CHAR_T *format;
461
 
      const struct tm *tp;
462
 
      extra_args_spec
463
 
  {
464
 
    struct tm tmcopy;
465
 
    tmcopy = *tp;
466
 
    return _strftime_copytm (s, maxsize, format, &tmcopy extra_args);
467
 
  }
468
 
# undef my_strftime
469
 
# define my_strftime _strftime_copytm
470
 
#endif
471
 
 
472
 
 
473
 
/* Write information from TP into S according to the format
474
 
   string FORMAT, writing no more that MAXSIZE characters
475
 
   (including the terminating '\0') and returning number of
476
 
   characters written.  If S is NULL, nothing will be written
477
 
   anywhere, so to determine how many characters would be
478
 
   written, use NULL for S and (size_t) UINT_MAX for MAXSIZE.  */
479
 
size_t
480
 
my_strftime (s, maxsize, format, tp extra_args)
481
 
      CHAR_T *s;
482
 
      size_t maxsize;
483
 
      const CHAR_T *format;
484
 
      const struct tm *tp;
485
 
      extra_args_spec
 
416
 
 
417
/* Just like my_strftime, below, but with one more parameter, UPCASE,
 
418
   to indicate that the result should be converted to upper case.  */
 
419
static size_t
 
420
strftime_case_ (bool upcase, STREAM_OR_CHAR_T *s,
 
421
                STRFTIME_ARG (size_t maxsize)
 
422
                const CHAR_T *format,
 
423
                const struct tm *tp extra_args_spec LOCALE_PARAM_PROTO)
486
424
{
 
425
#if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
 
426
  struct locale_data *const current = loc->__locales[LC_TIME];
 
427
#endif
 
428
#if FPRINTFTIME
 
429
  size_t maxsize = (size_t) -1;
 
430
#endif
 
431
 
487
432
  int hour12 = tp->tm_hour;
488
433
#ifdef _NL_CURRENT
489
434
  /* We cannot make the following values variables since we must delay
501
446
# define f_month \
502
447
  ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon))
503
448
# define ampm \
504
 
  ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11                    \
505
 
                                 ? NLW(PM_STR) : NLW(AM_STR)))
 
449
  ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11                    \
 
450
                                 ? NLW(PM_STR) : NLW(AM_STR)))
506
451
 
507
452
# define aw_len STRLEN (a_wkday)
508
453
# define am_len STRLEN (a_month)
509
454
# define ap_len STRLEN (ampm)
510
 
#else
511
 
# if !HAVE_STRFTIME
512
 
#  define f_wkday (weekday_name[tp->tm_wday])
513
 
#  define f_month (month_name[tp->tm_mon])
514
 
#  define a_wkday f_wkday
515
 
#  define a_month f_month
516
 
#  define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11))
517
 
 
518
 
  size_t aw_len = 3;
519
 
  size_t am_len = 3;
520
 
  size_t ap_len = 2;
521
 
# endif
522
455
#endif
523
456
  const char *zone;
524
457
  size_t i = 0;
525
 
  CHAR_T *p = s;
 
458
  STREAM_OR_CHAR_T *p = s;
526
459
  const CHAR_T *f;
527
460
#if DO_MULTIBYTE && !defined COMPILE_WIDE
528
461
  const char *format_end = NULL;
529
462
#endif
530
463
 
 
464
#if ! defined _LIBC && ! HAVE_RUN_TZSET_TEST
 
465
  /* Solaris 2.5.x and 2.6 tzset sometimes modify the storage returned
 
466
     by localtime.  On such systems, we must either use the tzset and
 
467
     localtime wrappers to work around the bug (which sets
 
468
     HAVE_RUN_TZSET_TEST) or make a copy of the structure.  */
 
469
  struct tm copy = *tp;
 
470
  tp = &copy;
 
471
#endif
 
472
 
531
473
  zone = NULL;
532
474
#if HAVE_TM_ZONE
533
475
  /* The POSIX test suite assumes that setting
542
484
  if (ut)
543
485
    {
544
486
      if (! (zone && *zone))
545
 
        zone = "GMT";
 
487
        zone = "GMT";
546
488
    }
547
489
  else
548
490
    {
549
 
      /* POSIX.1 8.1.1 requires that whenever strftime() is called, the
550
 
         time zone names contained in the external variable `tzname' shall
551
 
         be set as if the tzset() function had been called.  */
 
491
      /* POSIX.1 requires that local time zone information be used as
 
492
         though strftime called tzset.  */
552
493
# if HAVE_TZSET
553
494
      tzset ();
554
495
# endif
563
504
 
564
505
  for (f = format; *f != '\0'; ++f)
565
506
    {
566
 
      int pad = 0;              /* Padding for number ('-', '_', or 0).  */
567
 
      int modifier;             /* Field modifier ('E', 'O', or 0).  */
568
 
      int digits;               /* Max digits for numeric format.  */
569
 
      int number_value;         /* Numeric value to be printed.  */
570
 
      int negative_number;      /* 1 if the number is negative.  */
 
507
      int pad = 0;              /* Padding for number ('-', '_', or 0).  */
 
508
      int modifier;             /* Field modifier ('E', 'O', or 0).  */
 
509
      int digits = 0;           /* Max digits for numeric format.  */
 
510
      int number_value;         /* Numeric value to be printed.  */
 
511
      unsigned int u_number_value; /* (unsigned int) number_value.  */
 
512
      bool negative_number;     /* The number is negative.  */
 
513
      bool always_output_a_sign; /* +/- should always be output.  */
 
514
      int tz_colon_mask;        /* Bitmask of where ':' should appear.  */
571
515
      const CHAR_T *subfmt;
 
516
      CHAR_T sign_char;
572
517
      CHAR_T *bufp;
573
 
      CHAR_T buf[1 + (sizeof (int) < sizeof (time_t)
574
 
                      ? INT_STRLEN_BOUND (time_t)
575
 
                      : INT_STRLEN_BOUND (int))];
 
518
      CHAR_T buf[1
 
519
                 + 2 /* for the two colons in a %::z or %:::z time zone */
 
520
                 + (sizeof (int) < sizeof (time_t)
 
521
                    ? INT_STRLEN_BOUND (time_t)
 
522
                    : INT_STRLEN_BOUND (int))];
576
523
      int width = -1;
577
 
      int to_lowcase = 0;
578
 
      int to_uppcase = 0;
579
 
      int change_case = 0;
 
524
      bool to_lowcase = false;
 
525
      bool to_uppcase = upcase;
 
526
      size_t colons;
 
527
      bool change_case = false;
580
528
      int format_char;
581
529
 
582
530
#if DO_MULTIBYTE && !defined COMPILE_WIDE
583
531
      switch (*f)
584
 
        {
585
 
        case L_('%'):
586
 
          break;
587
 
 
588
 
        case L_('\b'): case L_('\t'): case L_('\n'):
589
 
        case L_('\v'): case L_('\f'): case L_('\r'):
590
 
        case L_(' '): case L_('!'): case L_('"'): case L_('#'): case L_('&'):
591
 
        case L_('\''): case L_('('): case L_(')'): case L_('*'): case L_('+'):
592
 
        case L_(','): case L_('-'): case L_('.'): case L_('/'): case L_('0'):
593
 
        case L_('1'): case L_('2'): case L_('3'): case L_('4'): case L_('5'):
594
 
        case L_('6'): case L_('7'): case L_('8'): case L_('9'): case L_(':'):
595
 
        case L_(';'): case L_('<'): case L_('='): case L_('>'): case L_('?'):
596
 
        case L_('A'): case L_('B'): case L_('C'): case L_('D'): case L_('E'):
597
 
        case L_('F'): case L_('G'): case L_('H'): case L_('I'): case L_('J'):
598
 
        case L_('K'): case L_('L'): case L_('M'): case L_('N'): case L_('O'):
599
 
        case L_('P'): case L_('Q'): case L_('R'): case L_('S'): case L_('T'):
600
 
        case L_('U'): case L_('V'): case L_('W'): case L_('X'): case L_('Y'):
601
 
        case L_('Z'): case L_('['): case L_('\\'): case L_(']'): case L_('^'):
602
 
        case L_('_'): case L_('a'): case L_('b'): case L_('c'): case L_('d'):
603
 
        case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'):
604
 
        case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'):
605
 
        case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'):
606
 
        case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'):
607
 
        case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'):
608
 
        case L_('~'):
609
 
          /* The C Standard requires these 98 characters (plus '%') to
610
 
             be in the basic execution character set.  None of these
611
 
             characters can start a multibyte sequence, so they need
612
 
             not be analyzed further.  */
613
 
          add (1, *p = *f);
614
 
          continue;
615
 
 
616
 
        default:
617
 
          /* Copy this multibyte sequence until we reach its end, find
618
 
             an error, or come back to the initial shift state.  */
619
 
          {
620
 
            mbstate_t mbstate = mbstate_zero;
621
 
            size_t len = 0;
622
 
            size_t fsize;
623
 
 
624
 
            if (! format_end)
625
 
              format_end = f + strlen (f) + 1;
626
 
            fsize = format_end - f;
627
 
 
628
 
            do
629
 
              {
630
 
                size_t bytes = mbrlen (f + len, fsize - len, &mbstate);
631
 
 
632
 
                if (bytes == 0)
633
 
                  break;
634
 
 
635
 
                if (bytes == (size_t) -2)
636
 
                  {
637
 
                    len += strlen (f + len);
638
 
                    break;
639
 
                  }
640
 
 
641
 
                if (bytes == (size_t) -1)
642
 
                  {
643
 
                    len++;
644
 
                    break;
645
 
                  }
646
 
 
647
 
                len += bytes;
648
 
              }
649
 
            while (! mbsinit (&mbstate));
650
 
 
651
 
            cpy (len, f);
652
 
            f += len - 1;
653
 
            continue;
654
 
          }
655
 
        }
 
532
        {
 
533
        case L_('%'):
 
534
          break;
 
535
 
 
536
        case L_('\b'): case L_('\t'): case L_('\n'):
 
537
        case L_('\v'): case L_('\f'): case L_('\r'):
 
538
        case L_(' '): case L_('!'): case L_('"'): case L_('#'): case L_('&'):
 
539
        case L_('\''): case L_('('): case L_(')'): case L_('*'): case L_('+'):
 
540
        case L_(','): case L_('-'): case L_('.'): case L_('/'): case L_('0'):
 
541
        case L_('1'): case L_('2'): case L_('3'): case L_('4'): case L_('5'):
 
542
        case L_('6'): case L_('7'): case L_('8'): case L_('9'): case L_(':'):
 
543
        case L_(';'): case L_('<'): case L_('='): case L_('>'): case L_('?'):
 
544
        case L_('A'): case L_('B'): case L_('C'): case L_('D'): case L_('E'):
 
545
        case L_('F'): case L_('G'): case L_('H'): case L_('I'): case L_('J'):
 
546
        case L_('K'): case L_('L'): case L_('M'): case L_('N'): case L_('O'):
 
547
        case L_('P'): case L_('Q'): case L_('R'): case L_('S'): case L_('T'):
 
548
        case L_('U'): case L_('V'): case L_('W'): case L_('X'): case L_('Y'):
 
549
        case L_('Z'): case L_('['): case L_('\\'): case L_(']'): case L_('^'):
 
550
        case L_('_'): case L_('a'): case L_('b'): case L_('c'): case L_('d'):
 
551
        case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'):
 
552
        case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'):
 
553
        case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'):
 
554
        case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'):
 
555
        case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'):
 
556
        case L_('~'):
 
557
          /* The C Standard requires these 98 characters (plus '%') to
 
558
             be in the basic execution character set.  None of these
 
559
             characters can start a multibyte sequence, so they need
 
560
             not be analyzed further.  */
 
561
          add1 (*f);
 
562
          continue;
 
563
 
 
564
        default:
 
565
          /* Copy this multibyte sequence until we reach its end, find
 
566
             an error, or come back to the initial shift state.  */
 
567
          {
 
568
            mbstate_t mbstate = mbstate_zero;
 
569
            size_t len = 0;
 
570
            size_t fsize;
 
571
 
 
572
            if (! format_end)
 
573
              format_end = f + strlen (f) + 1;
 
574
            fsize = format_end - f;
 
575
 
 
576
            do
 
577
              {
 
578
                size_t bytes = mbrlen (f + len, fsize - len, &mbstate);
 
579
 
 
580
                if (bytes == 0)
 
581
                  break;
 
582
 
 
583
                if (bytes == (size_t) -2)
 
584
                  {
 
585
                    len += strlen (f + len);
 
586
                    break;
 
587
                  }
 
588
 
 
589
                if (bytes == (size_t) -1)
 
590
                  {
 
591
                    len++;
 
592
                    break;
 
593
                  }
 
594
 
 
595
                len += bytes;
 
596
              }
 
597
            while (! mbsinit (&mbstate));
 
598
 
 
599
            cpy (len, f);
 
600
            f += len - 1;
 
601
            continue;
 
602
          }
 
603
        }
656
604
 
657
605
#else /* ! DO_MULTIBYTE */
658
606
 
659
607
      /* Either multibyte encodings are not supported, they are
660
 
         safe for formats, so any non-'%' byte can be copied through,
661
 
         or this is the wide character version.  */
 
608
         safe for formats, so any non-'%' byte can be copied through,
 
609
         or this is the wide character version.  */
662
610
      if (*f != L_('%'))
663
 
        {
664
 
          add (1, *p = *f);
665
 
          continue;
666
 
        }
 
611
        {
 
612
          add1 (*f);
 
613
          continue;
 
614
        }
667
615
 
668
616
#endif /* ! DO_MULTIBYTE */
669
617
 
670
618
      /* Check for flags that can modify a format.  */
671
619
      while (1)
672
 
        {
673
 
          switch (*++f)
674
 
            {
675
 
              /* This influences the number formats.  */
676
 
            case L_('_'):
677
 
            case L_('-'):
678
 
            case L_('0'):
679
 
              pad = *f;
680
 
              continue;
681
 
 
682
 
              /* This changes textual output.  */
683
 
            case L_('^'):
684
 
              to_uppcase = 1;
685
 
              continue;
686
 
            case L_('#'):
687
 
              change_case = 1;
688
 
              continue;
689
 
 
690
 
            default:
691
 
              break;
692
 
            }
693
 
          break;
694
 
        }
 
620
        {
 
621
          switch (*++f)
 
622
            {
 
623
              /* This influences the number formats.  */
 
624
            case L_('_'):
 
625
            case L_('-'):
 
626
            case L_('0'):
 
627
              pad = *f;
 
628
              continue;
 
629
 
 
630
              /* This changes textual output.  */
 
631
            case L_('^'):
 
632
              to_uppcase = true;
 
633
              continue;
 
634
            case L_('#'):
 
635
              change_case = true;
 
636
              continue;
 
637
 
 
638
            default:
 
639
              break;
 
640
            }
 
641
          break;
 
642
        }
695
643
 
696
644
      /* As a GNU extension we allow to specify the field width.  */
697
645
      if (ISDIGIT (*f))
698
 
        {
699
 
          width = 0;
700
 
          do
701
 
            {
702
 
              width *= 10;
703
 
              width += *f - L_('0');
704
 
              ++f;
705
 
            }
706
 
          while (ISDIGIT (*f));
707
 
        }
 
646
        {
 
647
          width = 0;
 
648
          do
 
649
            {
 
650
              if (width > INT_MAX / 10
 
651
                  || (width == INT_MAX / 10 && *f - L_('0') > INT_MAX % 10))
 
652
                /* Avoid overflow.  */
 
653
                width = INT_MAX;
 
654
              else
 
655
                {
 
656
                  width *= 10;
 
657
                  width += *f - L_('0');
 
658
                }
 
659
              ++f;
 
660
            }
 
661
          while (ISDIGIT (*f));
 
662
        }
708
663
 
709
664
      /* Check for modifiers.  */
710
665
      switch (*f)
711
 
        {
712
 
        case L_('E'):
713
 
        case L_('O'):
714
 
          modifier = *f++;
715
 
          break;
 
666
        {
 
667
        case L_('E'):
 
668
        case L_('O'):
 
669
          modifier = *f++;
 
670
          break;
716
671
 
717
 
        default:
718
 
          modifier = 0;
719
 
          break;
720
 
        }
 
672
        default:
 
673
          modifier = 0;
 
674
          break;
 
675
        }
721
676
 
722
677
      /* Now do the specified format.  */
723
678
      format_char = *f;
724
679
      switch (format_char)
725
 
        {
 
680
        {
726
681
#define DO_NUMBER(d, v) \
727
 
          digits = width == -1 ? d : width;                                   \
728
 
          number_value = v; goto do_number
 
682
          digits = d;                                                         \
 
683
          number_value = v; goto do_number
 
684
#define DO_SIGNED_NUMBER(d, negative, v) \
 
685
          digits = d;                                                         \
 
686
          negative_number = negative;                                         \
 
687
          u_number_value = v; goto do_signed_number
 
688
 
 
689
          /* The mask is not what you might think.
 
690
             When the ordinal i'th bit is set, insert a colon
 
691
             before the i'th digit of the time zone representation.  */
 
692
#define DO_TZ_OFFSET(d, negative, mask, v) \
 
693
          digits = d;                                                         \
 
694
          negative_number = negative;                                         \
 
695
          tz_colon_mask = mask;                                               \
 
696
          u_number_value = v; goto do_tz_offset
729
697
#define DO_NUMBER_SPACEPAD(d, v) \
730
 
          digits = width == -1 ? d : width;                                   \
731
 
          number_value = v; goto do_number_spacepad
732
 
 
733
 
        case L_('%'):
734
 
          if (modifier != 0)
735
 
            goto bad_format;
736
 
          add (1, *p = *f);
737
 
          break;
738
 
 
739
 
        case L_('a'):
740
 
          if (modifier != 0)
741
 
            goto bad_format;
742
 
          if (change_case)
743
 
            {
744
 
              to_uppcase = 1;
745
 
              to_lowcase = 0;
746
 
            }
747
 
#if defined _NL_CURRENT || !HAVE_STRFTIME
748
 
          cpy (aw_len, a_wkday);
749
 
          break;
750
 
#else
751
 
          goto underlying_strftime;
752
 
#endif
753
 
 
754
 
        case 'A':
755
 
          if (modifier != 0)
756
 
            goto bad_format;
757
 
          if (change_case)
758
 
            {
759
 
              to_uppcase = 1;
760
 
              to_lowcase = 0;
761
 
            }
762
 
#if defined _NL_CURRENT || !HAVE_STRFTIME
763
 
          cpy (STRLEN (f_wkday), f_wkday);
764
 
          break;
765
 
#else
766
 
          goto underlying_strftime;
767
 
#endif
768
 
 
769
 
        case L_('b'):
770
 
        case L_('h'):           /* POSIX.2 extension.  */
771
 
          if (change_case)
772
 
            {
773
 
              to_uppcase = 1;
774
 
              to_lowcase = 0;
775
 
            }
776
 
          if (modifier != 0)
777
 
            goto bad_format;
778
 
#if defined _NL_CURRENT || !HAVE_STRFTIME
779
 
          cpy (am_len, a_month);
780
 
          break;
781
 
#else
782
 
          goto underlying_strftime;
783
 
#endif
784
 
 
785
 
        case L_('B'):
786
 
          if (modifier != 0)
787
 
            goto bad_format;
788
 
          if (change_case)
789
 
            {
790
 
              to_uppcase = 1;
791
 
              to_lowcase = 0;
792
 
            }
793
 
#if defined _NL_CURRENT || !HAVE_STRFTIME
794
 
          cpy (STRLEN (f_month), f_month);
795
 
          break;
796
 
#else
797
 
          goto underlying_strftime;
798
 
#endif
799
 
 
800
 
        case L_('c'):
801
 
          if (modifier == L_('O'))
802
 
            goto bad_format;
803
 
#ifdef _NL_CURRENT
804
 
          if (! (modifier == 'E'
805
 
                 && (*(subfmt =
806
 
                       (const CHAR_T *) _NL_CURRENT (LC_TIME,
807
 
                                                     NLW(ERA_D_T_FMT)))
808
 
                     != '\0')))
809
 
            subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT));
810
 
#else
811
 
# if HAVE_STRFTIME
812
 
          goto underlying_strftime;
813
 
# else
814
 
          subfmt = L_("%a %b %e %H:%M:%S %Y");
815
 
# endif
816
 
#endif
817
 
 
818
 
        subformat:
819
 
          {
820
 
            CHAR_T *old_start = p;
821
 
            size_t len = my_strftime (NULL, (size_t) -1, subfmt,
822
 
                                      tp extra_args);
823
 
            add (len, my_strftime (p, maxsize - i, subfmt,
824
 
                                   tp extra_args));
825
 
 
826
 
            if (to_uppcase)
827
 
              while (old_start < p)
828
 
                {
829
 
                  *old_start = TOUPPER ((UCHAR_T) *old_start);
830
 
                  ++old_start;
831
 
                }
832
 
          }
833
 
          break;
834
 
 
835
 
#if HAVE_STRFTIME && ! (defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY)
836
 
        underlying_strftime:
837
 
          {
838
 
            /* The relevant information is available only via the
839
 
               underlying strftime implementation, so use that.  */
840
 
            char ufmt[4];
841
 
            char *u = ufmt;
842
 
            char ubuf[1024]; /* enough for any single format in practice */
843
 
            size_t len;
844
 
            /* Make sure we're calling the actual underlying strftime.
845
 
               In some cases, config.h contains something like
846
 
               "#define strftime rpl_strftime".  */
 
698
          digits = d;                                                         \
 
699
          number_value = v; goto do_number_spacepad
 
700
 
 
701
        case L_('%'):
 
702
          if (modifier != 0)
 
703
            goto bad_format;
 
704
          add1 (*f);
 
705
          break;
 
706
 
 
707
        case L_('a'):
 
708
          if (modifier != 0)
 
709
            goto bad_format;
 
710
          if (change_case)
 
711
            {
 
712
              to_uppcase = true;
 
713
              to_lowcase = false;
 
714
            }
 
715
#ifdef _NL_CURRENT
 
716
          cpy (aw_len, a_wkday);
 
717
          break;
 
718
#else
 
719
          goto underlying_strftime;
 
720
#endif
 
721
 
 
722
        case 'A':
 
723
          if (modifier != 0)
 
724
            goto bad_format;
 
725
          if (change_case)
 
726
            {
 
727
              to_uppcase = true;
 
728
              to_lowcase = false;
 
729
            }
 
730
#ifdef _NL_CURRENT
 
731
          cpy (STRLEN (f_wkday), f_wkday);
 
732
          break;
 
733
#else
 
734
          goto underlying_strftime;
 
735
#endif
 
736
 
 
737
        case L_('b'):
 
738
        case L_('h'):
 
739
          if (change_case)
 
740
            {
 
741
              to_uppcase = true;
 
742
              to_lowcase = false;
 
743
            }
 
744
          if (modifier != 0)
 
745
            goto bad_format;
 
746
#ifdef _NL_CURRENT
 
747
          cpy (am_len, a_month);
 
748
          break;
 
749
#else
 
750
          goto underlying_strftime;
 
751
#endif
 
752
 
 
753
        case L_('B'):
 
754
          if (modifier != 0)
 
755
            goto bad_format;
 
756
          if (change_case)
 
757
            {
 
758
              to_uppcase = true;
 
759
              to_lowcase = false;
 
760
            }
 
761
#ifdef _NL_CURRENT
 
762
          cpy (STRLEN (f_month), f_month);
 
763
          break;
 
764
#else
 
765
          goto underlying_strftime;
 
766
#endif
 
767
 
 
768
        case L_('c'):
 
769
          if (modifier == L_('O'))
 
770
            goto bad_format;
 
771
#ifdef _NL_CURRENT
 
772
          if (! (modifier == 'E'
 
773
                 && (*(subfmt =
 
774
                       (const CHAR_T *) _NL_CURRENT (LC_TIME,
 
775
                                                     NLW(ERA_D_T_FMT)))
 
776
                     != '\0')))
 
777
            subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT));
 
778
#else
 
779
          goto underlying_strftime;
 
780
#endif
 
781
 
 
782
        subformat:
 
783
          {
 
784
            size_t len = strftime_case_ (to_uppcase,
 
785
                                         NULL, STRFTIME_ARG ((size_t) -1)
 
786
                                         subfmt,
 
787
                                         tp extra_args LOCALE_ARG);
 
788
            add (len, strftime_case_ (to_uppcase, p,
 
789
                                      STRFTIME_ARG (maxsize - i)
 
790
                                      subfmt,
 
791
                                      tp extra_args LOCALE_ARG));
 
792
          }
 
793
          break;
 
794
 
 
795
#if !(defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY)
 
796
        underlying_strftime:
 
797
          {
 
798
            /* The relevant information is available only via the
 
799
               underlying strftime implementation, so use that.  */
 
800
            char ufmt[5];
 
801
            char *u = ufmt;
 
802
            char ubuf[1024]; /* enough for any single format in practice */
 
803
            size_t len;
 
804
            /* Make sure we're calling the actual underlying strftime.
 
805
               In some cases, config.h contains something like
 
806
               "#define strftime rpl_strftime".  */
847
807
# ifdef strftime
848
808
#  undef strftime
849
 
            size_t strftime ();
850
 
# endif
851
 
 
852
 
            *u++ = '%';
853
 
            if (modifier != 0)
854
 
              *u++ = modifier;
855
 
            *u++ = format_char;
856
 
            *u = '\0';
857
 
            len = strftime (ubuf, sizeof ubuf, ufmt, tp);
858
 
            if (len == 0 && ubuf[0] != '\0')
859
 
              return 0;
860
 
            cpy (len, ubuf);
861
 
          }
862
 
          break;
863
 
#endif
864
 
 
865
 
        case L_('C'):           /* POSIX.2 extension.  */
866
 
          if (modifier == L_('O'))
867
 
            goto bad_format;
868
 
          if (modifier == L_('E'))
869
 
            {
870
 
#if HAVE_STRUCT_ERA_ENTRY
871
 
              struct era_entry *era = _nl_get_era_entry (tp);
872
 
              if (era)
873
 
                {
874
 
# ifdef COMPILE_WIDE
875
 
                  size_t len = __wcslen (era->era_wname);
876
 
                  cpy (len, era->era_wname);
877
 
# else
878
 
                  size_t len = strlen (era->era_name);
879
 
                  cpy (len, era->era_name);
880
 
# endif
881
 
                  break;
882
 
                }
883
 
#else
884
 
# if HAVE_STRFTIME
885
 
              goto underlying_strftime;
886
 
# endif
887
 
#endif
888
 
            }
889
 
 
890
 
          {
891
 
            int year = tp->tm_year + TM_YEAR_BASE;
892
 
            DO_NUMBER (1, year / 100 - (year % 100 < 0));
893
 
          }
894
 
 
895
 
        case L_('x'):
896
 
          if (modifier == L_('O'))
897
 
            goto bad_format;
898
 
#ifdef _NL_CURRENT
899
 
          if (! (modifier == L_('E')
900
 
                 && (*(subfmt =
901
 
                       (const CHAR_T *)_NL_CURRENT (LC_TIME, NLW(ERA_D_FMT)))
902
 
                     != L_('\0'))))
903
 
            subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
904
 
          goto subformat;
905
 
#else
906
 
# if HAVE_STRFTIME
907
 
          goto underlying_strftime;
908
 
# else
909
 
          /* Fall through.  */
910
 
# endif
911
 
#endif
912
 
        case L_('D'):           /* POSIX.2 extension.  */
913
 
          if (modifier != 0)
914
 
            goto bad_format;
915
 
          subfmt = L_("%m/%d/%y");
916
 
          goto subformat;
917
 
 
918
 
        case L_('d'):
919
 
          if (modifier == L_('E'))
920
 
            goto bad_format;
921
 
 
922
 
          DO_NUMBER (2, tp->tm_mday);
923
 
 
924
 
        case L_('e'):           /* POSIX.2 extension.  */
925
 
          if (modifier == L_('E'))
926
 
            goto bad_format;
927
 
 
928
 
          DO_NUMBER_SPACEPAD (2, tp->tm_mday);
929
 
 
930
 
          /* All numeric formats set DIGITS and NUMBER_VALUE and then
931
 
             jump to one of these two labels.  */
932
 
 
933
 
        do_number_spacepad:
934
 
          /* Force `_' flag unless overwritten by `0' flag.  */
935
 
          if (pad != L_('0'))
936
 
            pad = L_('_');
937
 
 
938
 
        do_number:
939
 
          /* Format the number according to the MODIFIER flag.  */
940
 
 
941
 
          if (modifier == L_('O') && 0 <= number_value)
942
 
            {
943
 
#ifdef _NL_CURRENT
944
 
              /* Get the locale specific alternate representation of
945
 
                 the number NUMBER_VALUE.  If none exist NULL is returned.  */
946
 
# ifdef COMPILE_WIDE
947
 
              const wchar_t *cp = _nl_get_walt_digit (number_value);
948
 
# else
949
 
              const char *cp = _nl_get_alt_digit (number_value);
950
 
# endif
951
 
 
952
 
              if (cp != NULL)
953
 
                {
954
 
                  size_t digitlen = STRLEN (cp);
955
 
                  if (digitlen != 0)
956
 
                    {
957
 
                      cpy (digitlen, cp);
958
 
                      break;
959
 
                    }
960
 
                }
961
 
#else
962
 
# if HAVE_STRFTIME
963
 
              goto underlying_strftime;
964
 
# endif
965
 
#endif
966
 
            }
967
 
          {
968
 
            unsigned int u = number_value;
969
 
 
970
 
            bufp = buf + sizeof (buf) / sizeof (buf[0]);
971
 
            negative_number = number_value < 0;
972
 
 
973
 
            if (negative_number)
974
 
              u = -u;
975
 
 
976
 
            do
977
 
              *--bufp = u % 10 + L_('0');
978
 
            while ((u /= 10) != 0);
979
 
          }
980
 
 
981
 
        do_number_sign_and_padding:
982
 
          if (negative_number)
983
 
            *--bufp = L_('-');
984
 
 
985
 
          if (pad != L_('-'))
986
 
            {
987
 
              int padding = digits - (buf + (sizeof (buf) / sizeof (buf[0]))
988
 
                                      - bufp);
989
 
 
990
 
              if (pad == L_('_'))
991
 
                {
992
 
                  while (0 < padding--)
993
 
                    *--bufp = L_(' ');
994
 
                }
995
 
              else
996
 
                {
997
 
                  bufp += negative_number;
998
 
                  while (0 < padding--)
999
 
                    *--bufp = L_('0');
1000
 
                  if (negative_number)
1001
 
                    *--bufp = L_('-');
1002
 
                }
1003
 
            }
1004
 
 
1005
 
          cpy (buf + sizeof (buf) / sizeof (buf[0]) - bufp, bufp);
1006
 
          break;
1007
 
 
1008
 
        case L_('F'):
1009
 
          if (modifier != 0)
1010
 
            goto bad_format;
1011
 
          subfmt = L_("%Y-%m-%d");
1012
 
          goto subformat;
1013
 
 
1014
 
        case L_('H'):
1015
 
          if (modifier == L_('E'))
1016
 
            goto bad_format;
1017
 
 
1018
 
          DO_NUMBER (2, tp->tm_hour);
1019
 
 
1020
 
        case L_('I'):
1021
 
          if (modifier == L_('E'))
1022
 
            goto bad_format;
1023
 
 
1024
 
          DO_NUMBER (2, hour12);
1025
 
 
1026
 
        case L_('k'):           /* GNU extension.  */
1027
 
          if (modifier == L_('E'))
1028
 
            goto bad_format;
1029
 
 
1030
 
          DO_NUMBER_SPACEPAD (2, tp->tm_hour);
1031
 
 
1032
 
        case L_('l'):           /* GNU extension.  */
1033
 
          if (modifier == L_('E'))
1034
 
            goto bad_format;
1035
 
 
1036
 
          DO_NUMBER_SPACEPAD (2, hour12);
1037
 
 
1038
 
        case L_('j'):
1039
 
          if (modifier == L_('E'))
1040
 
            goto bad_format;
1041
 
 
1042
 
          DO_NUMBER (3, 1 + tp->tm_yday);
1043
 
 
1044
 
        case L_('M'):
1045
 
          if (modifier == L_('E'))
1046
 
            goto bad_format;
1047
 
 
1048
 
          DO_NUMBER (2, tp->tm_min);
1049
 
 
1050
 
        case L_('m'):
1051
 
          if (modifier == L_('E'))
1052
 
            goto bad_format;
1053
 
 
1054
 
          DO_NUMBER (2, tp->tm_mon + 1);
1055
 
 
1056
 
        case L_('N'):           /* GNU extension.  */
1057
 
          if (modifier == L_('E'))
1058
 
            goto bad_format;
1059
 
 
1060
 
          number_value = ns;
1061
 
          if (width != -1)
1062
 
            {
1063
 
              /* Take an explicit width less than 9 as a precision.  */
1064
 
              int j;
1065
 
              for (j = width; j < 9; j++)
1066
 
                number_value /= 10;
1067
 
            }
1068
 
 
1069
 
          DO_NUMBER (9, number_value);
1070
 
 
1071
 
        case L_('n'):           /* POSIX.2 extension.  */
1072
 
          add (1, *p = L_('\n'));
1073
 
          break;
1074
 
 
1075
 
        case L_('P'):
1076
 
          to_lowcase = 1;
1077
 
#if !defined _NL_CURRENT && HAVE_STRFTIME
1078
 
          format_char = L_('p');
1079
 
#endif
1080
 
          /* FALLTHROUGH */
1081
 
 
1082
 
        case L_('p'):
1083
 
          if (change_case)
1084
 
            {
1085
 
              to_uppcase = 0;
1086
 
              to_lowcase = 1;
1087
 
            }
1088
 
#if defined _NL_CURRENT || !HAVE_STRFTIME
1089
 
          cpy (ap_len, ampm);
1090
 
          break;
1091
 
#else
1092
 
          goto underlying_strftime;
1093
 
#endif
1094
 
 
1095
 
        case L_('R'):           /* ISO C99 extension.  */
1096
 
          subfmt = L_("%H:%M");
1097
 
          goto subformat;
1098
 
 
1099
 
        case L_('r'):           /* POSIX.2 extension.  */
1100
 
#ifdef _NL_CURRENT
1101
 
          if (*(subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME,
1102
 
                                                       NLW(T_FMT_AMPM)))
1103
 
              == L_('\0'))
1104
 
#endif
1105
 
            subfmt = L_("%I:%M:%S %p");
1106
 
          goto subformat;
1107
 
 
1108
 
        case L_('S'):
1109
 
          if (modifier == L_('E'))
1110
 
            goto bad_format;
1111
 
 
1112
 
          DO_NUMBER (2, tp->tm_sec);
1113
 
 
1114
 
        case L_('s'):           /* GNU extension.  */
1115
 
          {
1116
 
            struct tm ltm;
1117
 
            time_t t;
1118
 
 
1119
 
            ltm = *tp;
1120
 
            t = mktime (&ltm);
1121
 
 
1122
 
            /* Generate string value for T using time_t arithmetic;
1123
 
               this works even if sizeof (long) < sizeof (time_t).  */
1124
 
 
1125
 
            bufp = buf + sizeof (buf) / sizeof (buf[0]);
1126
 
            negative_number = t < 0;
1127
 
 
1128
 
            do
1129
 
              {
1130
 
                int d = t % 10;
1131
 
                t /= 10;
1132
 
 
1133
 
                if (negative_number)
1134
 
                  {
1135
 
                    d = -d;
1136
 
 
1137
 
                    /* Adjust if division truncates to minus infinity.  */
1138
 
                    if (0 < -1 % 10 && d < 0)
1139
 
                      {
1140
 
                        t++;
1141
 
                        d += 10;
1142
 
                      }
1143
 
                  }
1144
 
 
1145
 
                *--bufp = d + L_('0');
1146
 
              }
1147
 
            while (t != 0);
1148
 
 
1149
 
            digits = 1;
1150
 
            goto do_number_sign_and_padding;
1151
 
          }
1152
 
 
1153
 
        case L_('X'):
1154
 
          if (modifier == L_('O'))
1155
 
            goto bad_format;
1156
 
#ifdef _NL_CURRENT
1157
 
          if (! (modifier == L_('E')
1158
 
                 && (*(subfmt =
1159
 
                       (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ERA_T_FMT)))
1160
 
                     != L_('\0'))))
1161
 
            subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT));
1162
 
          goto subformat;
1163
 
#else
1164
 
# if HAVE_STRFTIME
1165
 
          goto underlying_strftime;
1166
 
# else
1167
 
          /* Fall through.  */
1168
 
# endif
1169
 
#endif
1170
 
        case L_('T'):           /* POSIX.2 extension.  */
1171
 
          subfmt = L_("%H:%M:%S");
1172
 
          goto subformat;
1173
 
 
1174
 
        case L_('t'):           /* POSIX.2 extension.  */
1175
 
          add (1, *p = L_('\t'));
1176
 
          break;
1177
 
 
1178
 
        case L_('u'):           /* POSIX.2 extension.  */
1179
 
          DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
1180
 
 
1181
 
        case L_('U'):
1182
 
          if (modifier == L_('E'))
1183
 
            goto bad_format;
1184
 
 
1185
 
          DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
1186
 
 
1187
 
        case L_('V'):
1188
 
        case L_('g'):           /* ISO C99 extension.  */
1189
 
        case L_('G'):           /* ISO C99 extension.  */
1190
 
          if (modifier == L_('E'))
1191
 
            goto bad_format;
1192
 
          {
1193
 
            int year = tp->tm_year + TM_YEAR_BASE;
1194
 
            int days = iso_week_days (tp->tm_yday, tp->tm_wday);
1195
 
 
1196
 
            if (days < 0)
1197
 
              {
1198
 
                /* This ISO week belongs to the previous year.  */
1199
 
                year--;
1200
 
                days = iso_week_days (tp->tm_yday + (365 + __isleap (year)),
1201
 
                                      tp->tm_wday);
1202
 
              }
1203
 
            else
1204
 
              {
1205
 
                int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
1206
 
                                       tp->tm_wday);
1207
 
                if (0 <= d)
1208
 
                  {
1209
 
                    /* This ISO week belongs to the next year.  */
1210
 
                    year++;
1211
 
                    days = d;
1212
 
                  }
1213
 
              }
1214
 
 
1215
 
            switch (*f)
1216
 
              {
1217
 
              case L_('g'):
1218
 
                DO_NUMBER (2, (year % 100 + 100) % 100);
1219
 
 
1220
 
              case L_('G'):
1221
 
                DO_NUMBER (1, year);
1222
 
 
1223
 
              default:
1224
 
                DO_NUMBER (2, days / 7 + 1);
1225
 
              }
1226
 
          }
1227
 
 
1228
 
        case L_('W'):
1229
 
          if (modifier == L_('E'))
1230
 
            goto bad_format;
1231
 
 
1232
 
          DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
1233
 
 
1234
 
        case L_('w'):
1235
 
          if (modifier == L_('E'))
1236
 
            goto bad_format;
1237
 
 
1238
 
          DO_NUMBER (1, tp->tm_wday);
1239
 
 
1240
 
        case L_('Y'):
1241
 
          if (modifier == 'E')
1242
 
            {
1243
 
#if HAVE_STRUCT_ERA_ENTRY
1244
 
              struct era_entry *era = _nl_get_era_entry (tp);
1245
 
              if (era)
1246
 
                {
1247
 
# ifdef COMPILE_WIDE
1248
 
                  subfmt = era->era_wformat;
1249
 
# else
1250
 
                  subfmt = era->era_format;
1251
 
# endif
1252
 
                  goto subformat;
1253
 
                }
1254
 
#else
1255
 
# if HAVE_STRFTIME
1256
 
              goto underlying_strftime;
1257
 
# endif
1258
 
#endif
1259
 
            }
1260
 
          if (modifier == L_('O'))
1261
 
            goto bad_format;
1262
 
          else
1263
 
            DO_NUMBER (1, tp->tm_year + TM_YEAR_BASE);
1264
 
 
1265
 
        case L_('y'):
1266
 
          if (modifier == L_('E'))
1267
 
            {
1268
 
#if HAVE_STRUCT_ERA_ENTRY
1269
 
              struct era_entry *era = _nl_get_era_entry (tp);
1270
 
              if (era)
1271
 
                {
1272
 
                  int delta = tp->tm_year - era->start_date[0];
1273
 
                  DO_NUMBER (1, (era->offset
1274
 
                                 + delta * era->absolute_direction));
1275
 
                }
1276
 
#else
1277
 
# if HAVE_STRFTIME
1278
 
              goto underlying_strftime;
1279
 
# endif
1280
 
#endif
1281
 
            }
1282
 
          DO_NUMBER (2, (tp->tm_year % 100 + 100) % 100);
1283
 
 
1284
 
        case L_('Z'):
1285
 
          if (change_case)
1286
 
            {
1287
 
              to_uppcase = 0;
1288
 
              to_lowcase = 1;
1289
 
            }
 
809
            size_t strftime ();
 
810
# endif
 
811
 
 
812
            /* The space helps distinguish strftime failure from empty
 
813
               output.  */
 
814
            *u++ = ' ';
 
815
            *u++ = '%';
 
816
            if (modifier != 0)
 
817
              *u++ = modifier;
 
818
            *u++ = format_char;
 
819
            *u = '\0';
 
820
            len = strftime (ubuf, sizeof ubuf, ufmt, tp);
 
821
            if (len != 0)
 
822
              cpy (len - 1, ubuf + 1);
 
823
          }
 
824
          break;
 
825
#endif
 
826
 
 
827
        case L_('C'):
 
828
          if (modifier == L_('O'))
 
829
            goto bad_format;
 
830
          if (modifier == L_('E'))
 
831
            {
 
832
#if HAVE_STRUCT_ERA_ENTRY
 
833
              struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
 
834
              if (era)
 
835
                {
 
836
# ifdef COMPILE_WIDE
 
837
                  size_t len = __wcslen (era->era_wname);
 
838
                  cpy (len, era->era_wname);
 
839
# else
 
840
                  size_t len = strlen (era->era_name);
 
841
                  cpy (len, era->era_name);
 
842
# endif
 
843
                  break;
 
844
                }
 
845
#else
 
846
              goto underlying_strftime;
 
847
#endif
 
848
            }
 
849
 
 
850
          {
 
851
            int century = tp->tm_year / 100 + TM_YEAR_BASE / 100;
 
852
            century -= tp->tm_year % 100 < 0 && 0 < century;
 
853
            DO_SIGNED_NUMBER (2, tp->tm_year < - TM_YEAR_BASE, century);
 
854
          }
 
855
 
 
856
        case L_('x'):
 
857
          if (modifier == L_('O'))
 
858
            goto bad_format;
 
859
#ifdef _NL_CURRENT
 
860
          if (! (modifier == L_('E')
 
861
                 && (*(subfmt =
 
862
                       (const CHAR_T *)_NL_CURRENT (LC_TIME, NLW(ERA_D_FMT)))
 
863
                     != L_('\0'))))
 
864
            subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
 
865
          goto subformat;
 
866
#else
 
867
          goto underlying_strftime;
 
868
#endif
 
869
        case L_('D'):
 
870
          if (modifier != 0)
 
871
            goto bad_format;
 
872
          subfmt = L_("%m/%d/%y");
 
873
          goto subformat;
 
874
 
 
875
        case L_('d'):
 
876
          if (modifier == L_('E'))
 
877
            goto bad_format;
 
878
 
 
879
          DO_NUMBER (2, tp->tm_mday);
 
880
 
 
881
        case L_('e'):
 
882
          if (modifier == L_('E'))
 
883
            goto bad_format;
 
884
 
 
885
          DO_NUMBER_SPACEPAD (2, tp->tm_mday);
 
886
 
 
887
          /* All numeric formats set DIGITS and NUMBER_VALUE (or U_NUMBER_VALUE)
 
888
             and then jump to one of these labels.  */
 
889
 
 
890
        do_tz_offset:
 
891
          always_output_a_sign = true;
 
892
          goto do_number_body;
 
893
 
 
894
        do_number_spacepad:
 
895
          /* Force `_' flag unless overridden by `0' or `-' flag.  */
 
896
          if (pad != L_('0') && pad != L_('-'))
 
897
            pad = L_('_');
 
898
 
 
899
        do_number:
 
900
          /* Format NUMBER_VALUE according to the MODIFIER flag.  */
 
901
          negative_number = number_value < 0;
 
902
          u_number_value = number_value;
 
903
 
 
904
        do_signed_number:
 
905
          always_output_a_sign = false;
 
906
          tz_colon_mask = 0;
 
907
 
 
908
        do_number_body:
 
909
          /* Format U_NUMBER_VALUE according to the MODIFIER flag.
 
910
             NEGATIVE_NUMBER is nonzero if the original number was
 
911
             negative; in this case it was converted directly to
 
912
             unsigned int (i.e., modulo (UINT_MAX + 1)) without
 
913
             negating it.  */
 
914
          if (modifier == L_('O') && !negative_number)
 
915
            {
 
916
#ifdef _NL_CURRENT
 
917
              /* Get the locale specific alternate representation of
 
918
                 the number.  If none exist NULL is returned.  */
 
919
              const CHAR_T *cp = nl_get_alt_digit (u_number_value
 
920
                                                   HELPER_LOCALE_ARG);
 
921
 
 
922
              if (cp != NULL)
 
923
                {
 
924
                  size_t digitlen = STRLEN (cp);
 
925
                  if (digitlen != 0)
 
926
                    {
 
927
                      cpy (digitlen, cp);
 
928
                      break;
 
929
                    }
 
930
                }
 
931
#else
 
932
              goto underlying_strftime;
 
933
#endif
 
934
            }
 
935
 
 
936
          bufp = buf + sizeof (buf) / sizeof (buf[0]);
 
937
 
 
938
          if (negative_number)
 
939
            u_number_value = - u_number_value;
 
940
 
 
941
          do
 
942
            {
 
943
              if (tz_colon_mask & 1)
 
944
                *--bufp = ':';
 
945
              tz_colon_mask >>= 1;
 
946
              *--bufp = u_number_value % 10 + L_('0');
 
947
              u_number_value /= 10;
 
948
            }
 
949
          while (u_number_value != 0 || tz_colon_mask != 0);
 
950
 
 
951
        do_number_sign_and_padding:
 
952
          if (digits < width)
 
953
            digits = width;
 
954
 
 
955
          sign_char = (negative_number ? L_('-')
 
956
                       : always_output_a_sign ? L_('+')
 
957
                       : 0);
 
958
 
 
959
          if (pad == L_('-'))
 
960
            {
 
961
              if (sign_char)
 
962
                add1 (sign_char);
 
963
            }
 
964
          else
 
965
            {
 
966
              int padding = digits - (buf + (sizeof (buf) / sizeof (buf[0]))
 
967
                                      - bufp) - !!sign_char;
 
968
 
 
969
              if (padding > 0)
 
970
                {
 
971
                  if (pad == L_('_'))
 
972
                    {
 
973
                      if ((size_t) padding >= maxsize - i)
 
974
                        return 0;
 
975
 
 
976
                      if (p)
 
977
                        memset_space (p, padding);
 
978
                      i += padding;
 
979
                      width = width > padding ? width - padding : 0;
 
980
                      if (sign_char)
 
981
                        add1 (sign_char);
 
982
                    }
 
983
                  else
 
984
                    {
 
985
                      if ((size_t) digits >= maxsize - i)
 
986
                        return 0;
 
987
 
 
988
                      if (sign_char)
 
989
                        add1 (sign_char);
 
990
 
 
991
                      if (p)
 
992
                        memset_zero (p, padding);
 
993
                      i += padding;
 
994
                      width = 0;
 
995
                    }
 
996
                }
 
997
              else
 
998
                {
 
999
                  if (sign_char)
 
1000
                    add1 (sign_char);
 
1001
                }
 
1002
            }
 
1003
 
 
1004
          cpy (buf + sizeof (buf) / sizeof (buf[0]) - bufp, bufp);
 
1005
          break;
 
1006
 
 
1007
        case L_('F'):
 
1008
          if (modifier != 0)
 
1009
            goto bad_format;
 
1010
          subfmt = L_("%Y-%m-%d");
 
1011
          goto subformat;
 
1012
 
 
1013
        case L_('H'):
 
1014
          if (modifier == L_('E'))
 
1015
            goto bad_format;
 
1016
 
 
1017
          DO_NUMBER (2, tp->tm_hour);
 
1018
 
 
1019
        case L_('I'):
 
1020
          if (modifier == L_('E'))
 
1021
            goto bad_format;
 
1022
 
 
1023
          DO_NUMBER (2, hour12);
 
1024
 
 
1025
        case L_('k'):           /* GNU extension.  */
 
1026
          if (modifier == L_('E'))
 
1027
            goto bad_format;
 
1028
 
 
1029
          DO_NUMBER_SPACEPAD (2, tp->tm_hour);
 
1030
 
 
1031
        case L_('l'):           /* GNU extension.  */
 
1032
          if (modifier == L_('E'))
 
1033
            goto bad_format;
 
1034
 
 
1035
          DO_NUMBER_SPACEPAD (2, hour12);
 
1036
 
 
1037
        case L_('j'):
 
1038
          if (modifier == L_('E'))
 
1039
            goto bad_format;
 
1040
 
 
1041
          DO_SIGNED_NUMBER (3, tp->tm_yday < -1, tp->tm_yday + 1U);
 
1042
 
 
1043
        case L_('M'):
 
1044
          if (modifier == L_('E'))
 
1045
            goto bad_format;
 
1046
 
 
1047
          DO_NUMBER (2, tp->tm_min);
 
1048
 
 
1049
        case L_('m'):
 
1050
          if (modifier == L_('E'))
 
1051
            goto bad_format;
 
1052
 
 
1053
          DO_SIGNED_NUMBER (2, tp->tm_mon < -1, tp->tm_mon + 1U);
 
1054
 
 
1055
#ifndef _LIBC
 
1056
        case L_('N'):           /* GNU extension.  */
 
1057
          if (modifier == L_('E'))
 
1058
            goto bad_format;
 
1059
 
 
1060
          number_value = ns;
 
1061
          if (width == -1)
 
1062
            width = 9;
 
1063
          else
 
1064
            {
 
1065
              /* Take an explicit width less than 9 as a precision.  */
 
1066
              int j;
 
1067
              for (j = width; j < 9; j++)
 
1068
                number_value /= 10;
 
1069
            }
 
1070
 
 
1071
          DO_NUMBER (width, number_value);
 
1072
#endif
 
1073
 
 
1074
        case L_('n'):
 
1075
          add1 (L_('\n'));
 
1076
          break;
 
1077
 
 
1078
        case L_('P'):
 
1079
          to_lowcase = true;
 
1080
#ifndef _NL_CURRENT
 
1081
          format_char = L_('p');
 
1082
#endif
 
1083
          /* FALLTHROUGH */
 
1084
 
 
1085
        case L_('p'):
 
1086
          if (change_case)
 
1087
            {
 
1088
              to_uppcase = false;
 
1089
              to_lowcase = true;
 
1090
            }
 
1091
#ifdef _NL_CURRENT
 
1092
          cpy (ap_len, ampm);
 
1093
          break;
 
1094
#else
 
1095
          goto underlying_strftime;
 
1096
#endif
 
1097
 
 
1098
        case L_('R'):
 
1099
          subfmt = L_("%H:%M");
 
1100
          goto subformat;
 
1101
 
 
1102
        case L_('r'):
 
1103
#ifdef _NL_CURRENT
 
1104
          if (*(subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME,
 
1105
                                                       NLW(T_FMT_AMPM)))
 
1106
              == L_('\0'))
 
1107
            subfmt = L_("%I:%M:%S %p");
 
1108
          goto subformat;
 
1109
#else
 
1110
          goto underlying_strftime;
 
1111
#endif
 
1112
 
 
1113
        case L_('S'):
 
1114
          if (modifier == L_('E'))
 
1115
            goto bad_format;
 
1116
 
 
1117
          DO_NUMBER (2, tp->tm_sec);
 
1118
 
 
1119
        case L_('s'):           /* GNU extension.  */
 
1120
          {
 
1121
            struct tm ltm;
 
1122
            time_t t;
 
1123
 
 
1124
            ltm = *tp;
 
1125
            t = mktime (&ltm);
 
1126
 
 
1127
            /* Generate string value for T using time_t arithmetic;
 
1128
               this works even if sizeof (long) < sizeof (time_t).  */
 
1129
 
 
1130
            bufp = buf + sizeof (buf) / sizeof (buf[0]);
 
1131
            negative_number = t < 0;
 
1132
 
 
1133
            do
 
1134
              {
 
1135
                int d = t % 10;
 
1136
                t /= 10;
 
1137
                *--bufp = (negative_number ? -d : d) + L_('0');
 
1138
              }
 
1139
            while (t != 0);
 
1140
 
 
1141
            digits = 1;
 
1142
            always_output_a_sign = false;
 
1143
            goto do_number_sign_and_padding;
 
1144
          }
 
1145
 
 
1146
        case L_('X'):
 
1147
          if (modifier == L_('O'))
 
1148
            goto bad_format;
 
1149
#ifdef _NL_CURRENT
 
1150
          if (! (modifier == L_('E')
 
1151
                 && (*(subfmt =
 
1152
                       (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ERA_T_FMT)))
 
1153
                     != L_('\0'))))
 
1154
            subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT));
 
1155
          goto subformat;
 
1156
#else
 
1157
          goto underlying_strftime;
 
1158
#endif
 
1159
        case L_('T'):
 
1160
          subfmt = L_("%H:%M:%S");
 
1161
          goto subformat;
 
1162
 
 
1163
        case L_('t'):
 
1164
          add1 (L_('\t'));
 
1165
          break;
 
1166
 
 
1167
        case L_('u'):
 
1168
          DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
 
1169
 
 
1170
        case L_('U'):
 
1171
          if (modifier == L_('E'))
 
1172
            goto bad_format;
 
1173
 
 
1174
          DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
 
1175
 
 
1176
        case L_('V'):
 
1177
        case L_('g'):
 
1178
        case L_('G'):
 
1179
          if (modifier == L_('E'))
 
1180
            goto bad_format;
 
1181
          {
 
1182
            /* YEAR is a leap year if and only if (tp->tm_year + TM_YEAR_BASE)
 
1183
               is a leap year, except that YEAR and YEAR - 1 both work
 
1184
               correctly even when (tp->tm_year + TM_YEAR_BASE) would
 
1185
               overflow.  */
 
1186
            int year = (tp->tm_year
 
1187
                        + (tp->tm_year < 0
 
1188
                           ? TM_YEAR_BASE % 400
 
1189
                           : TM_YEAR_BASE % 400 - 400));
 
1190
            int year_adjust = 0;
 
1191
            int days = iso_week_days (tp->tm_yday, tp->tm_wday);
 
1192
 
 
1193
            if (days < 0)
 
1194
              {
 
1195
                /* This ISO week belongs to the previous year.  */
 
1196
                year_adjust = -1;
 
1197
                days = iso_week_days (tp->tm_yday + (365 + __isleap (year - 1)),
 
1198
                                      tp->tm_wday);
 
1199
              }
 
1200
            else
 
1201
              {
 
1202
                int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
 
1203
                                       tp->tm_wday);
 
1204
                if (0 <= d)
 
1205
                  {
 
1206
                    /* This ISO week belongs to the next year.  */
 
1207
                    year_adjust = 1;
 
1208
                    days = d;
 
1209
                  }
 
1210
              }
 
1211
 
 
1212
            switch (*f)
 
1213
              {
 
1214
              case L_('g'):
 
1215
                {
 
1216
                  int yy = (tp->tm_year % 100 + year_adjust) % 100;
 
1217
                  DO_NUMBER (2, (0 <= yy
 
1218
                                 ? yy
 
1219
                                 : tp->tm_year < -TM_YEAR_BASE - year_adjust
 
1220
                                 ? -yy
 
1221
                                 : yy + 100));
 
1222
                }
 
1223
 
 
1224
              case L_('G'):
 
1225
                DO_SIGNED_NUMBER (4, tp->tm_year < -TM_YEAR_BASE - year_adjust,
 
1226
                                  (tp->tm_year + (unsigned int) TM_YEAR_BASE
 
1227
                                   + year_adjust));
 
1228
 
 
1229
              default:
 
1230
                DO_NUMBER (2, days / 7 + 1);
 
1231
              }
 
1232
          }
 
1233
 
 
1234
        case L_('W'):
 
1235
          if (modifier == L_('E'))
 
1236
            goto bad_format;
 
1237
 
 
1238
          DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
 
1239
 
 
1240
        case L_('w'):
 
1241
          if (modifier == L_('E'))
 
1242
            goto bad_format;
 
1243
 
 
1244
          DO_NUMBER (1, tp->tm_wday);
 
1245
 
 
1246
        case L_('Y'):
 
1247
          if (modifier == 'E')
 
1248
            {
 
1249
#if HAVE_STRUCT_ERA_ENTRY
 
1250
              struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
 
1251
              if (era)
 
1252
                {
 
1253
# ifdef COMPILE_WIDE
 
1254
                  subfmt = era->era_wformat;
 
1255
# else
 
1256
                  subfmt = era->era_format;
 
1257
# endif
 
1258
                  goto subformat;
 
1259
                }
 
1260
#else
 
1261
              goto underlying_strftime;
 
1262
#endif
 
1263
            }
 
1264
          if (modifier == L_('O'))
 
1265
            goto bad_format;
 
1266
          else
 
1267
            DO_SIGNED_NUMBER (4, tp->tm_year < -TM_YEAR_BASE,
 
1268
                              tp->tm_year + (unsigned int) TM_YEAR_BASE);
 
1269
 
 
1270
        case L_('y'):
 
1271
          if (modifier == L_('E'))
 
1272
            {
 
1273
#if HAVE_STRUCT_ERA_ENTRY
 
1274
              struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
 
1275
              if (era)
 
1276
                {
 
1277
                  int delta = tp->tm_year - era->start_date[0];
 
1278
                  DO_NUMBER (1, (era->offset
 
1279
                                 + delta * era->absolute_direction));
 
1280
                }
 
1281
#else
 
1282
              goto underlying_strftime;
 
1283
#endif
 
1284
            }
 
1285
 
 
1286
          {
 
1287
            int yy = tp->tm_year % 100;
 
1288
            if (yy < 0)
 
1289
              yy = tp->tm_year < - TM_YEAR_BASE ? -yy : yy + 100;
 
1290
            DO_NUMBER (2, yy);
 
1291
          }
 
1292
 
 
1293
        case L_('Z'):
 
1294
          if (change_case)
 
1295
            {
 
1296
              to_uppcase = false;
 
1297
              to_lowcase = true;
 
1298
            }
1290
1299
 
1291
1300
#if HAVE_TZNAME
1292
 
          /* The tzset() call might have changed the value.  */
1293
 
          if (!(zone && *zone) && tp->tm_isdst >= 0)
1294
 
            zone = tzname[tp->tm_isdst];
 
1301
          /* The tzset() call might have changed the value.  */
 
1302
          if (!(zone && *zone) && tp->tm_isdst >= 0)
 
1303
            zone = tzname[tp->tm_isdst != 0];
1295
1304
#endif
1296
 
          if (! zone)
1297
 
            zone = "";          /* POSIX.2 requires the empty string here.  */
 
1305
          if (! zone)
 
1306
            zone = "";
1298
1307
 
1299
1308
#ifdef COMPILE_WIDE
1300
 
          {
1301
 
            /* The zone string is always given in multibyte form.  We have
1302
 
               to transform it first.  */
1303
 
            wchar_t *wczone;
1304
 
            size_t len;
1305
 
            widen (zone, wczone, len);
1306
 
            cpy (len, wczone);
1307
 
          }
 
1309
          {
 
1310
            /* The zone string is always given in multibyte form.  We have
 
1311
               to transform it first.  */
 
1312
            wchar_t *wczone;
 
1313
            size_t len;
 
1314
            widen (zone, wczone, len);
 
1315
            cpy (len, wczone);
 
1316
          }
1308
1317
#else
1309
 
          cpy (strlen (zone), zone);
 
1318
          cpy (strlen (zone), zone);
1310
1319
#endif
1311
 
          break;
1312
 
 
1313
 
        case L_('z'):           /* ISO C99 extension.  */
1314
 
          if (tp->tm_isdst < 0)
1315
 
            break;
1316
 
 
1317
 
          {
1318
 
            int diff;
 
1320
          break;
 
1321
 
 
1322
        case L_(':'):
 
1323
          /* :, ::, and ::: are valid only just before 'z'.
 
1324
             :::: etc. are rejected later.  */
 
1325
          for (colons = 1; f[colons] == L_(':'); colons++)
 
1326
            continue;
 
1327
          if (f[colons] != L_('z'))
 
1328
            goto bad_format;
 
1329
          f += colons;
 
1330
          goto do_z_conversion;
 
1331
 
 
1332
        case L_('z'):
 
1333
          colons = 0;
 
1334
 
 
1335
        do_z_conversion:
 
1336
          if (tp->tm_isdst < 0)
 
1337
            break;
 
1338
 
 
1339
          {
 
1340
            int diff;
 
1341
            int hour_diff;
 
1342
            int min_diff;
 
1343
            int sec_diff;
1319
1344
#if HAVE_TM_GMTOFF
1320
 
            diff = tp->tm_gmtoff;
 
1345
            diff = tp->tm_gmtoff;
1321
1346
#else
1322
 
            if (ut)
1323
 
              diff = 0;
1324
 
            else
1325
 
              {
1326
 
                struct tm gtm;
1327
 
                struct tm ltm;
1328
 
                time_t lt;
1329
 
 
1330
 
                ltm = *tp;
1331
 
                lt = mktime (&ltm);
1332
 
 
1333
 
                if (lt == (time_t) -1)
1334
 
                  {
1335
 
                    /* mktime returns -1 for errors, but -1 is also a
1336
 
                       valid time_t value.  Check whether an error really
1337
 
                       occurred.  */
1338
 
                    struct tm tm;
1339
 
 
1340
 
                    if (! my_strftime_localtime_r (&lt, &tm)
1341
 
                        || ((ltm.tm_sec ^ tm.tm_sec)
1342
 
                            | (ltm.tm_min ^ tm.tm_min)
1343
 
                            | (ltm.tm_hour ^ tm.tm_hour)
1344
 
                            | (ltm.tm_mday ^ tm.tm_mday)
1345
 
                            | (ltm.tm_mon ^ tm.tm_mon)
1346
 
                            | (ltm.tm_year ^ tm.tm_year)))
1347
 
                      break;
1348
 
                  }
1349
 
 
1350
 
                if (! my_strftime_gmtime_r (&lt, &gtm))
1351
 
                  break;
1352
 
 
1353
 
                diff = tm_diff (&ltm, &gtm);
1354
 
              }
 
1347
            if (ut)
 
1348
              diff = 0;
 
1349
            else
 
1350
              {
 
1351
                struct tm gtm;
 
1352
                struct tm ltm;
 
1353
                time_t lt;
 
1354
 
 
1355
                ltm = *tp;
 
1356
                lt = mktime (&ltm);
 
1357
 
 
1358
                if (lt == (time_t) -1)
 
1359
                  {
 
1360
                    /* mktime returns -1 for errors, but -1 is also a
 
1361
                       valid time_t value.  Check whether an error really
 
1362
                       occurred.  */
 
1363
                    struct tm tm;
 
1364
 
 
1365
                    if (! __localtime_r (&lt, &tm)
 
1366
                        || ((ltm.tm_sec ^ tm.tm_sec)
 
1367
                            | (ltm.tm_min ^ tm.tm_min)
 
1368
                            | (ltm.tm_hour ^ tm.tm_hour)
 
1369
                            | (ltm.tm_mday ^ tm.tm_mday)
 
1370
                            | (ltm.tm_mon ^ tm.tm_mon)
 
1371
                            | (ltm.tm_year ^ tm.tm_year)))
 
1372
                      break;
 
1373
                  }
 
1374
 
 
1375
                if (! __gmtime_r (&lt, &gtm))
 
1376
                  break;
 
1377
 
 
1378
                diff = tm_diff (&ltm, &gtm);
 
1379
              }
1355
1380
#endif
1356
1381
 
1357
 
            if (diff < 0)
1358
 
              {
1359
 
                add (1, *p = L_('-'));
1360
 
                diff = -diff;
1361
 
              }
1362
 
            else
1363
 
              add (1, *p = L_('+'));
1364
 
 
1365
 
            diff /= 60;
1366
 
            DO_NUMBER (4, (diff / 60) * 100 + diff % 60);
1367
 
          }
1368
 
 
1369
 
        case L_('\0'):          /* GNU extension: % at end of format.  */
1370
 
            --f;
1371
 
            /* Fall through.  */
1372
 
        default:
1373
 
          /* Unknown format; output the format, including the '%',
1374
 
             since this is most likely the right thing to do if a
1375
 
             multibyte string has been misparsed.  */
1376
 
        bad_format:
1377
 
          {
1378
 
            int flen;
1379
 
            for (flen = 1; f[1 - flen] != L_('%'); flen++)
1380
 
              continue;
1381
 
            cpy (flen, &f[1 - flen]);
1382
 
          }
1383
 
          break;
1384
 
        }
 
1382
            hour_diff = diff / 60 / 60;
 
1383
            min_diff = diff / 60 % 60;
 
1384
            sec_diff = diff % 60;
 
1385
 
 
1386
            switch (colons)
 
1387
              {
 
1388
              case 0: /* +hhmm */
 
1389
                DO_TZ_OFFSET (5, diff < 0, 0, hour_diff * 100 + min_diff);
 
1390
 
 
1391
              case 1: tz_hh_mm: /* +hh:mm */
 
1392
                DO_TZ_OFFSET (6, diff < 0, 04, hour_diff * 100 + min_diff);
 
1393
 
 
1394
              case 2: tz_hh_mm_ss: /* +hh:mm:ss */
 
1395
                DO_TZ_OFFSET (9, diff < 0, 024,
 
1396
                              hour_diff * 10000 + min_diff * 100 + sec_diff);
 
1397
 
 
1398
              case 3: /* +hh if possible, else +hh:mm, else +hh:mm:ss */
 
1399
                if (sec_diff != 0)
 
1400
                  goto tz_hh_mm_ss;
 
1401
                if (min_diff != 0)
 
1402
                  goto tz_hh_mm;
 
1403
                DO_TZ_OFFSET (3, diff < 0, 0, hour_diff);
 
1404
 
 
1405
              default:
 
1406
                goto bad_format;
 
1407
              }
 
1408
          }
 
1409
 
 
1410
        case L_('\0'):          /* GNU extension: % at end of format.  */
 
1411
            --f;
 
1412
            /* Fall through.  */
 
1413
        default:
 
1414
          /* Unknown format; output the format, including the '%',
 
1415
             since this is most likely the right thing to do if a
 
1416
             multibyte string has been misparsed.  */
 
1417
        bad_format:
 
1418
          {
 
1419
            int flen;
 
1420
            for (flen = 1; f[1 - flen] != L_('%'); flen++)
 
1421
              continue;
 
1422
            cpy (flen, &f[1 - flen]);
 
1423
          }
 
1424
          break;
 
1425
        }
1385
1426
    }
1386
1427
 
 
1428
#if ! FPRINTFTIME
1387
1429
  if (p && maxsize != 0)
1388
1430
    *p = L_('\0');
 
1431
#endif
 
1432
 
1389
1433
  return i;
1390
1434
}
1391
1435
 
1392
 
 
1393
 
#ifdef emacs
 
1436
/* Write information from TP into S according to the format
 
1437
   string FORMAT, writing no more that MAXSIZE characters
 
1438
   (including the terminating '\0') and returning number of
 
1439
   characters written.  If S is NULL, nothing will be written
 
1440
   anywhere, so to determine how many characters would be
 
1441
   written, use NULL for S and (size_t) -1 for MAXSIZE.  */
 
1442
size_t
 
1443
my_strftime (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
 
1444
             const CHAR_T *format,
 
1445
             const struct tm *tp extra_args_spec LOCALE_PARAM_PROTO)
 
1446
{
 
1447
  return strftime_case_ (false, s, STRFTIME_ARG (maxsize)
 
1448
                         format, tp extra_args LOCALE_ARG);
 
1449
}
 
1450
 
 
1451
#if defined _LIBC && ! FPRINTFTIME
 
1452
libc_hidden_def (my_strftime)
 
1453
#endif
 
1454
 
 
1455
 
 
1456
#if defined emacs && ! FPRINTFTIME
1394
1457
/* For Emacs we have a separate interface which corresponds to the normal
1395
1458
   strftime function plus the ut argument, but without the ns argument.  */
1396
1459
size_t
1397
 
emacs_strftimeu (s, maxsize, format, tp, ut)
1398
 
      char *s;
1399
 
      size_t maxsize;
1400
 
      const char *format;
1401
 
      const struct tm *tp;
1402
 
      int ut;
 
1460
emacs_strftimeu (char *s, size_t maxsize, const char *format,
 
1461
                 const struct tm *tp, int ut)
1403
1462
{
1404
1463
  return my_strftime (s, maxsize, format, tp, ut, 0);
1405
1464
}