LCOV - differential code coverage report
Current view: top level - src/timezone - zic.c (source / functions) Coverage Total Hit LBC UIC UBC GBC GIC CBC EUB ECB
Current: Differential Code Coverage HEAD vs 15 Lines: 58.6 % 1859 1089 113 290 367 99 407 583 304 393
Current Date: 2023-04-08 15:15:32 Functions: 77.8 % 72 56 16 56 16 56
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /* Compile .zi time zone data into TZif binary files.  */
       2                 : 
       3                 : /*
       4                 :  * This file is in the public domain, so clarified as of
       5                 :  * 2006-07-17 by Arthur David Olson.
       6                 :  *
       7                 :  * IDENTIFICATION
       8                 :  *    src/timezone/zic.c
       9                 :  */
      10                 : 
      11                 : #include "postgres_fe.h"
      12                 : 
      13                 : #include <fcntl.h>
      14                 : #include <sys/stat.h>
      15                 : #include <time.h>
      16                 : 
      17                 : #include "pg_getopt.h"
      18                 : 
      19                 : #include "private.h"
      20                 : #include "tzfile.h"
      21                 : 
      22                 : #define ZIC_VERSION_PRE_2013 '2'
      23                 : #define ZIC_VERSION '3'
      24                 : 
      25                 : typedef int64 zic_t;
      26                 : #define ZIC_MIN PG_INT64_MIN
      27                 : #define ZIC_MAX PG_INT64_MAX
      28                 : 
      29                 : #ifndef ZIC_MAX_ABBR_LEN_WO_WARN
      30                 : #define ZIC_MAX_ABBR_LEN_WO_WARN    6
      31                 : #endif                          /* !defined ZIC_MAX_ABBR_LEN_WO_WARN */
      32                 : 
      33                 : #ifndef WIN32
      34                 : #ifdef S_IRUSR
      35                 : #define MKDIR_UMASK (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
      36                 : #else
      37                 : #define MKDIR_UMASK 0755
      38                 : #endif
      39                 : #endif
      40                 : /* Port to native MS-Windows and to ancient UNIX.  */
      41                 : #if !defined S_ISDIR && defined S_IFDIR && defined S_IFMT
      42                 : #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
      43                 : #endif
      44                 : 
      45                 : /* The maximum ptrdiff_t value, for pre-C99 platforms.  */
      46                 : #ifndef PTRDIFF_MAX
      47                 : static ptrdiff_t const PTRDIFF_MAX = MAXVAL(ptrdiff_t, TYPE_BIT(ptrdiff_t));
      48                 : #endif
      49                 : 
      50                 : /*
      51                 :  * The type for line numbers.  In Postgres, use %d to format them; upstream
      52                 :  * uses PRIdMAX but we prefer not to rely on that, not least because it
      53                 :  * results in platform-dependent strings to be translated.
      54                 :  */
      55                 : typedef int lineno_t;
      56                 : 
      57                 : struct rule
      58                 : {
      59                 :     const char *r_filename;
      60                 :     lineno_t    r_linenum;
      61                 :     const char *r_name;
      62                 : 
      63                 :     zic_t       r_loyear;       /* for example, 1986 */
      64                 :     zic_t       r_hiyear;       /* for example, 1986 */
      65                 :     bool        r_lowasnum;
      66                 :     bool        r_hiwasnum;
      67                 : 
      68                 :     int         r_month;        /* 0..11 */
      69                 : 
      70                 :     int         r_dycode;       /* see below */
      71                 :     int         r_dayofmonth;
      72                 :     int         r_wday;
      73                 : 
      74                 :     zic_t       r_tod;          /* time from midnight */
      75                 :     bool        r_todisstd;     /* is r_tod standard time? */
      76                 :     bool        r_todisut;      /* is r_tod UT? */
      77                 :     bool        r_isdst;        /* is this daylight saving time? */
      78                 :     zic_t       r_save;         /* offset from standard time */
      79                 :     const char *r_abbrvar;      /* variable part of abbreviation */
      80                 : 
      81                 :     bool        r_todo;         /* a rule to do (used in outzone) */
      82                 :     zic_t       r_temp;         /* used in outzone */
      83                 : };
      84                 : 
      85                 : /*
      86                 :  *  r_dycode        r_dayofmonth    r_wday
      87                 :  */
      88                 : 
      89                 : #define DC_DOM      0   /* 1..31 */ /* unused */
      90                 : #define DC_DOWGEQ   1   /* 1..31 */ /* 0..6 (Sun..Sat) */
      91                 : #define DC_DOWLEQ   2   /* 1..31 */ /* 0..6 (Sun..Sat) */
      92                 : 
      93                 : struct zone
      94                 : {
      95                 :     const char *z_filename;
      96                 :     lineno_t    z_linenum;
      97                 : 
      98                 :     const char *z_name;
      99                 :     zic_t       z_stdoff;
     100                 :     char       *z_rule;
     101                 :     const char *z_format;
     102                 :     char        z_format_specifier;
     103                 : 
     104                 :     bool        z_isdst;
     105                 :     zic_t       z_save;
     106                 : 
     107                 :     struct rule *z_rules;
     108                 :     ptrdiff_t   z_nrules;
     109                 : 
     110                 :     struct rule z_untilrule;
     111                 :     zic_t       z_untiltime;
     112                 : };
     113                 : 
     114                 : extern int  link(const char *target, const char *linkname);
     115                 : #ifndef AT_SYMLINK_FOLLOW
     116                 : #define linkat(targetdir, target, linknamedir, linkname, flag) \
     117                 :     (itssymlink(target) ? (errno = ENOTSUP, -1) : link(target, linkname))
     118                 : #endif
     119                 : 
     120                 : static void memory_exhausted(const char *msg) pg_attribute_noreturn();
     121                 : static void verror(const char *string, va_list args) pg_attribute_printf(1, 0);
     122                 : static void error(const char *string,...) pg_attribute_printf(1, 2);
     123                 : static void warning(const char *string,...) pg_attribute_printf(1, 2);
     124                 : static void usage(FILE *stream, int status) pg_attribute_noreturn();
     125                 : static void addtt(zic_t starttime, int type);
     126                 : static int  addtype(zic_t utoff, char const *abbr,
     127                 :                     bool isdst, bool ttisstd, bool ttisut);
     128                 : static void leapadd(zic_t t, int correction, int rolling);
     129                 : static void adjleap(void);
     130                 : static void associate(void);
     131                 : static void dolink(char const *target, char const *linkname,
     132                 :                    bool staysymlink);
     133                 : static char **getfields(char *cp);
     134                 : static zic_t gethms(const char *string, const char *errstring);
     135                 : static zic_t getsave(char *field, bool *isdst);
     136                 : static void inexpires(char **fields, int nfields);
     137                 : static void infile(const char *name);
     138                 : static void inleap(char **fields, int nfields);
     139                 : static void inlink(char **fields, int nfields);
     140                 : static void inrule(char **fields, int nfields);
     141                 : static bool inzcont(char **fields, int nfields);
     142                 : static bool inzone(char **fields, int nfields);
     143                 : static bool inzsub(char **fields, int nfields, bool iscont);
     144                 : static bool itsdir(char const *name);
     145                 : static bool itssymlink(char const *name);
     146                 : static bool is_alpha(char a);
     147                 : static char lowerit(char a);
     148                 : static void mkdirs(char const *argname, bool ancestors);
     149                 : static void newabbr(const char *string);
     150                 : static zic_t oadd(zic_t t1, zic_t t2);
     151                 : static void outzone(const struct zone *zpfirst, ptrdiff_t zonecount);
     152                 : static zic_t rpytime(const struct rule *rp, zic_t wantedy);
     153                 : static void rulesub(struct rule *rp,
     154                 :                     const char *loyearp, const char *hiyearp,
     155                 :                     const char *typep, const char *monthp,
     156                 :                     const char *dayp, const char *timep);
     157                 : static zic_t tadd(zic_t t1, zic_t t2);
     158                 : 
     159                 : /* Bound on length of what %z can expand to.  */
     160                 : enum
     161                 : {
     162                 : PERCENT_Z_LEN_BOUND = sizeof "+995959" - 1};
     163                 : 
     164                 : /* If true, work around a bug in Qt 5.6.1 and earlier, which mishandles
     165                 :    TZif files whose POSIX-TZ-style strings contain '<'; see
     166                 :    QTBUG-53071 <https://bugreports.qt.io/browse/QTBUG-53071>.  This
     167                 :    workaround will no longer be needed when Qt 5.6.1 and earlier are
     168                 :    obsolete, say in the year 2021.  */
     169                 : #ifndef WORK_AROUND_QTBUG_53071
     170                 : enum
     171                 : {
     172                 : WORK_AROUND_QTBUG_53071 = true};
     173                 : #endif
     174                 : 
     175                 : static int  charcnt;
     176                 : static bool errors;
     177                 : static bool warnings;
     178                 : static const char *filename;
     179                 : static int  leapcnt;
     180                 : static bool leapseen;
     181                 : static zic_t leapminyear;
     182                 : static zic_t leapmaxyear;
     183                 : static lineno_t linenum;
     184                 : static int  max_abbrvar_len = PERCENT_Z_LEN_BOUND;
     185                 : static int  max_format_len;
     186                 : static zic_t max_year;
     187                 : static zic_t min_year;
     188                 : static bool noise;
     189                 : static bool print_abbrevs;
     190                 : static zic_t print_cutoff;
     191                 : static const char *rfilename;
     192                 : static lineno_t rlinenum;
     193                 : static const char *progname;
     194                 : static ptrdiff_t timecnt;
     195                 : static ptrdiff_t timecnt_alloc;
     196                 : static int  typecnt;
     197                 : 
     198                 : /*
     199                 :  * Line codes.
     200                 :  */
     201                 : 
     202                 : #define LC_RULE     0
     203                 : #define LC_ZONE     1
     204                 : #define LC_LINK     2
     205                 : #define LC_LEAP     3
     206                 : #define LC_EXPIRES  4
     207                 : 
     208                 : /*
     209                 :  * Which fields are which on a Zone line.
     210                 :  */
     211                 : 
     212                 : #define ZF_NAME     1
     213                 : #define ZF_STDOFF   2
     214                 : #define ZF_RULE     3
     215                 : #define ZF_FORMAT   4
     216                 : #define ZF_TILYEAR  5
     217                 : #define ZF_TILMONTH 6
     218                 : #define ZF_TILDAY   7
     219                 : #define ZF_TILTIME  8
     220                 : #define ZONE_MINFIELDS  5
     221                 : #define ZONE_MAXFIELDS  9
     222                 : 
     223                 : /*
     224                 :  * Which fields are which on a Zone continuation line.
     225                 :  */
     226                 : 
     227                 : #define ZFC_STDOFF  0
     228                 : #define ZFC_RULE    1
     229                 : #define ZFC_FORMAT  2
     230                 : #define ZFC_TILYEAR 3
     231                 : #define ZFC_TILMONTH    4
     232                 : #define ZFC_TILDAY  5
     233                 : #define ZFC_TILTIME 6
     234                 : #define ZONEC_MINFIELDS 3
     235                 : #define ZONEC_MAXFIELDS 7
     236                 : 
     237                 : /*
     238                 :  * Which files are which on a Rule line.
     239                 :  */
     240                 : 
     241                 : #define RF_NAME     1
     242                 : #define RF_LOYEAR   2
     243                 : #define RF_HIYEAR   3
     244                 : #define RF_COMMAND  4
     245                 : #define RF_MONTH    5
     246                 : #define RF_DAY      6
     247                 : #define RF_TOD      7
     248                 : #define RF_SAVE     8
     249                 : #define RF_ABBRVAR  9
     250                 : #define RULE_FIELDS 10
     251                 : 
     252                 : /*
     253                 :  * Which fields are which on a Link line.
     254                 :  */
     255                 : 
     256                 : #define LF_TARGET   1
     257                 : #define LF_LINKNAME 2
     258                 : #define LINK_FIELDS 3
     259                 : 
     260                 : /*
     261                 :  * Which fields are which on a Leap line.
     262                 :  */
     263                 : 
     264                 : #define LP_YEAR     1
     265                 : #define LP_MONTH    2
     266                 : #define LP_DAY      3
     267                 : #define LP_TIME     4
     268                 : #define LP_CORR     5
     269                 : #define LP_ROLL     6
     270                 : #define LEAP_FIELDS 7
     271                 : 
     272                 : /* Expires lines are like Leap lines, except without CORR and ROLL fields.  */
     273                 : #define EXPIRES_FIELDS  5
     274                 : 
     275                 : /*
     276                 :  * Year synonyms.
     277                 :  */
     278                 : 
     279                 : #define YR_MINIMUM  0
     280                 : #define YR_MAXIMUM  1
     281                 : #define YR_ONLY     2
     282                 : 
     283                 : static struct rule *rules;
     284                 : static ptrdiff_t nrules;        /* number of rules */
     285                 : static ptrdiff_t nrules_alloc;
     286                 : 
     287                 : static struct zone *zones;
     288                 : static ptrdiff_t nzones;        /* number of zones */
     289                 : static ptrdiff_t nzones_alloc;
     290                 : 
     291                 : struct link
     292                 : {
     293                 :     const char *l_filename;
     294                 :     lineno_t    l_linenum;
     295                 :     const char *l_target;
     296                 :     const char *l_linkname;
     297                 : };
     298                 : 
     299                 : static struct link *links;
     300                 : static ptrdiff_t nlinks;
     301                 : static ptrdiff_t nlinks_alloc;
     302                 : 
     303                 : struct lookup
     304                 : {
     305                 :     const char *l_word;
     306                 :     const int   l_value;
     307                 : };
     308                 : 
     309                 : static struct lookup const *byword(const char *word,
     310                 :                                    const struct lookup *table);
     311                 : 
     312                 : static struct lookup const zi_line_codes[] = {
     313                 :     {"Rule", LC_RULE},
     314                 :     {"Zone", LC_ZONE},
     315                 :     {"Link", LC_LINK},
     316                 :     {NULL, 0}
     317                 : };
     318                 : static struct lookup const leap_line_codes[] = {
     319                 :     {"Leap", LC_LEAP},
     320                 :     {"Expires", LC_EXPIRES},
     321                 :     {NULL, 0}
     322                 : };
     323                 : 
     324                 : static struct lookup const mon_names[] = {
     325                 :     {"January", TM_JANUARY},
     326                 :     {"February", TM_FEBRUARY},
     327                 :     {"March", TM_MARCH},
     328                 :     {"April", TM_APRIL},
     329                 :     {"May", TM_MAY},
     330                 :     {"June", TM_JUNE},
     331                 :     {"July", TM_JULY},
     332                 :     {"August", TM_AUGUST},
     333                 :     {"September", TM_SEPTEMBER},
     334                 :     {"October", TM_OCTOBER},
     335                 :     {"November", TM_NOVEMBER},
     336                 :     {"December", TM_DECEMBER},
     337                 :     {NULL, 0}
     338                 : };
     339                 : 
     340                 : static struct lookup const wday_names[] = {
     341                 :     {"Sunday", TM_SUNDAY},
     342                 :     {"Monday", TM_MONDAY},
     343                 :     {"Tuesday", TM_TUESDAY},
     344                 :     {"Wednesday", TM_WEDNESDAY},
     345                 :     {"Thursday", TM_THURSDAY},
     346                 :     {"Friday", TM_FRIDAY},
     347                 :     {"Saturday", TM_SATURDAY},
     348                 :     {NULL, 0}
     349                 : };
     350                 : 
     351                 : static struct lookup const lasts[] = {
     352                 :     {"last-Sunday", TM_SUNDAY},
     353                 :     {"last-Monday", TM_MONDAY},
     354                 :     {"last-Tuesday", TM_TUESDAY},
     355                 :     {"last-Wednesday", TM_WEDNESDAY},
     356                 :     {"last-Thursday", TM_THURSDAY},
     357                 :     {"last-Friday", TM_FRIDAY},
     358                 :     {"last-Saturday", TM_SATURDAY},
     359                 :     {NULL, 0}
     360                 : };
     361                 : 
     362                 : static struct lookup const begin_years[] = {
     363                 :     {"minimum", YR_MINIMUM},
     364                 :     {"maximum", YR_MAXIMUM},
     365                 :     {NULL, 0}
     366                 : };
     367                 : 
     368                 : static struct lookup const end_years[] = {
     369                 :     {"minimum", YR_MINIMUM},
     370                 :     {"maximum", YR_MAXIMUM},
     371                 :     {"only", YR_ONLY},
     372                 :     {NULL, 0}
     373                 : };
     374                 : 
     375                 : static struct lookup const leap_types[] = {
     376                 :     {"Rolling", true},
     377                 :     {"Stationary", false},
     378                 :     {NULL, 0}
     379                 : };
     380                 : 
     381                 : static const int len_months[2][MONSPERYEAR] = {
     382                 :     {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
     383                 :     {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
     384                 : };
     385                 : 
     386                 : static const int len_years[2] = {
     387                 :     DAYSPERNYEAR, DAYSPERLYEAR
     388                 : };
     389                 : 
     390                 : static struct attype
     391                 : {
     392                 :     zic_t       at;
     393                 :     bool        dontmerge;
     394                 :     unsigned char type;
     395                 : }          *attypes;
     396                 : static zic_t utoffs[TZ_MAX_TYPES];
     397                 : static char isdsts[TZ_MAX_TYPES];
     398                 : static unsigned char desigidx[TZ_MAX_TYPES];
     399                 : static bool ttisstds[TZ_MAX_TYPES];
     400                 : static bool ttisuts[TZ_MAX_TYPES];
     401                 : static char chars[TZ_MAX_CHARS];
     402                 : static zic_t trans[TZ_MAX_LEAPS];
     403                 : static zic_t corr[TZ_MAX_LEAPS];
     404                 : static char roll[TZ_MAX_LEAPS];
     405                 : 
     406                 : /*
     407                 :  * Memory allocation.
     408                 :  */
     409                 : 
     410                 : static void
     411 UIC           0 : memory_exhausted(const char *msg)
     412                 : {
     413 UBC           0 :     fprintf(stderr, _("%s: Memory exhausted: %s\n"), progname, msg);
     414 UIC           0 :     exit(EXIT_FAILURE);
     415 EUB             : }
     416                 : 
     417                 : static size_t
     418 GIC       18480 : size_product(size_t nitems, size_t itemsize)
     419                 : {
     420 CBC       18480 :     if (SIZE_MAX / itemsize < nitems)
     421 UIC           0 :         memory_exhausted(_("size overflow"));
     422 CBC       18480 :     return nitems * itemsize;
     423 EUB             : }
     424 ECB             : 
     425                 : static void *
     426 GIC       86658 : memcheck(void *ptr)
     427                 : {
     428 CBC       86658 :     if (ptr == NULL)
     429 UIC           0 :         memory_exhausted(strerror(errno));
     430 CBC       86658 :     return ptr;
     431 EUB             : }
     432 ECB             : 
     433                 : static void *
     434 GIC       22460 : emalloc(size_t size)
     435                 : {
     436 CBC       22460 :     return memcheck(malloc(size));
     437                 : }
     438 ECB             : 
     439                 : static void *
     440 GIC         244 : erealloc(void *ptr, size_t size)
     441                 : {
     442 CBC         244 :     return memcheck(realloc(ptr, size));
     443                 : }
     444 ECB             : 
     445                 : static char *
     446 GIC       63954 : ecpyalloc(char const *str)
     447                 : {
     448 CBC       63954 :     return memcheck(strdup(str));
     449                 : }
     450 ECB             : 
     451                 : static void *
     452 GIC       85516 : growalloc(void *ptr, size_t itemsize, ptrdiff_t nitems, ptrdiff_t *nitems_alloc)
     453                 : {
     454 CBC       85516 :     if (nitems < *nitems_alloc)
     455 GIC       85272 :         return ptr;
     456 ECB             :     else
     457                 :     {
     458 GIC         244 :         ptrdiff_t   nitems_max = PTRDIFF_MAX - WORK_AROUND_QTBUG_53071;
     459             244 :         ptrdiff_t   amax = nitems_max < SIZE_MAX ? nitems_max : SIZE_MAX;
     460 ECB             : 
     461 CBC         244 :         if ((amax - 1) / 3 * 2 < *nitems_alloc)
     462 UIC           0 :             memory_exhausted(_("integer overflow"));
     463 CBC         244 :         *nitems_alloc += (*nitems_alloc >> 1) + 1;
     464 GBC         244 :         return erealloc(ptr, size_product(*nitems_alloc, itemsize));
     465 ECB             :     }
     466                 : }
     467                 : 
     468                 : /*
     469                 :  * Error handling.
     470                 :  */
     471                 : 
     472                 : static void
     473 GIC     5816396 : eats(char const *name, lineno_t num, char const *rname, lineno_t rnum)
     474                 : {
     475 CBC     5816396 :     filename = name;
     476 GIC     5816396 :     linenum = num;
     477 CBC     5816396 :     rfilename = rname;
     478         5816396 :     rlinenum = rnum;
     479         5816396 : }
     480 ECB             : 
     481                 : static void
     482 GIC       33112 : eat(char const *name, lineno_t num)
     483                 : {
     484 CBC       33112 :     eats(name, num, NULL, -1);
     485 GIC       33112 : }
     486 ECB             : 
     487                 : static void
     488 UIC           0 : verror(const char *string, va_list args)
     489                 : {
     490 EUB             :     /*
     491                 :      * Match the format of "cc" to allow sh users to zic ... 2>&1 | error -t
     492                 :      * "*" -v on BSD systems.
     493                 :      */
     494 UIC           0 :     if (filename)
     495               0 :         fprintf(stderr, _("\"%s\", line %d: "), filename, linenum);
     496 UBC           0 :     vfprintf(stderr, string, args);
     497               0 :     if (rfilename != NULL)
     498               0 :         fprintf(stderr, _(" (rule from \"%s\", line %d)"),
     499 EUB             :                 rfilename, rlinenum);
     500 UBC           0 :     fprintf(stderr, "\n");
     501 UIC           0 : }
     502 EUB             : 
     503                 : static void
     504 UIC           0 : error(const char *string,...)
     505                 : {
     506 EUB             :     va_list     args;
     507                 : 
     508 UIC           0 :     va_start(args, string);
     509               0 :     verror(string, args);
     510 UBC           0 :     va_end(args);
     511               0 :     errors = true;
     512               0 : }
     513 EUB             : 
     514                 : static void
     515 UIC           0 : warning(const char *string,...)
     516                 : {
     517 EUB             :     va_list     args;
     518                 : 
     519 UIC           0 :     fprintf(stderr, _("warning: "));
     520               0 :     va_start(args, string);
     521 UBC           0 :     verror(string, args);
     522               0 :     va_end(args);
     523               0 :     warnings = true;
     524               0 : }
     525 EUB             : 
     526                 : static void
     527 GIC        1412 : close_file(FILE *stream, char const *dir, char const *name)
     528                 : {
     529 CBC        1412 :     char const *e = (ferror(stream) ? _("I/O error")
     530 GIC        1412 :                      : fclose(stream) != 0 ? strerror(errno) : NULL);
     531 ECB             : 
     532 CBC        1412 :     if (e)
     533                 :     {
     534 LBC           0 :         fprintf(stderr, "%s: %s%s%s%s%s\n", progname,
     535                 :                 dir ? dir : "", dir ? "/" : "",
     536 EUB             :                 name ? name : "", name ? ": " : "",
     537                 :                 e);
     538 UIC           0 :         exit(EXIT_FAILURE);
     539                 :     }
     540 GBC        1412 : }
     541                 : 
     542 ECB             : static void
     543 UIC           0 : usage(FILE *stream, int status)
     544                 : {
     545 UBC           0 :     fprintf(stream,
     546                 :             _("%s: usage is %s [ --version ] [ --help ] [ -v ] [ -P ] \\\n"
     547 EUB             :               "\t[ -b {slim|fat} ] [ -d directory ] [ -l localtime ]"
     548                 :               " [ -L leapseconds ] \\\n"
     549                 :               "\t[ -p posixrules ] [ -r '[@lo][/@hi]' ] [ -t localtime-link ] \\\n"
     550                 :               "\t[ filename ... ]\n\n"
     551                 :               "Report bugs to %s.\n"),
     552                 :             progname, progname, PACKAGE_BUGREPORT);
     553 UIC           0 :     if (status == EXIT_SUCCESS)
     554               0 :         close_file(stream, NULL, NULL);
     555 UBC           0 :     exit(status);
     556 EUB             : }
     557                 : 
     558                 : /* Change the working directory to DIR, possibly creating DIR and its
     559                 :    ancestors.  After this is done, all files are accessed with names
     560                 :    relative to DIR.  */
     561                 : static void
     562 GIC           4 : change_directory(char const *dir)
     563                 : {
     564 CBC           4 :     if (chdir(dir) != 0)
     565                 :     {
     566               2 :         int         chdir_errno = errno;
     567                 : 
     568               2 :         if (chdir_errno == ENOENT)
     569                 :         {
     570               2 :             mkdirs(dir, false);
     571 GIC           2 :             chdir_errno = chdir(dir) == 0 ? 0 : errno;
     572 ECB             :         }
     573 CBC           2 :         if (chdir_errno != 0)
     574                 :         {
     575 LBC           0 :             fprintf(stderr, _("%s: Can't chdir to %s: %s\n"),
     576                 :                     progname, dir, strerror(chdir_errno));
     577 UBC           0 :             exit(EXIT_FAILURE);
     578                 :         }
     579 EUB             :     }
     580 GIC           4 : }
     581                 : 
     582 ECB             : #define TIME_T_BITS_IN_FILE 64
     583                 : 
     584                 : /* The minimum and maximum values representable in a TZif file.  */
     585                 : static zic_t const min_time = MINVAL(zic_t, TIME_T_BITS_IN_FILE);
     586                 : static zic_t const max_time = MAXVAL(zic_t, TIME_T_BITS_IN_FILE);
     587                 : 
     588                 : /* The minimum, and one less than the maximum, values specified by
     589                 :    the -r option.  These default to MIN_TIME and MAX_TIME.  */
     590                 : static zic_t lo_time = MINVAL(zic_t, TIME_T_BITS_IN_FILE);
     591                 : static zic_t hi_time = MAXVAL(zic_t, TIME_T_BITS_IN_FILE);
     592                 : 
     593                 : /* The time specified by an Expires line, or negative if no such line.  */
     594                 : static zic_t leapexpires = -1;
     595                 : 
     596                 : /* The time specified by an #expires comment, or negative if no such line.  */
     597                 : static zic_t comment_leapexpires = -1;
     598                 : 
     599                 : /* Set the time range of the output to TIMERANGE.
     600                 :    Return true if successful.  */
     601                 : static bool
     602 UIC           0 : timerange_option(char *timerange)
     603                 : {
     604 UBC           0 :     int64       lo = min_time,
     605 UIC           0 :                 hi = max_time;
     606 UBC           0 :     char       *lo_end = timerange,
     607 EUB             :                *hi_end;
     608                 : 
     609 UIC           0 :     if (*timerange == '@')
     610                 :     {
     611 UBC           0 :         errno = 0;
     612 UIC           0 :         lo = strtoimax(timerange + 1, &lo_end, 10);
     613 UBC           0 :         if (lo_end == timerange + 1 || (lo == PG_INT64_MAX && errno == ERANGE))
     614               0 :             return false;
     615 EUB             :     }
     616 UBC           0 :     hi_end = lo_end;
     617 UIC           0 :     if (lo_end[0] == '/' && lo_end[1] == '@')
     618 EUB             :     {
     619 UBC           0 :         errno = 0;
     620 UIC           0 :         hi = strtoimax(lo_end + 2, &hi_end, 10);
     621 UBC           0 :         if (hi_end == lo_end + 2 || hi == PG_INT64_MIN)
     622               0 :             return false;
     623               0 :         hi -= !(hi == PG_INT64_MAX && errno == ERANGE);
     624 EUB             :     }
     625 UBC           0 :     if (*hi_end || hi < lo || max_time < lo || hi < min_time)
     626 UIC           0 :         return false;
     627 UBC           0 :     lo_time = lo < min_time ? min_time : lo;
     628               0 :     hi_time = max_time < hi ? max_time : hi;
     629               0 :     return true;
     630 EUB             : }
     631                 : 
     632                 : static const char *psxrules;
     633                 : static const char *lcltime;
     634                 : static const char *directory;
     635                 : static const char *leapsec;
     636                 : static const char *tzdefault;
     637                 : 
     638                 : /* -1 if the TZif output file should be slim, 0 if default, 1 if the
     639                 :    output should be fat for backward compatibility.  ZIC_BLOAT_DEFAULT
     640                 :    determines the default.  */
     641                 : static int  bloat;
     642                 : 
     643                 : static bool
     644 GIC      141680 : want_bloat(void)
     645                 : {
     646 CBC      141680 :     return 0 <= bloat;
     647                 : }
     648 ECB             : 
     649                 : #ifndef ZIC_BLOAT_DEFAULT
     650                 : #define ZIC_BLOAT_DEFAULT "slim"
     651                 : #endif
     652                 : 
     653                 : int
     654 GIC           4 : main(int argc, char **argv)
     655            6404 : {
     656 ECB             :     int         c,
     657                 :                 k;
     658                 :     ptrdiff_t   i,
     659                 :                 j;
     660 GIC           4 :     bool        timerange_given = false;
     661                 : 
     662 ECB             : #ifndef WIN32
     663 GIC           4 :     umask(umask(S_IWGRP | S_IWOTH) | (S_IWGRP | S_IWOTH));
     664                 : #endif
     665 CBC           4 :     progname = argv[0];
     666                 :     if (TYPE_BIT(zic_t) < 64)
     667 ECB             :     {
     668                 :         fprintf(stderr, "%s: %s\n", progname,
     669                 :                 _("wild compilation-time specification of zic_t"));
     670                 :         return EXIT_FAILURE;
     671                 :     }
     672 GIC          16 :     for (k = 1; k < argc; k++)
     673              12 :         if (strcmp(argv[k], "--version") == 0)
     674 ECB             :         {
     675 LBC           0 :             printf("zic %s\n", PG_VERSION);
     676 UIC           0 :             close_file(stdout, NULL, NULL);
     677 UBC           0 :             return EXIT_SUCCESS;
     678 EUB             :         }
     679 GBC          12 :         else if (strcmp(argv[k], "--help") == 0)
     680                 :         {
     681 LBC           0 :             usage(stdout, EXIT_SUCCESS);
     682                 :         }
     683 GBC           8 :     while ((c = getopt(argc, argv, "b:d:l:L:p:Pr:st:vy:")) != EOF && c != -1)
     684 GIC           4 :         switch (c)
     685 ECB             :         {
     686 LBC           0 :             default:
     687 UIC           0 :                 usage(stderr, EXIT_FAILURE);
     688 UBC           0 :             case 'b':
     689               0 :                 if (strcmp(optarg, "slim") == 0)
     690 EUB             :                 {
     691 UBC           0 :                     if (0 < bloat)
     692 UIC           0 :                         error(_("incompatible -b options"));
     693 UBC           0 :                     bloat = -1;
     694 EUB             :                 }
     695 UBC           0 :                 else if (strcmp(optarg, "fat") == 0)
     696                 :                 {
     697               0 :                     if (bloat < 0)
     698 UIC           0 :                         error(_("incompatible -b options"));
     699 UBC           0 :                     bloat = 1;
     700 EUB             :                 }
     701                 :                 else
     702 UIC           0 :                     error(_("invalid option: -b '%s'"), optarg);
     703               0 :                 break;
     704 GBC           4 :             case 'd':
     705               4 :                 if (directory == NULL)
     706 CBC           4 :                     directory = strdup(optarg);
     707 ECB             :                 else
     708                 :                 {
     709 UIC           0 :                     fprintf(stderr,
     710                 :                             _("%s: More than one -d option specified\n"),
     711 EUB             :                             progname);
     712 UIC           0 :                     return EXIT_FAILURE;
     713                 :                 }
     714 GBC           4 :                 break;
     715 UIC           0 :             case 'l':
     716 LBC           0 :                 if (lcltime == NULL)
     717 UBC           0 :                     lcltime = strdup(optarg);
     718 EUB             :                 else
     719                 :                 {
     720 UIC           0 :                     fprintf(stderr,
     721                 :                             _("%s: More than one -l option specified\n"),
     722 EUB             :                             progname);
     723 UIC           0 :                     return EXIT_FAILURE;
     724                 :                 }
     725 UBC           0 :                 break;
     726 UIC           0 :             case 'p':
     727 UBC           0 :                 if (psxrules == NULL)
     728               0 :                     psxrules = strdup(optarg);
     729 EUB             :                 else
     730                 :                 {
     731 UIC           0 :                     fprintf(stderr,
     732                 :                             _("%s: More than one -p option specified\n"),
     733 EUB             :                             progname);
     734 UIC           0 :                     return EXIT_FAILURE;
     735                 :                 }
     736 UBC           0 :                 break;
     737 UIC           0 :             case 't':
     738 UBC           0 :                 if (tzdefault != NULL)
     739 EUB             :                 {
     740 UBC           0 :                     fprintf(stderr,
     741                 :                             _("%s: More than one -t option"
     742 EUB             :                               " specified\n"),
     743                 :                             progname);
     744 UIC           0 :                     return EXIT_FAILURE;
     745                 :                 }
     746 UBC           0 :                 tzdefault = optarg;
     747 UIC           0 :                 break;
     748 UBC           0 :             case 'y':
     749               0 :                 warning(_("-y ignored"));
     750               0 :                 break;
     751               0 :             case 'L':
     752               0 :                 if (leapsec == NULL)
     753               0 :                     leapsec = strdup(optarg);
     754 EUB             :                 else
     755                 :                 {
     756 UIC           0 :                     fprintf(stderr,
     757                 :                             _("%s: More than one -L option specified\n"),
     758 EUB             :                             progname);
     759 UIC           0 :                     return EXIT_FAILURE;
     760                 :                 }
     761 UBC           0 :                 break;
     762 UIC           0 :             case 'v':
     763 UBC           0 :                 noise = true;
     764               0 :                 break;
     765               0 :             case 'P':
     766               0 :                 print_abbrevs = true;
     767               0 :                 print_cutoff = time(NULL);
     768               0 :                 break;
     769               0 :             case 'r':
     770               0 :                 if (timerange_given)
     771 EUB             :                 {
     772 UBC           0 :                     fprintf(stderr,
     773                 :                             _("%s: More than one -r option specified\n"),
     774 EUB             :                             progname);
     775 UIC           0 :                     return EXIT_FAILURE;
     776                 :                 }
     777 UBC           0 :                 if (!timerange_option(optarg))
     778                 :                 {
     779               0 :                     fprintf(stderr,
     780                 :                             _("%s: invalid time range: %s\n"),
     781 EUB             :                             progname, optarg);
     782 UIC           0 :                     return EXIT_FAILURE;
     783                 :                 }
     784 UBC           0 :                 timerange_given = true;
     785 UIC           0 :                 break;
     786 UBC           0 :             case 's':
     787               0 :                 warning(_("-s ignored"));
     788               0 :                 break;
     789 EUB             :         }
     790 GBC           4 :     if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
     791 UIC           0 :         usage(stderr, EXIT_FAILURE);    /* usage message by request */
     792 CBC           4 :     if (bloat == 0)
     793 EUB             :     {
     794 ECB             :         static char const bloat_default[] = ZIC_BLOAT_DEFAULT;
     795                 : 
     796 GIC           4 :         if (strcmp(bloat_default, "slim") == 0)
     797               4 :             bloat = -1;
     798 LBC           0 :         else if (strcmp(bloat_default, "fat") == 0)
     799               0 :             bloat = 1;
     800 EUB             :         else
     801 UBC           0 :             abort();            /* Configuration error.  */
     802                 :     }
     803 GBC           4 :     if (directory == NULL)
     804 UIC           0 :         directory = "data";
     805 CBC           4 :     if (tzdefault == NULL)
     806 GBC           4 :         tzdefault = TZDEFAULT;
     807 ECB             : 
     808 CBC           4 :     if (optind < argc && leapsec != NULL)
     809                 :     {
     810 LBC           0 :         infile(leapsec);
     811 UIC           0 :         adjleap();
     812 EUB             :     }
     813                 : 
     814 GIC           8 :     for (k = optind; k < argc; k++)
     815               4 :         infile(argv[k]);
     816 CBC           4 :     if (errors)
     817 LBC           0 :         return EXIT_FAILURE;
     818 CBC           4 :     associate();
     819 GBC           4 :     change_directory(directory);
     820 CBC        1412 :     for (i = 0; i < nzones; i = j)
     821 ECB             :     {
     822                 :         /*
     823                 :          * Find the next non-continuation zone entry.
     824                 :          */
     825 GIC        7812 :         for (j = i + 1; j < nzones && zones[j].z_name == NULL; ++j)
     826            6404 :             continue;
     827 CBC        1408 :         outzone(&zones[i], j - i);
     828 ECB             :     }
     829                 : 
     830                 :     /*
     831                 :      * Make links.
     832                 :      */
     833 GIC         984 :     for (i = 0; i < nlinks; ++i)
     834                 :     {
     835 CBC         980 :         eat(links[i].l_filename, links[i].l_linenum);
     836 GIC         980 :         dolink(links[i].l_target, links[i].l_linkname, false);
     837 CBC         980 :         if (noise)
     838 LBC           0 :             for (j = 0; j < nlinks; ++j)
     839               0 :                 if (strcmp(links[i].l_linkname,
     840 UBC           0 :                            links[j].l_target) == 0)
     841               0 :                     warning(_("link to link"));
     842 EUB             :     }
     843 GBC           4 :     if (lcltime != NULL)
     844                 :     {
     845 LBC           0 :         eat(_("command line"), 1);
     846 UIC           0 :         dolink(lcltime, tzdefault, true);
     847 EUB             :     }
     848 GBC           4 :     if (psxrules != NULL)
     849                 :     {
     850 LBC           0 :         eat(_("command line"), 1);
     851 UIC           0 :         dolink(psxrules, TZDEFRULES, true);
     852 EUB             :     }
     853 GBC           4 :     if (warnings && (ferror(stderr) || fclose(stderr) != 0))
     854 UIC           0 :         return EXIT_FAILURE;
     855 CBC           4 :     return errors ? EXIT_FAILURE : EXIT_SUCCESS;
     856 EUB             : }
     857 ECB             : 
     858                 : static bool
     859 GIC        4700 : componentcheck(char const *name, char const *component,
     860                 :                char const *component_end)
     861 ECB             : {
     862                 :     enum
     863                 :     {
     864                 :     component_len_max = 14};
     865 GIC        4700 :     ptrdiff_t   component_len = component_end - component;
     866                 : 
     867 CBC        4700 :     if (component_len == 0)
     868                 :     {
     869 LBC           0 :         if (!*name)
     870 UIC           0 :             error(_("empty file name"));
     871 EUB             :         else
     872 UBC           0 :             error(_(component == name
     873                 :                     ? "file name '%s' begins with '/'"
     874 EUB             :                     : *component_end
     875                 :                     ? "file name '%s' contains '//'"
     876                 :                     : "file name '%s' ends with '/'"),
     877                 :                   name);
     878 UIC           0 :         return false;
     879                 :     }
     880 GBC        4700 :     if (0 < component_len && component_len <= 2
     881 GIC          56 :         && component[0] == '.' && component_end[-1] == '.')
     882 ECB             :     {
     883 LBC           0 :         int         len = component_len;
     884                 : 
     885 UBC           0 :         error(_("file name '%s' contains '%.*s' component"),
     886                 :               name, len, component);
     887               0 :         return false;
     888                 :     }
     889 GBC        4700 :     if (noise)
     890                 :     {
     891 LBC           0 :         if (0 < component_len && component[0] == '-')
     892 UIC           0 :             warning(_("file name '%s' component contains leading '-'"),
     893 EUB             :                     name);
     894 UBC           0 :         if (component_len_max < component_len)
     895 UIC           0 :             warning(_("file name '%s' contains overlength component"
     896 EUB             :                       " '%.*s...'"),
     897                 :                     name, component_len_max, component);
     898                 :     }
     899 GIC        4700 :     return true;
     900                 : }
     901 ECB             : 
     902                 : static bool
     903 GIC        2388 : namecheck(const char *name)
     904                 : {
     905 ECB             :     char const *cp;
     906                 : 
     907                 :     /* Benign characters in a portable file name.  */
     908                 :     static char const benign[] =
     909                 :     "-/_"
     910                 :     "abcdefghijklmnopqrstuvwxyz"
     911                 :     "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
     912                 : 
     913                 :     /*
     914                 :      * Non-control chars in the POSIX portable character set, excluding the
     915                 :      * benign characters.
     916                 :      */
     917                 :     static char const printable_and_not_benign[] =
     918                 :     " !\"#$%&'()*+,.0123456789:;<=>?@[\\]^`{|}~";
     919                 : 
     920 GIC        2388 :     char const *component = name;
     921                 : 
     922 CBC       36336 :     for (cp = name; *cp; cp++)
     923                 :     {
     924           33948 :         unsigned char c = *cp;
     925                 : 
     926           33948 :         if (noise && !strchr(benign, c))
     927                 :         {
     928 LBC           0 :             warning((strchr(printable_and_not_benign, c)
     929                 :                      ? _("file name '%s' contains byte '%c'")
     930 EUB             :                      : _("file name '%s' contains byte '\\%o'")),
     931                 :                     name, c);
     932                 :         }
     933 GIC       33948 :         if (c == '/')
     934                 :         {
     935 CBC        2312 :             if (!componentcheck(name, component, cp))
     936 UIC           0 :                 return false;
     937 CBC        2312 :             component = cp + 1;
     938 EUB             :         }
     939 ECB             :     }
     940 GIC        2388 :     return componentcheck(name, component, cp);
     941                 : }
     942 ECB             : 
     943                 : /*
     944                 :  * Create symlink contents suitable for symlinking FROM to TO, as a
     945                 :  * freshly allocated string.  FROM should be a relative file name, and
     946                 :  * is relative to the global variable DIRECTORY.  TO can be either
     947                 :  * relative or absolute.
     948                 :  */
     949                 : #ifdef HAVE_SYMLINK
     950                 : static char *
     951 UIC           0 : relname(char const *target, char const *linkname)
     952                 : {
     953 EUB             :     size_t      i,
     954                 :                 taillen,
     955                 :                 dotdotetcsize;
     956 UIC           0 :     size_t      dir_len = 0,
     957               0 :                 dotdots = 0,
     958 UBC           0 :                 linksize = SIZE_MAX;
     959               0 :     char const *f = target;
     960               0 :     char       *result = NULL;
     961 EUB             : 
     962 UBC           0 :     if (*linkname == '/')
     963                 :     {
     964 EUB             :         /* Make F absolute too.  */
     965 UIC           0 :         size_t      len = strlen(directory);
     966               0 :         bool        needslash = len && directory[len - 1] != '/';
     967 EUB             : 
     968 UBC           0 :         linksize = len + needslash + strlen(target) + 1;
     969 UIC           0 :         f = result = emalloc(linksize);
     970 UBC           0 :         strcpy(result, directory);
     971               0 :         result[len] = '/';
     972               0 :         strcpy(result + len + needslash, target);
     973 EUB             :     }
     974 UBC           0 :     for (i = 0; f[i] && f[i] == linkname[i]; i++)
     975 UIC           0 :         if (f[i] == '/')
     976 UBC           0 :             dir_len = i + 1;
     977               0 :     for (; linkname[i]; i++)
     978               0 :         dotdots += linkname[i] == '/' && linkname[i - 1] != '/';
     979               0 :     taillen = strlen(f + dir_len);
     980               0 :     dotdotetcsize = 3 * dotdots + taillen + 1;
     981               0 :     if (dotdotetcsize <= linksize)
     982 EUB             :     {
     983 UBC           0 :         if (!result)
     984 UIC           0 :             result = emalloc(dotdotetcsize);
     985 UBC           0 :         for (i = 0; i < dotdots; i++)
     986               0 :             memcpy(result + 3 * i, "../", 3);
     987               0 :         memmove(result + 3 * dotdots, f + dir_len, taillen + 1);
     988 EUB             :     }
     989 UBC           0 :     return result;
     990                 : }
     991 EUB             : #endif                          /* HAVE_SYMLINK */
     992                 : 
     993                 : /* Hard link FROM to TO, following any symbolic links.
     994                 :    Return 0 if successful, an error number otherwise.  */
     995                 : static int
     996 GIC         992 : hardlinkerr(char const *target, char const *linkname)
     997                 : {
     998 CBC         992 :     int         r = linkat(AT_FDCWD, target, AT_FDCWD, linkname, AT_SYMLINK_FOLLOW);
     999                 : 
    1000             992 :     return r == 0 ? 0 : errno;
    1001                 : }
    1002 ECB             : 
    1003                 : static void
    1004 GIC         980 : dolink(char const *target, char const *linkname, bool staysymlink)
    1005                 : {
    1006 CBC         980 :     bool        remove_only = strcmp(target, "-") == 0;
    1007 GIC         980 :     bool        linkdirs_made = false;
    1008 ECB             :     int         link_errno;
    1009                 : 
    1010                 :     /*
    1011                 :      * We get to be careful here since there's a fair chance of root running
    1012                 :      * us.
    1013                 :      */
    1014 GIC         980 :     if (!remove_only && itsdir(target))
    1015                 :     {
    1016 LBC           0 :         fprintf(stderr, _("%s: linking target %s/%s failed: %s\n"),
    1017                 :                 progname, directory, target, strerror(EPERM));
    1018 UBC           0 :         exit(EXIT_FAILURE);
    1019                 :     }
    1020 GBC         980 :     if (staysymlink)
    1021 UIC           0 :         staysymlink = itssymlink(linkname);
    1022 CBC         980 :     if (remove(linkname) == 0)
    1023 GBC         490 :         linkdirs_made = true;
    1024 CBC         490 :     else if (errno != ENOENT)
    1025 ECB             :     {
    1026 LBC           0 :         char const *e = strerror(errno);
    1027                 : 
    1028 UBC           0 :         fprintf(stderr, _("%s: Can't remove %s/%s: %s\n"),
    1029                 :                 progname, directory, linkname, e);
    1030               0 :         exit(EXIT_FAILURE);
    1031                 :     }
    1032 GBC         980 :     if (remove_only)
    1033 UIC           0 :         return;
    1034 CBC         980 :     link_errno = staysymlink ? ENOTSUP : hardlinkerr(target, linkname);
    1035 GBC         980 :     if (link_errno == ENOENT && !linkdirs_made)
    1036 ECB             :     {
    1037 CBC          12 :         mkdirs(linkname, true);
    1038 GIC          12 :         linkdirs_made = true;
    1039 CBC          12 :         link_errno = hardlinkerr(target, linkname);
    1040 ECB             :     }
    1041 CBC         980 :     if (link_errno != 0)
    1042                 :     {
    1043 ECB             : #ifdef HAVE_SYMLINK
    1044 UIC           0 :         bool        absolute = *target == '/';
    1045               0 :         char       *linkalloc = absolute ? NULL : relname(target, linkname);
    1046 UBC           0 :         char const *contents = absolute ? target : linkalloc;
    1047               0 :         int         symlink_errno = symlink(contents, linkname) == 0 ? 0 : errno;
    1048 EUB             : 
    1049 UBC           0 :         if (!linkdirs_made
    1050 UIC           0 :             && (symlink_errno == ENOENT || symlink_errno == ENOTSUP))
    1051 EUB             :         {
    1052 UBC           0 :             mkdirs(linkname, true);
    1053 UIC           0 :             if (symlink_errno == ENOENT)
    1054 UBC           0 :                 symlink_errno = symlink(contents, linkname) == 0 ? 0 : errno;
    1055 EUB             :         }
    1056 UBC           0 :         free(linkalloc);
    1057 UIC           0 :         if (symlink_errno == 0)
    1058 EUB             :         {
    1059 UBC           0 :             if (link_errno != ENOTSUP)
    1060 UIC           0 :                 warning(_("symbolic link used because hard link failed: %s"),
    1061 EUB             :                         strerror(link_errno));
    1062                 :         }
    1063                 :         else
    1064                 : #endif                          /* HAVE_SYMLINK */
    1065                 :         {
    1066                 :             FILE       *fp,
    1067                 :                        *tp;
    1068                 :             int         c;
    1069                 : 
    1070 UIC           0 :             fp = fopen(target, "rb");
    1071               0 :             if (!fp)
    1072 EUB             :             {
    1073 UBC           0 :                 char const *e = strerror(errno);
    1074                 : 
    1075               0 :                 fprintf(stderr, _("%s: Can't read %s/%s: %s\n"),
    1076                 :                         progname, directory, target, e);
    1077               0 :                 exit(EXIT_FAILURE);
    1078                 :             }
    1079               0 :             tp = fopen(linkname, "wb");
    1080 UIC           0 :             if (!tp)
    1081 EUB             :             {
    1082 UBC           0 :                 char const *e = strerror(errno);
    1083                 : 
    1084               0 :                 fprintf(stderr, _("%s: Can't create %s/%s: %s\n"),
    1085                 :                         progname, directory, linkname, e);
    1086               0 :                 exit(EXIT_FAILURE);
    1087                 :             }
    1088               0 :             while ((c = getc(fp)) != EOF)
    1089 UIC           0 :                 putc(c, tp);
    1090 UBC           0 :             close_file(fp, directory, target);
    1091               0 :             close_file(tp, directory, linkname);
    1092               0 :             if (link_errno != ENOTSUP)
    1093               0 :                 warning(_("copy used because hard link failed: %s"),
    1094 EUB             :                         strerror(link_errno));
    1095                 : #ifdef HAVE_SYMLINK
    1096 UIC           0 :             else if (symlink_errno != ENOTSUP)
    1097               0 :                 warning(_("copy used because symbolic link failed: %s"),
    1098 EUB             :                         strerror(symlink_errno));
    1099                 : #endif
    1100                 :         }
    1101                 :     }
    1102                 : }
    1103                 : 
    1104                 : /* Return true if NAME is a directory.  */
    1105                 : static bool
    1106 GIC         980 : itsdir(char const *name)
    1107                 : {
    1108 ECB             :     struct stat st;
    1109 GIC         980 :     int         res = stat(name, &st);
    1110                 : #ifdef S_ISDIR
    1111 CBC         980 :     if (res == 0)
    1112 GIC         980 :         return S_ISDIR(st.st_mode) != 0;
    1113 ECB             : #endif
    1114 LBC           0 :     if (res == 0 || errno == EOVERFLOW)
    1115                 :     {
    1116 UBC           0 :         size_t      n = strlen(name);
    1117 UIC           0 :         char       *nameslashdot = emalloc(n + 3);
    1118 EUB             :         bool        dir;
    1119                 : 
    1120 UIC           0 :         memcpy(nameslashdot, name, n);
    1121               0 :         strcpy(&nameslashdot[n], &"/."[!(n && name[n - 1] != '/')]);
    1122 UBC           0 :         dir = stat(nameslashdot, &st) == 0 || errno == EOVERFLOW;
    1123               0 :         free(nameslashdot);
    1124               0 :         return dir;
    1125 EUB             :     }
    1126 UBC           0 :     return false;
    1127                 : }
    1128 EUB             : 
    1129                 : /* Return true if NAME is a symbolic link.  */
    1130                 : static bool
    1131 UIC           0 : itssymlink(char const *name)
    1132                 : {
    1133 EUB             : #ifdef HAVE_SYMLINK
    1134                 :     char        c;
    1135                 : 
    1136 UIC           0 :     return 0 <= readlink(name, &c, 1);
    1137                 : #else
    1138 EUB             :     return false;
    1139                 : #endif
    1140                 : }
    1141                 : 
    1142                 : /*
    1143                 :  * Associate sets of rules with zones.
    1144                 :  */
    1145                 : 
    1146                 : /*
    1147                 :  * Sort by rule name.
    1148                 :  */
    1149                 : 
    1150                 : static int
    1151 GIC       47136 : rcomp(const void *cp1, const void *cp2)
    1152                 : {
    1153 CBC       94272 :     return strcmp(((const struct rule *) cp1)->r_name,
    1154 GIC       47136 :                   ((const struct rule *) cp2)->r_name);
    1155 ECB             : }
    1156                 : 
    1157                 : static void
    1158 GIC           4 : associate(void)
    1159                 : {
    1160 ECB             :     struct zone *zp;
    1161                 :     struct rule *rp;
    1162                 :     ptrdiff_t   i,
    1163                 :                 j,
    1164                 :                 base,
    1165                 :                 out;
    1166                 : 
    1167 GIC           4 :     if (nrules != 0)
    1168                 :     {
    1169 CBC           4 :         qsort(rules, nrules, sizeof *rules, rcomp);
    1170 GIC        8028 :         for (i = 0; i < nrules - 1; ++i)
    1171 ECB             :         {
    1172 CBC        8540 :             if (strcmp(rules[i].r_name,
    1173 GIC        8024 :                        rules[i + 1].r_name) != 0)
    1174 CBC         516 :                 continue;
    1175           15016 :             if (strcmp(rules[i].r_filename,
    1176            7508 :                        rules[i + 1].r_filename) == 0)
    1177            7508 :                 continue;
    1178 LBC           0 :             eat(rules[i].r_filename, rules[i].r_linenum);
    1179               0 :             warning(_("same rule name in multiple files"));
    1180 UBC           0 :             eat(rules[i + 1].r_filename, rules[i + 1].r_linenum);
    1181               0 :             warning(_("same rule name in multiple files"));
    1182               0 :             for (j = i + 2; j < nrules; ++j)
    1183 EUB             :             {
    1184 UBC           0 :                 if (strcmp(rules[i].r_name,
    1185 UIC           0 :                            rules[j].r_name) != 0)
    1186 UBC           0 :                     break;
    1187               0 :                 if (strcmp(rules[i].r_filename,
    1188               0 :                            rules[j].r_filename) == 0)
    1189               0 :                     continue;
    1190               0 :                 if (strcmp(rules[i + 1].r_filename,
    1191               0 :                            rules[j].r_filename) == 0)
    1192               0 :                     continue;
    1193               0 :                 break;
    1194 EUB             :             }
    1195 UBC           0 :             i = j - 1;
    1196                 :         }
    1197 EUB             :     }
    1198 GIC        7816 :     for (i = 0; i < nzones; ++i)
    1199                 :     {
    1200 CBC        7812 :         zp = &zones[i];
    1201 GIC        7812 :         zp->z_rules = NULL;
    1202 CBC        7812 :         zp->z_nrules = 0;
    1203 ECB             :     }
    1204 CBC         524 :     for (base = 0; base < nrules; base = out)
    1205                 :     {
    1206             520 :         rp = &rules[base];
    1207 GIC        8028 :         for (out = base + 1; out < nrules; ++out)
    1208 CBC        8024 :             if (strcmp(rp->r_name, rules[out].r_name) != 0)
    1209             516 :                 break;
    1210         1016080 :         for (i = 0; i < nzones; ++i)
    1211 ECB             :         {
    1212 CBC     1015560 :             zp = &zones[i];
    1213 GIC     1015560 :             if (strcmp(zp->z_rule, rp->r_name) != 0)
    1214 CBC     1012444 :                 continue;
    1215            3116 :             zp->z_rules = rp;
    1216            3116 :             zp->z_nrules = out - base;
    1217 ECB             :         }
    1218                 :     }
    1219 GIC        7816 :     for (i = 0; i < nzones; ++i)
    1220                 :     {
    1221 CBC        7812 :         zp = &zones[i];
    1222 GIC        7812 :         if (zp->z_nrules == 0)
    1223 ECB             :         {
    1224                 :             /*
    1225                 :              * Maybe we have a local standard time offset.
    1226                 :              */
    1227 GIC        4696 :             eat(zp->z_filename, zp->z_linenum);
    1228            4696 :             zp->z_save = getsave(zp->z_rule, &zp->z_isdst);
    1229 ECB             : 
    1230                 :             /*
    1231                 :              * Note, though, that if there's no rule, a '%s' in the format is
    1232                 :              * a bad thing.
    1233                 :              */
    1234 GIC        4696 :             if (zp->z_format_specifier == 's')
    1235 UIC           0 :                 error("%s", _("%s in ruleless zone"));
    1236 ECB             :         }
    1237 EUB             :     }
    1238 GIC           4 :     if (errors)
    1239 UIC           0 :         exit(EXIT_FAILURE);
    1240 CBC           4 : }
    1241 EUB             : 
    1242 ECB             : static void
    1243 GIC           4 : infile(const char *name)
    1244                 : {
    1245 ECB             :     FILE       *fp;
    1246                 :     char      **fields;
    1247                 :     char       *cp;
    1248                 :     const struct lookup *lp;
    1249                 :     int         nfields;
    1250                 :     bool        wantcont;
    1251                 :     lineno_t    num;
    1252                 :     char        buf[BUFSIZ];
    1253                 : 
    1254 GIC           4 :     if (strcmp(name, "-") == 0)
    1255                 :     {
    1256 LBC           0 :         name = _("standard input");
    1257 UIC           0 :         fp = stdin;
    1258 EUB             :     }
    1259 GBC           4 :     else if ((fp = fopen(name, "r")) == NULL)
    1260                 :     {
    1261 LBC           0 :         const char *e = strerror(errno);
    1262                 : 
    1263 UBC           0 :         fprintf(stderr, _("%s: Cannot open %s: %s\n"),
    1264                 :                 progname, name, e);
    1265               0 :         exit(EXIT_FAILURE);
    1266                 :     }
    1267 GBC           4 :     wantcont = false;
    1268 GIC           4 :     for (num = 1;; ++num)
    1269 ECB             :     {
    1270 CBC       16832 :         eat(name, num);
    1271 GIC       16832 :         if (fgets(buf, sizeof buf, fp) != buf)
    1272 CBC           4 :             break;
    1273           16828 :         cp = strchr(buf, '\n');
    1274           16828 :         if (cp == NULL)
    1275 ECB             :         {
    1276 LBC           0 :             error(_("line too long"));
    1277 UIC           0 :             exit(EXIT_FAILURE);
    1278 EUB             :         }
    1279 GBC       16828 :         *cp = '\0';
    1280 GIC       16828 :         fields = getfields(buf);
    1281 CBC       16828 :         nfields = 0;
    1282          143572 :         while (fields[nfields] != NULL)
    1283 ECB             :         {
    1284                 :             static char nada;
    1285                 : 
    1286 GIC      126744 :             if (strcmp(fields[nfields], "-") == 0)
    1287           15900 :                 fields[nfields] = &nada;
    1288 CBC      126744 :             ++nfields;
    1289 ECB             :         }
    1290 CBC       16828 :         if (nfields == 0)
    1291                 :         {
    1292               8 :             if (name == leapsec && *buf == '#')
    1293                 :             {
    1294 ECB             :                 /*
    1295                 :                  * PG: INT64_FORMAT isn't portable for sscanf, so be content
    1296                 :                  * with scanning a "long".  Once we are requiring C99 in all
    1297                 :                  * live branches, it'd be sensible to adopt upstream's
    1298                 :                  * practice of using the <inttypes.h> macros.  But for now, we
    1299                 :                  * don't actually use this code, and it won't overflow before
    1300                 :                  * 2038 anyway.
    1301                 :                  */
    1302                 :                 long        cl_tmp;
    1303                 : 
    1304 UIC           0 :                 sscanf(buf, "#expires %ld", &cl_tmp);
    1305               0 :                 comment_leapexpires = cl_tmp;
    1306 EUB             :             }
    1307                 :         }
    1308 GIC       16820 :         else if (wantcont)
    1309                 :         {
    1310 CBC        6404 :             wantcont = inzcont(fields, nfields);
    1311                 :         }
    1312 ECB             :         else
    1313                 :         {
    1314 GIC       10416 :             struct lookup const *line_codes
    1315           10416 :             = name == leapsec ? leap_line_codes : zi_line_codes;
    1316 ECB             : 
    1317 CBC       10416 :             lp = byword(fields[0], line_codes);
    1318 GIC       10416 :             if (lp == NULL)
    1319 LBC           0 :                 error(_("input line of unknown type"));
    1320 ECB             :             else
    1321 GBC       10416 :                 switch (lp->l_value)
    1322                 :                 {
    1323 CBC        8028 :                     case LC_RULE:
    1324 GIC        8028 :                         inrule(fields, nfields);
    1325 CBC        8028 :                         wantcont = false;
    1326            8028 :                         break;
    1327            1408 :                     case LC_ZONE:
    1328            1408 :                         wantcont = inzone(fields, nfields);
    1329            1408 :                         break;
    1330             980 :                     case LC_LINK:
    1331             980 :                         inlink(fields, nfields);
    1332             980 :                         wantcont = false;
    1333             980 :                         break;
    1334 LBC           0 :                     case LC_LEAP:
    1335               0 :                         inleap(fields, nfields);
    1336 UBC           0 :                         wantcont = false;
    1337               0 :                         break;
    1338               0 :                     case LC_EXPIRES:
    1339               0 :                         inexpires(fields, nfields);
    1340               0 :                         wantcont = false;
    1341               0 :                         break;
    1342               0 :                     default:    /* "cannot happen" */
    1343               0 :                         fprintf(stderr,
    1344 EUB             :                                 _("%s: panic: Invalid l_value %d\n"),
    1345 UBC           0 :                                 progname, lp->l_value);
    1346 UIC           0 :                         exit(EXIT_FAILURE);
    1347 EUB             :                 }
    1348                 :         }
    1349 GIC       16828 :         free(fields);
    1350                 :     }
    1351 CBC           4 :     close_file(fp, NULL, filename);
    1352 GIC           4 :     if (wantcont)
    1353 LBC           0 :         error(_("expected continuation line not found"));
    1354 CBC           4 : }
    1355 EUB             : 
    1356 ECB             : /*
    1357                 :  * Convert a string of one of the forms
    1358                 :  *  h   -h  hh:mm   -hh:mm  hh:mm:ss    -hh:mm:ss
    1359                 :  * into a number of seconds.
    1360                 :  * A null string maps to zero.
    1361                 :  * Call error with errstring and return zero on errors.
    1362                 :  */
    1363                 : 
    1364                 : static zic_t
    1365 GIC       34968 : gethms(char const *string, char const *errstring)
    1366                 : {
    1367 ECB             :     /* PG: make hh be int not zic_t to avoid sscanf portability issues */
    1368                 :     int         hh;
    1369                 :     int         sign,
    1370 GIC       34968 :                 mm = 0,
    1371           34968 :                 ss = 0;
    1372 ECB             :     char        hhx,
    1373                 :                 mmx,
    1374                 :                 ssx,
    1375 GIC       34968 :                 xr = '0',
    1376                 :                 xs;
    1377 CBC       34968 :     int         tenths = 0;
    1378 GIC       34968 :     bool        ok = true;
    1379 ECB             : 
    1380 CBC       34968 :     if (string == NULL || *string == '\0')
    1381 GIC        4468 :         return 0;
    1382 CBC       30500 :     if (*string == '-')
    1383 ECB             :     {
    1384 CBC        3944 :         sign = -1;
    1385 GIC        3944 :         ++string;
    1386 ECB             :     }
    1387                 :     else
    1388 GIC       26556 :         sign = 1;
    1389           30500 :     switch (sscanf(string,
    1390 ECB             :                    "%d%c%d%c%d%c%1d%*[0]%c%*[0123456789]%c",
    1391                 :                    &hh, &hhx, &mm, &mmx, &ss, &ssx, &tenths, &xr, &xs))
    1392                 :     {
    1393 UIC           0 :         default:
    1394               0 :             ok = false;
    1395 UBC           0 :             break;
    1396               0 :         case 8:
    1397               0 :             ok = '0' <= xr && xr <= '9';
    1398 EUB             :             /* fallthrough */
    1399 UBC           0 :         case 7:
    1400 UIC           0 :             ok &= ssx == '.';
    1401 UBC           0 :             if (ok && noise)
    1402               0 :                 warning(_("fractional seconds rejected by"
    1403 EUB             :                           " pre-2018 versions of zic"));
    1404                 :             /* fallthrough */
    1405                 :         case 5:
    1406 GIC        1564 :             ok &= mmx == ':';
    1407                 :             /* fallthrough */
    1408 CBC        2400 :         case 3:
    1409 GIC        2400 :             ok &= hhx == ':';
    1410 ECB             :             /* fallthrough */
    1411 CBC       30500 :         case 1:
    1412 GIC       30500 :             break;
    1413 ECB             :     }
    1414 CBC       30500 :     if (!ok)
    1415                 :     {
    1416 LBC           0 :         error("%s", errstring);
    1417 UIC           0 :         return 0;
    1418 EUB             :     }
    1419 GBC       30500 :     if (hh < 0 ||
    1420 GIC       30500 :         mm < 0 || mm >= MINSPERHOUR ||
    1421 CBC       30500 :         ss < 0 || ss > SECSPERMIN)
    1422 ECB             :     {
    1423 LBC           0 :         error("%s", errstring);
    1424 UIC           0 :         return 0;
    1425 EUB             :     }
    1426                 :     /* Some compilers warn that this test is unsatisfiable for 32-bit ints */
    1427                 : #if INT_MAX > PG_INT32_MAX
    1428                 :     if (ZIC_MAX / SECSPERHOUR < hh)
    1429                 :     {
    1430                 :         error(_("time overflow"));
    1431                 :         return 0;
    1432                 :     }
    1433                 : #endif
    1434 GIC       30500 :     ss += 5 + ((ss ^ 1) & (xr == '0')) <= tenths;    /* Round to even.  */
    1435           30500 :     if (noise && (hh > HOURSPERDAY ||
    1436 LBC           0 :                   (hh == HOURSPERDAY && (mm != 0 || ss != 0))))
    1437               0 :         warning(_("values over 24 hours not handled by pre-2007 versions of zic"));
    1438 GBC       30500 :     return oadd(sign * (zic_t) hh * SECSPERHOUR,
    1439           30500 :                 sign * (mm * SECSPERMIN + ss));
    1440 ECB             : }
    1441                 : 
    1442                 : static zic_t
    1443 GIC       12724 : getsave(char *field, bool *isdst)
    1444                 : {
    1445 CBC       12724 :     int         dst = -1;
    1446                 :     zic_t       save;
    1447           12724 :     size_t      fieldlen = strlen(field);
    1448                 : 
    1449           12724 :     if (fieldlen != 0)
    1450                 :     {
    1451            8256 :         char       *ep = field + fieldlen - 1;
    1452                 : 
    1453            8256 :         switch (*ep)
    1454                 :         {
    1455 LBC           0 :             case 'd':
    1456 UIC           0 :                 dst = 1;
    1457 UBC           0 :                 *ep = '\0';
    1458               0 :                 break;
    1459               0 :             case 's':
    1460               0 :                 dst = 0;
    1461               0 :                 *ep = '\0';
    1462               0 :                 break;
    1463 EUB             :         }
    1464                 :     }
    1465 GIC       12724 :     save = gethms(field, _("invalid saved time"));
    1466           12724 :     *isdst = dst < 0 ? save != 0 : dst;
    1467 CBC       12724 :     return save;
    1468 ECB             : }
    1469                 : 
    1470                 : static void
    1471 GIC        8028 : inrule(char **fields, int nfields)
    1472                 : {
    1473 ECB             :     static struct rule r;
    1474                 : 
    1475 GIC        8028 :     if (nfields != RULE_FIELDS)
    1476                 :     {
    1477 LBC           0 :         error(_("wrong number of fields on Rule line"));
    1478 UIC           0 :         return;
    1479 EUB             :     }
    1480 GBC        8028 :     switch (*fields[RF_NAME])
    1481                 :     {
    1482 LBC           0 :         case '\0':
    1483                 :         case ' ':
    1484 EUB             :         case '\f':
    1485                 :         case '\n':
    1486                 :         case '\r':
    1487                 :         case '\t':
    1488                 :         case '\v':
    1489                 :         case '+':
    1490                 :         case '-':
    1491                 :         case '0':
    1492                 :         case '1':
    1493                 :         case '2':
    1494                 :         case '3':
    1495                 :         case '4':
    1496                 :         case '5':
    1497                 :         case '6':
    1498                 :         case '7':
    1499                 :         case '8':
    1500                 :         case '9':
    1501 UIC           0 :             error(_("Invalid rule name \"%s\""), fields[RF_NAME]);
    1502               0 :             return;
    1503 EUB             :     }
    1504 GBC        8028 :     r.r_filename = filename;
    1505 GIC        8028 :     r.r_linenum = linenum;
    1506 CBC        8028 :     r.r_save = getsave(fields[RF_SAVE], &r.r_isdst);
    1507            8028 :     rulesub(&r, fields[RF_LOYEAR], fields[RF_HIYEAR], fields[RF_COMMAND],
    1508            8028 :             fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]);
    1509            8028 :     r.r_name = ecpyalloc(fields[RF_NAME]);
    1510            8028 :     r.r_abbrvar = ecpyalloc(fields[RF_ABBRVAR]);
    1511            8028 :     if (max_abbrvar_len < strlen(r.r_abbrvar))
    1512 LBC           0 :         max_abbrvar_len = strlen(r.r_abbrvar);
    1513 CBC        8028 :     rules = growalloc(rules, sizeof *rules, nrules, &nrules_alloc);
    1514 GBC        8028 :     rules[nrules++] = r;
    1515 ECB             : }
    1516                 : 
    1517                 : static bool
    1518 GIC        1408 : inzone(char **fields, int nfields)
    1519                 : {
    1520 ECB             :     ptrdiff_t   i;
    1521                 : 
    1522 GIC        1408 :     if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS)
    1523                 :     {
    1524 LBC           0 :         error(_("wrong number of fields on Zone line"));
    1525 UIC           0 :         return false;
    1526 EUB             :     }
    1527 GBC        1408 :     if (lcltime != NULL && strcmp(fields[ZF_NAME], tzdefault) == 0)
    1528                 :     {
    1529 LBC           0 :         error(
    1530                 :               _("\"Zone %s\" line and -l option are mutually exclusive"),
    1531 EUB             :               tzdefault);
    1532 UIC           0 :         return false;
    1533                 :     }
    1534 GBC        1408 :     if (strcmp(fields[ZF_NAME], TZDEFRULES) == 0 && psxrules != NULL)
    1535                 :     {
    1536 LBC           0 :         error(
    1537                 :               _("\"Zone %s\" line and -p option are mutually exclusive"),
    1538 EUB             :               TZDEFRULES);
    1539 UIC           0 :         return false;
    1540                 :     }
    1541 GBC     1393864 :     for (i = 0; i < nzones; ++i)
    1542 GIC     1392456 :         if (zones[i].z_name != NULL &&
    1543 CBC      247104 :             strcmp(zones[i].z_name, fields[ZF_NAME]) == 0)
    1544 ECB             :         {
    1545 LBC           0 :             error(_("duplicate zone name %s"
    1546                 :                     " (file \"%s\", line %d)"),
    1547 UBC           0 :                   fields[ZF_NAME],
    1548 UIC           0 :                   zones[i].z_filename,
    1549 UBC           0 :                   zones[i].z_linenum);
    1550               0 :             return false;
    1551 EUB             :         }
    1552 GBC        1408 :     return inzsub(fields, nfields, false);
    1553                 : }
    1554 ECB             : 
    1555                 : static bool
    1556 GIC        6404 : inzcont(char **fields, int nfields)
    1557                 : {
    1558 CBC        6404 :     if (nfields < ZONEC_MINFIELDS || nfields > ZONEC_MAXFIELDS)
    1559                 :     {
    1560 LBC           0 :         error(_("wrong number of fields on Zone continuation line"));
    1561 UIC           0 :         return false;
    1562 EUB             :     }
    1563 GBC        6404 :     return inzsub(fields, nfields, true);
    1564                 : }
    1565 ECB             : 
    1566                 : static bool
    1567 GIC        7812 : inzsub(char **fields, int nfields, bool iscont)
    1568                 : {
    1569 ECB             :     char       *cp;
    1570                 :     char       *cp1;
    1571                 :     static struct zone z;
    1572                 :     int         i_stdoff,
    1573                 :                 i_rule,
    1574                 :                 i_format;
    1575                 :     int         i_untilyear,
    1576                 :                 i_untilmonth;
    1577                 :     int         i_untilday,
    1578                 :                 i_untiltime;
    1579                 :     bool        hasuntil;
    1580                 : 
    1581 GIC        7812 :     if (iscont)
    1582                 :     {
    1583 CBC        6404 :         i_stdoff = ZFC_STDOFF;
    1584 GIC        6404 :         i_rule = ZFC_RULE;
    1585 CBC        6404 :         i_format = ZFC_FORMAT;
    1586            6404 :         i_untilyear = ZFC_TILYEAR;
    1587            6404 :         i_untilmonth = ZFC_TILMONTH;
    1588            6404 :         i_untilday = ZFC_TILDAY;
    1589            6404 :         i_untiltime = ZFC_TILTIME;
    1590            6404 :         z.z_name = NULL;
    1591 ECB             :     }
    1592 CBC        1408 :     else if (!namecheck(fields[ZF_NAME]))
    1593 UIC           0 :         return false;
    1594 ECB             :     else
    1595 EUB             :     {
    1596 GIC        1408 :         i_stdoff = ZF_STDOFF;
    1597            1408 :         i_rule = ZF_RULE;
    1598 CBC        1408 :         i_format = ZF_FORMAT;
    1599            1408 :         i_untilyear = ZF_TILYEAR;
    1600            1408 :         i_untilmonth = ZF_TILMONTH;
    1601            1408 :         i_untilday = ZF_TILDAY;
    1602            1408 :         i_untiltime = ZF_TILTIME;
    1603            1408 :         z.z_name = ecpyalloc(fields[ZF_NAME]);
    1604 ECB             :     }
    1605 CBC        7812 :     z.z_filename = filename;
    1606 GIC        7812 :     z.z_linenum = linenum;
    1607 CBC        7812 :     z.z_stdoff = gethms(fields[i_stdoff], _("invalid UT offset"));
    1608            7812 :     if ((cp = strchr(fields[i_format], '%')) != NULL)
    1609 ECB             :     {
    1610 CBC        1812 :         if ((*++cp != 's' && *cp != 'z') || strchr(cp, '%')
    1611 GIC        1812 :             || strchr(fields[i_format], '/'))
    1612 ECB             :         {
    1613 LBC           0 :             error(_("invalid abbreviation format"));
    1614 UIC           0 :             return false;
    1615 EUB             :         }
    1616                 :     }
    1617 GIC        7812 :     z.z_rule = ecpyalloc(fields[i_rule]);
    1618            7812 :     z.z_format = cp1 = ecpyalloc(fields[i_format]);
    1619 CBC        7812 :     z.z_format_specifier = cp ? *cp : '\0';
    1620            7812 :     if (z.z_format_specifier == 'z')
    1621 ECB             :     {
    1622 LBC           0 :         if (noise)
    1623 UIC           0 :             warning(_("format '%s' not handled by pre-2015 versions of zic"),
    1624 EUB             :                     z.z_format);
    1625 UBC           0 :         cp1[cp - fields[i_format]] = 's';
    1626                 :     }
    1627 GBC        7812 :     if (max_format_len < strlen(z.z_format))
    1628 GIC          16 :         max_format_len = strlen(z.z_format);
    1629 CBC        7812 :     hasuntil = nfields > i_untilyear;
    1630            7812 :     if (hasuntil)
    1631 ECB             :     {
    1632 CBC        6404 :         z.z_untilrule.r_filename = filename;
    1633 GIC        6404 :         z.z_untilrule.r_linenum = linenum;
    1634 CBC       12392 :         rulesub(&z.z_untilrule,
    1635            6404 :                 fields[i_untilyear],
    1636 ECB             :                 "only",
    1637                 :                 "",
    1638                 :                 (nfields > i_untilmonth) ?
    1639 GIC        4880 :                 fields[i_untilmonth] : "Jan",
    1640            3940 :                 (nfields > i_untilday) ? fields[i_untilday] : "1",
    1641 CBC        2048 :                 (nfields > i_untiltime) ? fields[i_untiltime] : "0");
    1642            6404 :         z.z_untiltime = rpytime(&z.z_untilrule,
    1643 ECB             :                                 z.z_untilrule.r_loyear);
    1644 CBC        6404 :         if (iscont && nzones > 0 &&
    1645 GIC        5156 :             z.z_untiltime > min_time &&
    1646 CBC        5156 :             z.z_untiltime < max_time &&
    1647            5156 :             zones[nzones - 1].z_untiltime > min_time &&
    1648            5156 :             zones[nzones - 1].z_untiltime < max_time &&
    1649            5156 :             zones[nzones - 1].z_untiltime >= z.z_untiltime)
    1650 ECB             :         {
    1651 LBC           0 :             error(_("Zone continuation line end time is not after end time of previous line"));
    1652 UIC           0 :             return false;
    1653 EUB             :         }
    1654                 :     }
    1655 GIC        7812 :     zones = growalloc(zones, sizeof *zones, nzones, &nzones_alloc);
    1656            7812 :     zones[nzones++] = z;
    1657 ECB             : 
    1658                 :     /*
    1659                 :      * If there was an UNTIL field on this line, there's more information
    1660                 :      * about the zone on the next line.
    1661                 :      */
    1662 GIC        7812 :     return hasuntil;
    1663                 : }
    1664 ECB             : 
    1665                 : static zic_t
    1666 UIC           0 : getleapdatetime(char **fields, int nfields, bool expire_line)
    1667                 : {
    1668 EUB             :     const char *cp;
    1669                 :     const struct lookup *lp;
    1670                 :     zic_t       i,
    1671                 :                 j;
    1672                 : 
    1673                 :     /* PG: make year be int not zic_t to avoid sscanf portability issues */
    1674                 :     int         year;
    1675                 :     int         month,
    1676                 :                 day;
    1677                 :     zic_t       dayoff,
    1678                 :                 tod;
    1679                 :     zic_t       t;
    1680                 :     char        xs;
    1681                 : 
    1682 UIC           0 :     dayoff = 0;
    1683               0 :     cp = fields[LP_YEAR];
    1684 UBC           0 :     if (sscanf(cp, "%d%c", &year, &xs) != 1)
    1685 EUB             :     {
    1686                 :         /*
    1687                 :          * Leapin' Lizards!
    1688                 :          */
    1689 UIC           0 :         error(_("invalid leaping year"));
    1690               0 :         return -1;
    1691 EUB             :     }
    1692 UBC           0 :     if (!expire_line)
    1693                 :     {
    1694               0 :         if (!leapseen || leapmaxyear < year)
    1695 UIC           0 :             leapmaxyear = year;
    1696 UBC           0 :         if (!leapseen || leapminyear > year)
    1697               0 :             leapminyear = year;
    1698               0 :         leapseen = true;
    1699 EUB             :     }
    1700 UBC           0 :     j = EPOCH_YEAR;
    1701 UIC           0 :     while (j != year)
    1702 EUB             :     {
    1703 UBC           0 :         if (year > j)
    1704                 :         {
    1705               0 :             i = len_years[isleap(j)];
    1706 UIC           0 :             ++j;
    1707 EUB             :         }
    1708                 :         else
    1709                 :         {
    1710 UIC           0 :             --j;
    1711               0 :             i = -len_years[isleap(j)];
    1712 EUB             :         }
    1713 UBC           0 :         dayoff = oadd(dayoff, i);
    1714                 :     }
    1715               0 :     if ((lp = byword(fields[LP_MONTH], mon_names)) == NULL)
    1716                 :     {
    1717               0 :         error(_("invalid month name"));
    1718 UIC           0 :         return -1;
    1719 EUB             :     }
    1720 UBC           0 :     month = lp->l_value;
    1721 UIC           0 :     j = TM_JANUARY;
    1722 UBC           0 :     while (j != month)
    1723 EUB             :     {
    1724 UBC           0 :         i = len_months[isleap(year)][j];
    1725 UIC           0 :         dayoff = oadd(dayoff, i);
    1726 UBC           0 :         ++j;
    1727 EUB             :     }
    1728 UBC           0 :     cp = fields[LP_DAY];
    1729 UIC           0 :     if (sscanf(cp, "%d%c", &day, &xs) != 1 ||
    1730 UBC           0 :         day <= 0 || day > len_months[isleap(year)][month])
    1731 EUB             :     {
    1732 UBC           0 :         error(_("invalid day of month"));
    1733 UIC           0 :         return -1;
    1734 EUB             :     }
    1735 UBC           0 :     dayoff = oadd(dayoff, day - 1);
    1736 UIC           0 :     if (dayoff < min_time / SECSPERDAY)
    1737 EUB             :     {
    1738 UBC           0 :         error(_("time too small"));
    1739 UIC           0 :         return -1;
    1740 EUB             :     }
    1741 UBC           0 :     if (dayoff > max_time / SECSPERDAY)
    1742                 :     {
    1743               0 :         error(_("time too large"));
    1744 UIC           0 :         return -1;
    1745 EUB             :     }
    1746 UBC           0 :     t = dayoff * SECSPERDAY;
    1747 UIC           0 :     tod = gethms(fields[LP_TIME], _("invalid time of day"));
    1748 UBC           0 :     t = tadd(t, tod);
    1749               0 :     if (t < 0)
    1750               0 :         error(_("leap second precedes Epoch"));
    1751               0 :     return t;
    1752 EUB             : }
    1753                 : 
    1754                 : static void
    1755 UIC           0 : inleap(char **fields, int nfields)
    1756                 : {
    1757 UBC           0 :     if (nfields != LEAP_FIELDS)
    1758 UIC           0 :         error(_("wrong number of fields on Leap line"));
    1759 EUB             :     else
    1760                 :     {
    1761 UIC           0 :         zic_t       t = getleapdatetime(fields, nfields, false);
    1762                 : 
    1763 UBC           0 :         if (0 <= t)
    1764                 :         {
    1765               0 :             struct lookup const *lp = byword(fields[LP_ROLL], leap_types);
    1766                 : 
    1767               0 :             if (!lp)
    1768 UIC           0 :                 error(_("invalid Rolling/Stationary field on Leap line"));
    1769 EUB             :             else
    1770                 :             {
    1771 UIC           0 :                 int         correction = 0;
    1772                 : 
    1773 UBC           0 :                 if (!fields[LP_CORR][0])    /* infile() turns "-" into "".  */
    1774 UIC           0 :                     correction = -1;
    1775 UBC           0 :                 else if (strcmp(fields[LP_CORR], "+") == 0)
    1776               0 :                     correction = 1;
    1777 EUB             :                 else
    1778 UBC           0 :                     error(_("invalid CORRECTION field on Leap line"));
    1779 UIC           0 :                 if (correction)
    1780 UBC           0 :                     leapadd(t, correction, lp->l_value);
    1781 EUB             :             }
    1782                 :         }
    1783                 :     }
    1784 UIC           0 : }
    1785                 : 
    1786 EUB             : static void
    1787 UIC           0 : inexpires(char **fields, int nfields)
    1788                 : {
    1789 UBC           0 :     if (nfields != EXPIRES_FIELDS)
    1790 UIC           0 :         error(_("wrong number of fields on Expires line"));
    1791 UBC           0 :     else if (0 <= leapexpires)
    1792               0 :         error(_("multiple Expires lines"));
    1793 EUB             :     else
    1794 UBC           0 :         leapexpires = getleapdatetime(fields, nfields, true);
    1795 UIC           0 : }
    1796 EUB             : 
    1797                 : static void
    1798 GIC         980 : inlink(char **fields, int nfields)
    1799                 : {
    1800 ECB             :     struct link l;
    1801                 : 
    1802 GIC         980 :     if (nfields != LINK_FIELDS)
    1803                 :     {
    1804 LBC           0 :         error(_("wrong number of fields on Link line"));
    1805 UIC           0 :         return;
    1806 EUB             :     }
    1807 GBC         980 :     if (*fields[LF_TARGET] == '\0')
    1808                 :     {
    1809 LBC           0 :         error(_("blank TARGET field on Link line"));
    1810 UIC           0 :         return;
    1811 EUB             :     }
    1812 GBC         980 :     if (!namecheck(fields[LF_LINKNAME]))
    1813 UIC           0 :         return;
    1814 CBC         980 :     l.l_filename = filename;
    1815 GBC         980 :     l.l_linenum = linenum;
    1816 CBC         980 :     l.l_target = ecpyalloc(fields[LF_TARGET]);
    1817             980 :     l.l_linkname = ecpyalloc(fields[LF_LINKNAME]);
    1818             980 :     links = growalloc(links, sizeof *links, nlinks, &nlinks_alloc);
    1819             980 :     links[nlinks++] = l;
    1820 ECB             : }
    1821                 : 
    1822                 : static void
    1823 GIC       14432 : rulesub(struct rule *rp, const char *loyearp, const char *hiyearp,
    1824                 :         const char *typep, const char *monthp, const char *dayp,
    1825 ECB             :         const char *timep)
    1826                 : {
    1827                 :     const struct lookup *lp;
    1828                 :     const char *cp;
    1829                 :     char       *dp;
    1830                 :     char       *ep;
    1831                 :     char        xs;
    1832                 : 
    1833                 :     /* PG: year_tmp is to avoid sscanf portability issues */
    1834                 :     int         year_tmp;
    1835                 : 
    1836 GIC       14432 :     if ((lp = byword(monthp, mon_names)) == NULL)
    1837                 :     {
    1838 LBC           0 :         error(_("invalid month name"));
    1839 UIC           0 :         return;
    1840 EUB             :     }
    1841 GBC       14432 :     rp->r_month = lp->l_value;
    1842 GIC       14432 :     rp->r_todisstd = false;
    1843 CBC       14432 :     rp->r_todisut = false;
    1844           14432 :     dp = ecpyalloc(timep);
    1845           14432 :     if (*dp != '\0')
    1846 ECB             :     {
    1847 CBC       14432 :         ep = dp + strlen(dp) - 1;
    1848 GIC       14432 :         switch (lowerit(*ep))
    1849 ECB             :         {
    1850 CBC        2828 :             case 's':           /* Standard */
    1851 GIC        2828 :                 rp->r_todisstd = true;
    1852 CBC        2828 :                 rp->r_todisut = false;
    1853            2828 :                 *ep = '\0';
    1854            2828 :                 break;
    1855 LBC           0 :             case 'w':           /* Wall */
    1856               0 :                 rp->r_todisstd = false;
    1857 UBC           0 :                 rp->r_todisut = false;
    1858               0 :                 *ep = '\0';
    1859               0 :                 break;
    1860 GBC         656 :             case 'g':           /* Greenwich */
    1861 EUB             :             case 'u':           /* Universal */
    1862 ECB             :             case 'z':           /* Zulu */
    1863 GIC         656 :                 rp->r_todisstd = true;
    1864             656 :                 rp->r_todisut = true;
    1865 CBC         656 :                 *ep = '\0';
    1866             656 :                 break;
    1867 ECB             :         }
    1868                 :     }
    1869 GIC       14432 :     rp->r_tod = gethms(dp, _("invalid time of day"));
    1870           14432 :     free(dp);
    1871 ECB             : 
    1872                 :     /*
    1873                 :      * Year work.
    1874                 :      */
    1875 GIC       14432 :     cp = loyearp;
    1876           14432 :     lp = byword(cp, begin_years);
    1877 CBC       14432 :     rp->r_lowasnum = lp == NULL;
    1878           14432 :     if (!rp->r_lowasnum)
    1879 LBC           0 :         switch (lp->l_value)
    1880 ECB             :         {
    1881 UBC           0 :             case YR_MINIMUM:
    1882 UIC           0 :                 rp->r_loyear = ZIC_MIN;
    1883 UBC           0 :                 break;
    1884               0 :             case YR_MAXIMUM:
    1885               0 :                 rp->r_loyear = ZIC_MAX;
    1886               0 :                 break;
    1887               0 :             default:            /* "cannot happen" */
    1888               0 :                 fprintf(stderr,
    1889 EUB             :                         _("%s: panic: Invalid l_value %d\n"),
    1890 UBC           0 :                         progname, lp->l_value);
    1891 UIC           0 :                 exit(EXIT_FAILURE);
    1892 EUB             :         }
    1893 GBC       14432 :     else if (sscanf(cp, "%d%c", &year_tmp, &xs) == 1)
    1894 GIC       14432 :         rp->r_loyear = year_tmp;
    1895 ECB             :     else
    1896                 :     {
    1897 UIC           0 :         error(_("invalid starting year"));
    1898               0 :         return;
    1899 EUB             :     }
    1900 GBC       14432 :     cp = hiyearp;
    1901 GIC       14432 :     lp = byword(cp, end_years);
    1902 CBC       14432 :     rp->r_hiwasnum = lp == NULL;
    1903           14432 :     if (!rp->r_hiwasnum)
    1904           12000 :         switch (lp->l_value)
    1905 ECB             :         {
    1906 LBC           0 :             case YR_MINIMUM:
    1907 UIC           0 :                 rp->r_hiyear = ZIC_MIN;
    1908 UBC           0 :                 break;
    1909 GBC         192 :             case YR_MAXIMUM:
    1910             192 :                 rp->r_hiyear = ZIC_MAX;
    1911 CBC         192 :                 break;
    1912           11808 :             case YR_ONLY:
    1913           11808 :                 rp->r_hiyear = rp->r_loyear;
    1914           11808 :                 break;
    1915 LBC           0 :             default:            /* "cannot happen" */
    1916               0 :                 fprintf(stderr,
    1917 EUB             :                         _("%s: panic: Invalid l_value %d\n"),
    1918 UBC           0 :                         progname, lp->l_value);
    1919 UIC           0 :                 exit(EXIT_FAILURE);
    1920 EUB             :         }
    1921 GBC        2432 :     else if (sscanf(cp, "%d%c", &year_tmp, &xs) == 1)
    1922 GIC        2432 :         rp->r_hiyear = year_tmp;
    1923 ECB             :     else
    1924                 :     {
    1925 UIC           0 :         error(_("invalid ending year"));
    1926               0 :         return;
    1927 EUB             :     }
    1928 GBC       14432 :     if (rp->r_loyear > rp->r_hiyear)
    1929                 :     {
    1930 LBC           0 :         error(_("starting year greater than ending year"));
    1931 UIC           0 :         return;
    1932 EUB             :     }
    1933 GBC       14432 :     if (*typep != '\0')
    1934                 :     {
    1935 LBC           0 :         error(_("year type \"%s\" is unsupported; use \"-\" instead"),
    1936                 :               typep);
    1937 UBC           0 :         return;
    1938                 :     }
    1939 EUB             : 
    1940                 :     /*
    1941                 :      * Day work. Accept things such as: 1 lastSunday last-Sunday
    1942                 :      * (undocumented; warn about this) Sun<=20 Sun>=7
    1943                 :      */
    1944 GIC       14432 :     dp = ecpyalloc(dayp);
    1945           14432 :     if ((lp = byword(dp, lasts)) != NULL)
    1946 ECB             :     {
    1947 CBC        1368 :         rp->r_dycode = DC_DOWLEQ;
    1948 GIC        1368 :         rp->r_wday = lp->l_value;
    1949 CBC        1368 :         rp->r_dayofmonth = len_months[1][rp->r_month];
    1950 ECB             :     }
    1951                 :     else
    1952                 :     {
    1953 GIC       13064 :         if ((ep = strchr(dp, '<')) != NULL)
    1954              28 :             rp->r_dycode = DC_DOWLEQ;
    1955 CBC       13036 :         else if ((ep = strchr(dp, '>')) != NULL)
    1956            1584 :             rp->r_dycode = DC_DOWGEQ;
    1957 ECB             :         else
    1958                 :         {
    1959 GIC       11452 :             ep = dp;
    1960           11452 :             rp->r_dycode = DC_DOM;
    1961 ECB             :         }
    1962 CBC       13064 :         if (rp->r_dycode != DC_DOM)
    1963                 :         {
    1964            1612 :             *ep++ = 0;
    1965 GIC        1612 :             if (*ep++ != '=')
    1966 ECB             :             {
    1967 LBC           0 :                 error(_("invalid day of month"));
    1968 UIC           0 :                 free(dp);
    1969 UBC           0 :                 return;
    1970 EUB             :             }
    1971 GBC        1612 :             if ((lp = byword(dp, wday_names)) == NULL)
    1972                 :             {
    1973 LBC           0 :                 error(_("invalid weekday name"));
    1974 UIC           0 :                 free(dp);
    1975 UBC           0 :                 return;
    1976 EUB             :             }
    1977 GBC        1612 :             rp->r_wday = lp->l_value;
    1978                 :         }
    1979 CBC       13064 :         if (sscanf(ep, "%d%c", &rp->r_dayofmonth, &xs) != 1 ||
    1980 GIC       13064 :             rp->r_dayofmonth <= 0 ||
    1981 CBC       13064 :             (rp->r_dayofmonth > len_months[1][rp->r_month]))
    1982 ECB             :         {
    1983 LBC           0 :             error(_("invalid day of month"));
    1984 UIC           0 :             free(dp);
    1985 UBC           0 :             return;
    1986 EUB             :         }
    1987                 :     }
    1988 GIC       14432 :     free(dp);
    1989                 : }
    1990 ECB             : 
    1991                 : static void
    1992 GIC       24756 : convert(const int32 val, char *const buf)
    1993                 : {
    1994 ECB             :     int         i;
    1995                 :     int         shift;
    1996 GIC       24756 :     unsigned char *const b = (unsigned char *) buf;
    1997                 : 
    1998 CBC      123780 :     for (i = 0, shift = 24; i < 4; ++i, shift -= 8)
    1999 GIC       99024 :         b[i] = val >> shift;
    2000 CBC       24756 : }
    2001 ECB             : 
    2002                 : static void
    2003 GIC       67152 : convert64(const zic_t val, char *const buf)
    2004                 : {
    2005 ECB             :     int         i;
    2006                 :     int         shift;
    2007 GIC       67152 :     unsigned char *const b = (unsigned char *) buf;
    2008                 : 
    2009 CBC      604368 :     for (i = 0, shift = 56; i < 8; ++i, shift -= 8)
    2010 GIC      537216 :         b[i] = val >> shift;
    2011 CBC       67152 : }
    2012 ECB             : 
    2013                 : static void
    2014 GIC        7860 : puttzcode(const int32 val, FILE *const fp)
    2015                 : {
    2016 ECB             :     char        buf[4];
    2017                 : 
    2018 GIC        7860 :     convert(val, buf);
    2019            7860 :     fwrite(buf, sizeof buf, 1, fp);
    2020 CBC        7860 : }
    2021 ECB             : 
    2022                 : static void
    2023 GIC       67152 : puttzcodepass(zic_t val, FILE *fp, int pass)
    2024                 : {
    2025 CBC       67152 :     if (pass == 1)
    2026 UIC           0 :         puttzcode(val, fp);
    2027 ECB             :     else
    2028 EUB             :     {
    2029                 :         char        buf[8];
    2030                 : 
    2031 GIC       67152 :         convert64(val, buf);
    2032           67152 :         fwrite(buf, sizeof buf, 1, fp);
    2033 ECB             :     }
    2034 CBC       67152 : }
    2035                 : 
    2036 ECB             : static int
    2037 GIC      777928 : atcomp(const void *avp, const void *bvp)
    2038                 : {
    2039 CBC      777928 :     const zic_t a = ((const struct attype *) avp)->at;
    2040 GIC      777928 :     const zic_t b = ((const struct attype *) bvp)->at;
    2041 ECB             : 
    2042 CBC      777928 :     return (a < b) ? -1 : (a > b);
    2043                 : }
    2044 ECB             : 
    2045                 : struct timerange
    2046                 : {
    2047                 :     int         defaulttype;
    2048                 :     ptrdiff_t   base,
    2049                 :                 count;
    2050                 :     int         leapbase,
    2051                 :                 leapcount;
    2052                 : };
    2053                 : 
    2054                 : static struct timerange
    2055 GIC        2816 : limitrange(struct timerange r, zic_t lo, zic_t hi,
    2056                 :            zic_t const *ats, unsigned char const *types)
    2057 ECB             : {
    2058 GIC        3552 :     while (0 < r.count && ats[r.base] < lo)
    2059                 :     {
    2060 CBC         736 :         r.defaulttype = types[r.base];
    2061 GIC         736 :         r.count--;
    2062 CBC         736 :         r.base++;
    2063 ECB             :     }
    2064 CBC        2816 :     while (0 < r.leapcount && trans[r.leapbase] < lo)
    2065                 :     {
    2066 LBC           0 :         r.leapcount--;
    2067 UIC           0 :         r.leapbase++;
    2068 EUB             :     }
    2069                 : 
    2070 GIC        2816 :     if (hi < ZIC_MAX)
    2071                 :     {
    2072 CBC        2224 :         while (0 < r.count && hi + 1 < ats[r.base + r.count - 1])
    2073 GIC         816 :             r.count--;
    2074 CBC        1408 :         while (0 < r.leapcount && hi + 1 < trans[r.leapbase + r.leapcount - 1])
    2075 LBC           0 :             r.leapcount--;
    2076 ECB             :     }
    2077 EUB             : 
    2078 GIC        2816 :     return r;
    2079                 : }
    2080 ECB             : 
    2081                 : static void
    2082 GIC        1408 : writezone(const char *const name, const char *const string, char version,
    2083                 :           int defaulttype)
    2084 ECB             : {
    2085                 :     FILE       *fp;
    2086                 :     ptrdiff_t   i,
    2087                 :                 j;
    2088                 :     int         pass;
    2089                 :     static const struct tzhead tzh0;
    2090                 :     static struct tzhead tzh;
    2091 GIC        1408 :     bool        dir_checked = false;
    2092            1408 :     zic_t       one = 1;
    2093 CBC        1408 :     zic_t       y2038_boundary = one << 31;
    2094            1408 :     ptrdiff_t   nats = timecnt + WORK_AROUND_QTBUG_53071;
    2095 ECB             : 
    2096                 :     /*
    2097                 :      * Allocate the ATS and TYPES arrays via a single malloc, as this is a bit
    2098                 :      * faster.
    2099                 :      */
    2100 GIC        1408 :     zic_t      *ats = emalloc(MAXALIGN(size_product(nats, sizeof *ats + 1)));
    2101            1408 :     void       *typesptr = ats + nats;
    2102 CBC        1408 :     unsigned char *types = typesptr;
    2103 ECB             :     struct timerange rangeall,
    2104                 :                 range32,
    2105                 :                 range64;
    2106                 : 
    2107                 :     /*
    2108                 :      * Sort.
    2109                 :      */
    2110 GIC        1408 :     if (timecnt > 1)
    2111            1232 :         qsort(attypes, timecnt, sizeof *attypes, atcomp);
    2112 ECB             : 
    2113                 :     /*
    2114                 :      * Optimize.
    2115                 :      */
    2116                 :     {
    2117                 :         ptrdiff_t   fromi,
    2118                 :                     toi;
    2119                 : 
    2120 GIC        1408 :         toi = 0;
    2121            1408 :         fromi = 0;
    2122 CBC       70104 :         for (; fromi < timecnt; ++fromi)
    2123 ECB             :         {
    2124 CBC       68696 :             if (toi != 0
    2125 GIC      135192 :                 && ((attypes[fromi].at
    2126 CBC       67416 :                      + utoffs[attypes[toi - 1].type])
    2127           67416 :                     <= (attypes[toi - 1].at
    2128           67416 :                         + utoffs[toi == 1 ? 0
    2129           67416 :                                  : attypes[toi - 2].type])))
    2130 ECB             :             {
    2131 CBC         360 :                 attypes[toi - 1].type =
    2132 GIC         360 :                     attypes[fromi].type;
    2133 CBC         360 :                 continue;
    2134 ECB             :             }
    2135 CBC       68336 :             if (toi == 0
    2136 GIC       67056 :                 || attypes[fromi].dontmerge
    2137 CBC       66568 :                 || (utoffs[attypes[toi - 1].type]
    2138           66568 :                     != utoffs[attypes[fromi].type])
    2139            1840 :                 || (isdsts[attypes[toi - 1].type]
    2140            1840 :                     != isdsts[attypes[fromi].type])
    2141            1468 :                 || (desigidx[attypes[toi - 1].type]
    2142            1468 :                     != desigidx[attypes[fromi].type]))
    2143           67152 :                 attypes[toi++] = attypes[fromi];
    2144 ECB             :         }
    2145 CBC        1408 :         timecnt = toi;
    2146                 :     }
    2147 ECB             : 
    2148 GIC        1408 :     if (noise && timecnt > 1200)
    2149                 :     {
    2150 LBC           0 :         if (timecnt > TZ_MAX_TIMES)
    2151 UIC           0 :             warning(_("reference clients mishandle"
    2152 EUB             :                       " more than %d transition times"),
    2153                 :                     TZ_MAX_TIMES);
    2154                 :         else
    2155 UIC           0 :             warning(_("pre-2014 clients may mishandle"
    2156                 :                       " more than 1200 transition times"));
    2157 EUB             :     }
    2158                 : 
    2159                 :     /*
    2160                 :      * Transfer.
    2161                 :      */
    2162 GIC       68560 :     for (i = 0; i < timecnt; ++i)
    2163                 :     {
    2164 CBC       67152 :         ats[i] = attypes[i].at;
    2165 GIC       67152 :         types[i] = attypes[i].type;
    2166 ECB             :     }
    2167                 : 
    2168                 :     /*
    2169                 :      * Correct for leap seconds.
    2170                 :      */
    2171 GIC       68560 :     for (i = 0; i < timecnt; ++i)
    2172                 :     {
    2173 CBC       67152 :         j = leapcnt;
    2174 GIC       67152 :         while (--j >= 0)
    2175 LBC           0 :             if (ats[i] > trans[j] - corr[j])
    2176 ECB             :             {
    2177 UBC           0 :                 ats[i] = tadd(ats[i], corr[j]);
    2178 UIC           0 :                 break;
    2179 EUB             :             }
    2180                 :     }
    2181                 : 
    2182                 :     /*
    2183                 :      * Work around QTBUG-53071 for timestamps less than y2038_boundary - 1, by
    2184                 :      * inserting a no-op transition at time y2038_boundary - 1. This works
    2185                 :      * only for timestamps before the boundary, which should be good enough in
    2186                 :      * practice as QTBUG-53071 should be long-dead by 2038.  Do this after
    2187                 :      * correcting for leap seconds, as the idea is to insert a transition just
    2188                 :      * before 32-bit pg_time_t rolls around, and this occurs at a slightly
    2189                 :      * different moment if transitions are leap-second corrected.
    2190                 :      */
    2191 GIC        1408 :     if (WORK_AROUND_QTBUG_53071 && timecnt != 0 && want_bloat()
    2192 UIC           0 :         && ats[timecnt - 1] < y2038_boundary - 1 && strchr(string, '<'))
    2193 ECB             :     {
    2194 UBC           0 :         ats[timecnt] = y2038_boundary - 1;
    2195 UIC           0 :         types[timecnt] = types[timecnt - 1];
    2196 UBC           0 :         timecnt++;
    2197 EUB             :     }
    2198                 : 
    2199 GIC        1408 :     rangeall.defaulttype = defaulttype;
    2200            1408 :     rangeall.base = rangeall.leapbase = 0;
    2201 CBC        1408 :     rangeall.count = timecnt;
    2202            1408 :     rangeall.leapcount = leapcnt;
    2203            1408 :     range64 = limitrange(rangeall, lo_time, hi_time, ats, types);
    2204            1408 :     range32 = limitrange(range64, PG_INT32_MIN, PG_INT32_MAX, ats, types);
    2205 ECB             : 
    2206                 :     /*
    2207                 :      * Remove old file, if any, to snap links.
    2208                 :      */
    2209 GIC        1408 :     if (remove(name) == 0)
    2210             704 :         dir_checked = true;
    2211 CBC         704 :     else if (errno != ENOENT)
    2212 ECB             :     {
    2213 LBC           0 :         const char *e = strerror(errno);
    2214                 : 
    2215 UBC           0 :         fprintf(stderr, _("%s: Cannot remove %s/%s: %s\n"),
    2216                 :                 progname, directory, name, e);
    2217               0 :         exit(EXIT_FAILURE);
    2218                 :     }
    2219 GBC        1408 :     fp = fopen(name, "wb");
    2220 GIC        1408 :     if (!fp)
    2221 ECB             :     {
    2222 CBC          28 :         int         fopen_errno = errno;
    2223                 : 
    2224              28 :         if (fopen_errno == ENOENT && !dir_checked)
    2225                 :         {
    2226              28 :             mkdirs(name, true);
    2227 GIC          28 :             fp = fopen(name, "wb");
    2228 CBC          28 :             fopen_errno = errno;
    2229 ECB             :         }
    2230 CBC          28 :         if (!fp)
    2231                 :         {
    2232 LBC           0 :             fprintf(stderr, _("%s: Cannot create %s/%s: %s\n"),
    2233                 :                     progname, directory, name, strerror(fopen_errno));
    2234 UBC           0 :             exit(EXIT_FAILURE);
    2235                 :         }
    2236 EUB             :     }
    2237 GIC        4224 :     for (pass = 1; pass <= 2; ++pass)
    2238                 :     {
    2239 ECB             :         ptrdiff_t   thistimei,
    2240                 :                     thistimecnt,
    2241                 :                     thistimelim;
    2242                 :         int         thisleapi,
    2243                 :                     thisleapcnt,
    2244                 :                     thisleaplim;
    2245                 :         int         currenttype,
    2246                 :                     thisdefaulttype;
    2247                 :         bool        locut,
    2248                 :                     hicut;
    2249                 :         zic_t       lo;
    2250                 :         int         old0;
    2251                 :         char        omittype[TZ_MAX_TYPES];
    2252                 :         int         typemap[TZ_MAX_TYPES];
    2253                 :         int         thistypecnt,
    2254                 :                     stdcnt,
    2255                 :                     utcnt;
    2256                 :         char        thischars[TZ_MAX_CHARS];
    2257                 :         int         thischarcnt;
    2258                 :         bool        toomanytimes;
    2259                 :         int         indmap[TZ_MAX_CHARS];
    2260                 : 
    2261 GIC        2816 :         if (pass == 1)
    2262                 :         {
    2263 ECB             :             /*
    2264                 :              * Arguably the default time type in the 32-bit data should be
    2265                 :              * range32.defaulttype, which is suited for timestamps just before
    2266                 :              * PG_INT32_MIN.  However, zic traditionally used the time type of
    2267                 :              * the indefinite past instead.  Internet RFC 8532 says readers
    2268                 :              * should ignore 32-bit data, so this discrepancy matters only to
    2269                 :              * obsolete readers where the traditional type might be more
    2270                 :              * appropriate even if it's "wrong".  So, use the historical zic
    2271                 :              * value, unless -r specifies a low cutoff that excludes some
    2272                 :              * 32-bit timestamps.
    2273                 :              */
    2274 GIC        2816 :             thisdefaulttype = (lo_time <= PG_INT32_MIN
    2275                 :                                ? range64.defaulttype
    2276 CBC        1408 :                                : range32.defaulttype);
    2277                 : 
    2278            1408 :             thistimei = range32.base;
    2279 GIC        1408 :             thistimecnt = range32.count;
    2280 CBC        1408 :             toomanytimes = thistimecnt >> 31 >> 1 != 0;
    2281            1408 :             thisleapi = range32.leapbase;
    2282            1408 :             thisleapcnt = range32.leapcount;
    2283            1408 :             locut = PG_INT32_MIN < lo_time;
    2284            1408 :             hicut = hi_time < PG_INT32_MAX;
    2285 ECB             :         }
    2286                 :         else
    2287                 :         {
    2288 GIC        1408 :             thisdefaulttype = range64.defaulttype;
    2289            1408 :             thistimei = range64.base;
    2290 CBC        1408 :             thistimecnt = range64.count;
    2291            1408 :             toomanytimes = thistimecnt >> 31 >> 31 >> 2 != 0;
    2292            1408 :             thisleapi = range64.leapbase;
    2293            1408 :             thisleapcnt = range64.leapcount;
    2294            1408 :             locut = min_time < lo_time;
    2295            1408 :             hicut = hi_time < max_time;
    2296 ECB             :         }
    2297 CBC        2816 :         if (toomanytimes)
    2298 UIC           0 :             error(_("too many transition times"));
    2299 ECB             : 
    2300 EUB             :         /*
    2301                 :          * Keep the last too-low transition if no transition is exactly at LO.
    2302                 :          * The kept transition will be output as a LO "transition"; see
    2303                 :          * "Output a LO_TIME transition" below.  This is needed when the
    2304                 :          * output is truncated at the start, and is also useful when catering
    2305                 :          * to buggy 32-bit clients that do not use time type 0 for timestamps
    2306                 :          * before the first transition.
    2307                 :          */
    2308 GIC        2816 :         if (0 < thistimei && ats[thistimei] != lo_time)
    2309                 :         {
    2310 CBC         644 :             thistimei--;
    2311 GIC         644 :             thistimecnt++;
    2312 CBC         644 :             locut = false;
    2313 ECB             :         }
    2314                 : 
    2315 GIC        2816 :         thistimelim = thistimei + thistimecnt;
    2316            2816 :         thisleaplim = thisleapi + thisleapcnt;
    2317 CBC        2816 :         if (thistimecnt != 0)
    2318 ECB             :         {
    2319 CBC        2560 :             if (ats[thistimei] == lo_time)
    2320 UIC           0 :                 locut = false;
    2321 CBC        2560 :             if (hi_time < ZIC_MAX && ats[thistimelim - 1] == hi_time + 1)
    2322 UBC           0 :                 hicut = false;
    2323 ECB             :         }
    2324 GBC        2816 :         memset(omittype, true, typecnt);
    2325 GIC        2816 :         omittype[thisdefaulttype] = false;
    2326 CBC      136212 :         for (i = thistimei; i < thistimelim; i++)
    2327          133396 :             omittype[types[i]] = false;
    2328 ECB             : 
    2329                 :         /*
    2330                 :          * Reorder types to make THISDEFAULTTYPE type 0. Use TYPEMAP to swap
    2331                 :          * OLD0 and THISDEFAULTTYPE so that THISDEFAULTTYPE appears as type 0
    2332                 :          * in the output instead of OLD0.  TYPEMAP also omits unused types.
    2333                 :          */
    2334 GIC        2816 :         old0 = strlen(omittype);
    2335                 : 
    2336 ECB             : #ifndef LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH
    2337                 : 
    2338                 :         /*
    2339                 :          * For some pre-2011 systems: if the last-to-be-written standard (or
    2340                 :          * daylight) type has an offset different from the most recently used
    2341                 :          * offset, append an (unused) copy of the most recently used type (to
    2342                 :          * help get global "altzone" and "timezone" variables set correctly).
    2343                 :          */
    2344 GIC        2816 :         if (want_bloat())
    2345                 :         {
    2346 ECB             :             int         mrudst,
    2347                 :                         mrustd,
    2348                 :                         hidst,
    2349                 :                         histd,
    2350                 :                         type;
    2351                 : 
    2352 UIC           0 :             hidst = histd = mrudst = mrustd = -1;
    2353               0 :             for (i = thistimei; i < thistimelim; ++i)
    2354 UBC           0 :                 if (isdsts[types[i]])
    2355               0 :                     mrudst = types[i];
    2356 EUB             :                 else
    2357 UBC           0 :                     mrustd = types[i];
    2358 UIC           0 :             for (i = old0; i < typecnt; i++)
    2359 EUB             :             {
    2360 UBC           0 :                 int         h = (i == old0 ? thisdefaulttype
    2361 UIC           0 :                                  : i == thisdefaulttype ? old0 : i);
    2362 EUB             : 
    2363 UBC           0 :                 if (!omittype[h])
    2364                 :                 {
    2365               0 :                     if (isdsts[h])
    2366 UIC           0 :                         hidst = i;
    2367 EUB             :                     else
    2368 UBC           0 :                         histd = i;
    2369                 :                 }
    2370 EUB             :             }
    2371 UIC           0 :             if (hidst >= 0 && mrudst >= 0 && hidst != mrudst &&
    2372               0 :                 utoffs[hidst] != utoffs[mrudst])
    2373 EUB             :             {
    2374 UBC           0 :                 isdsts[mrudst] = -1;
    2375 UIC           0 :                 type = addtype(utoffs[mrudst],
    2376 UBC           0 :                                &chars[desigidx[mrudst]],
    2377 EUB             :                                true,
    2378 UBC           0 :                                ttisstds[mrudst],
    2379 UIC           0 :                                ttisuts[mrudst]);
    2380 UBC           0 :                 isdsts[mrudst] = 1;
    2381               0 :                 omittype[type] = false;
    2382 EUB             :             }
    2383 UBC           0 :             if (histd >= 0 && mrustd >= 0 && histd != mrustd &&
    2384 UIC           0 :                 utoffs[histd] != utoffs[mrustd])
    2385 EUB             :             {
    2386 UBC           0 :                 isdsts[mrustd] = -1;
    2387 UIC           0 :                 type = addtype(utoffs[mrustd],
    2388 UBC           0 :                                &chars[desigidx[mrustd]],
    2389 EUB             :                                false,
    2390 UBC           0 :                                ttisstds[mrustd],
    2391 UIC           0 :                                ttisuts[mrustd]);
    2392 UBC           0 :                 isdsts[mrustd] = 0;
    2393               0 :                 omittype[type] = false;
    2394 EUB             :             }
    2395                 :         }
    2396                 : #endif                          /* !defined
    2397                 :                                  * LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH */
    2398 GIC        2816 :         thistypecnt = 0;
    2399           15736 :         for (i = old0; i < typecnt; i++)
    2400 CBC       12920 :             if (!omittype[i])
    2401           12812 :                 typemap[i == old0 ? thisdefaulttype
    2402           12812 :                         : i == thisdefaulttype ? old0 : i]
    2403           25624 :                     = thistypecnt++;
    2404 ECB             : 
    2405 CBC      143616 :         for (i = 0; i < sizeof indmap / sizeof indmap[0]; ++i)
    2406 GIC      140800 :             indmap[i] = -1;
    2407 CBC        2816 :         thischarcnt = stdcnt = utcnt = 0;
    2408           15736 :         for (i = old0; i < typecnt; i++)
    2409 ECB             :         {
    2410                 :             char       *thisabbr;
    2411                 : 
    2412 GIC       12920 :             if (omittype[i])
    2413             108 :                 continue;
    2414 CBC       12812 :             if (ttisstds[i])
    2415 LBC           0 :                 stdcnt = thistypecnt;
    2416 CBC       12812 :             if (ttisuts[i])
    2417 UBC           0 :                 utcnt = thistypecnt;
    2418 CBC       12812 :             if (indmap[desigidx[i]] >= 0)
    2419 GBC        1040 :                 continue;
    2420 CBC       11772 :             thisabbr = &chars[desigidx[i]];
    2421          108732 :             for (j = 0; j < thischarcnt; ++j)
    2422           96968 :                 if (strcmp(&thischars[j], thisabbr) == 0)
    2423               8 :                     break;
    2424           11772 :             if (j == thischarcnt)
    2425 ECB             :             {
    2426 CBC       11764 :                 strcpy(&thischars[thischarcnt], thisabbr);
    2427 GIC       11764 :                 thischarcnt += strlen(thisabbr) + 1;
    2428 ECB             :             }
    2429 CBC       11772 :             indmap[desigidx[i]] = j;
    2430                 :         }
    2431            2816 :         if (pass == 1 && !want_bloat())
    2432                 :         {
    2433            1408 :             utcnt = stdcnt = thisleapcnt = 0;
    2434 GIC        1408 :             thistimecnt = -(locut + hicut);
    2435 CBC        1408 :             thistypecnt = thischarcnt = 1;
    2436            1408 :             thistimelim = thistimei;
    2437 ECB             :         }
    2438                 : #define DO(field)   fwrite(tzh.field, sizeof tzh.field, 1, fp)
    2439 GIC        2816 :         tzh = tzh0;
    2440            2816 :         memcpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic);
    2441 CBC        2816 :         tzh.tzh_version[0] = version;
    2442            2816 :         convert(utcnt, tzh.tzh_ttisutcnt);
    2443            2816 :         convert(stdcnt, tzh.tzh_ttisstdcnt);
    2444            2816 :         convert(thisleapcnt, tzh.tzh_leapcnt);
    2445            2816 :         convert(locut + thistimecnt + hicut, tzh.tzh_timecnt);
    2446            2816 :         convert(thistypecnt, tzh.tzh_typecnt);
    2447            2816 :         convert(thischarcnt, tzh.tzh_charcnt);
    2448            2816 :         DO(tzh_magic);
    2449            2816 :         DO(tzh_version);
    2450            2816 :         DO(tzh_reserved);
    2451            2816 :         DO(tzh_ttisutcnt);
    2452            2816 :         DO(tzh_ttisstdcnt);
    2453            2816 :         DO(tzh_leapcnt);
    2454            2816 :         DO(tzh_timecnt);
    2455            2816 :         DO(tzh_typecnt);
    2456            2816 :         DO(tzh_charcnt);
    2457 ECB             : #undef DO
    2458 CBC        2816 :         if (pass == 1 && !want_bloat())
    2459                 :         {
    2460 ECB             :             /* Output a minimal data block with just one time type.  */
    2461 GIC        1408 :             puttzcode(0, fp);   /* utoff */
    2462            1408 :             putc(0, fp);        /* dst */
    2463 CBC        1408 :             putc(0, fp);        /* index of abbreviation */
    2464            1408 :             putc(0, fp);        /* empty-string abbreviation */
    2465            1408 :             continue;
    2466 ECB             :         }
    2467                 : 
    2468                 :         /* PG: print current timezone abbreviations if requested */
    2469 GIC        1408 :         if (print_abbrevs && pass == 2)
    2470                 :         {
    2471 ECB             :             /* Print "type" data for periods ending after print_cutoff */
    2472 UIC           0 :             for (i = thistimei; i < thistimelim; ++i)
    2473                 :             {
    2474 UBC           0 :                 if (i == thistimelim - 1 || ats[i + 1] > print_cutoff)
    2475                 :                 {
    2476               0 :                     unsigned char tm = types[i];
    2477 UIC           0 :                     char       *thisabbrev = &thischars[indmap[desigidx[tm]]];
    2478 EUB             : 
    2479 UBC           0 :                     fprintf(stdout, "%s\t" INT64_FORMAT "%s\n",
    2480                 :                             thisabbrev,
    2481 EUB             :                             utoffs[tm],
    2482 UIC           0 :                             isdsts[tm] ? "\tD" : "");
    2483                 :                 }
    2484 EUB             :             }
    2485                 :             /* Print the default type if we have no transitions at all */
    2486 UIC           0 :             if (thistimei >= thistimelim)
    2487                 :             {
    2488 UBC           0 :                 unsigned char tm = defaulttype;
    2489 UIC           0 :                 char       *thisabbrev = &thischars[indmap[desigidx[tm]]];
    2490 EUB             : 
    2491 UBC           0 :                 fprintf(stdout, "%s\t" INT64_FORMAT "%s\n",
    2492                 :                         thisabbrev,
    2493 EUB             :                         utoffs[tm],
    2494 UIC           0 :                         isdsts[tm] ? "\tD" : "");
    2495                 :             }
    2496 EUB             :         }
    2497                 : 
    2498                 :         /*
    2499                 :          * Output a LO_TIME transition if needed; see limitrange. But do not
    2500                 :          * go below the minimum representable value for this pass.
    2501                 :          */
    2502 GIC        1408 :         lo = pass == 1 && lo_time < PG_INT32_MIN ? PG_INT32_MIN : lo_time;
    2503                 : 
    2504 CBC        1408 :         if (locut)
    2505 UIC           0 :             puttzcodepass(lo, fp, pass);
    2506 CBC       68560 :         for (i = thistimei; i < thistimelim; ++i)
    2507 EUB             :         {
    2508 CBC       67152 :             zic_t       at = ats[i] < lo ? lo : ats[i];
    2509                 : 
    2510           67152 :             puttzcodepass(at, fp, pass);
    2511                 :         }
    2512            1408 :         if (hicut)
    2513 UIC           0 :             puttzcodepass(hi_time + 1, fp, pass);
    2514 CBC        1408 :         currenttype = 0;
    2515 GBC        1408 :         if (locut)
    2516 LBC           0 :             putc(currenttype, fp);
    2517 CBC       68560 :         for (i = thistimei; i < thistimelim; ++i)
    2518 EUB             :         {
    2519 CBC       67152 :             currenttype = typemap[types[i]];
    2520 GIC       67152 :             putc(currenttype, fp);
    2521 ECB             :         }
    2522 CBC        1408 :         if (hicut)
    2523 UIC           0 :             putc(currenttype, fp);
    2524 ECB             : 
    2525 GBC        7868 :         for (i = old0; i < typecnt; i++)
    2526                 :         {
    2527 CBC       11512 :             int         h = (i == old0 ? thisdefaulttype
    2528 GIC        5052 :                              : i == thisdefaulttype ? old0 : i);
    2529 ECB             : 
    2530 CBC        6460 :             if (!omittype[h])
    2531                 :             {
    2532            6452 :                 puttzcode(utoffs[h], fp);
    2533 GIC        6452 :                 putc(isdsts[h], fp);
    2534 CBC        6452 :                 putc(indmap[desigidx[h]], fp);
    2535 ECB             :             }
    2536                 :         }
    2537 GIC        1408 :         if (thischarcnt != 0)
    2538            1408 :             fwrite(thischars, sizeof thischars[0],
    2539 ECB             :                    thischarcnt, fp);
    2540 CBC        1408 :         for (i = thisleapi; i < thisleaplim; ++i)
    2541                 :         {
    2542 ECB             :             zic_t       todo;
    2543                 : 
    2544 UIC           0 :             if (roll[i])
    2545                 :             {
    2546 UBC           0 :                 if (timecnt == 0 || trans[i] < ats[0])
    2547                 :                 {
    2548               0 :                     j = 0;
    2549 UIC           0 :                     while (isdsts[j])
    2550 UBC           0 :                         if (++j >= typecnt)
    2551 EUB             :                         {
    2552 UBC           0 :                             j = 0;
    2553 UIC           0 :                             break;
    2554 EUB             :                         }
    2555                 :                 }
    2556                 :                 else
    2557                 :                 {
    2558 UIC           0 :                     j = 1;
    2559               0 :                     while (j < timecnt &&
    2560 UBC           0 :                            trans[i] >= ats[j])
    2561               0 :                         ++j;
    2562               0 :                     j = types[j - 1];
    2563 EUB             :                 }
    2564 UBC           0 :                 todo = tadd(trans[i], -utoffs[j]);
    2565                 :             }
    2566 EUB             :             else
    2567 UIC           0 :                 todo = trans[i];
    2568               0 :             puttzcodepass(todo, fp, pass);
    2569 UBC           0 :             puttzcode(corr[i], fp);
    2570 EUB             :         }
    2571 GBC        1408 :         if (stdcnt != 0)
    2572 UIC           0 :             for (i = old0; i < typecnt; i++)
    2573 LBC           0 :                 if (!omittype[i])
    2574 UBC           0 :                     putc(ttisstds[i], fp);
    2575 GBC        1408 :         if (utcnt != 0)
    2576 UBC           0 :             for (i = old0; i < typecnt; i++)
    2577 LBC           0 :                 if (!omittype[i])
    2578 UBC           0 :                     putc(ttisuts[i], fp);
    2579 EUB             :     }
    2580 GBC        1408 :     fprintf(fp, "\n%s\n", string);
    2581 GIC        1408 :     close_file(fp, directory, name);
    2582 CBC        1408 :     free(ats);
    2583            1408 : }
    2584 ECB             : 
    2585                 : static char const *
    2586 UIC           0 : abbroffset(char *buf, zic_t offset)
    2587                 : {
    2588 UBC           0 :     char        sign = '+';
    2589                 :     int         seconds,
    2590 EUB             :                 minutes;
    2591                 : 
    2592 UIC           0 :     if (offset < 0)
    2593                 :     {
    2594 UBC           0 :         offset = -offset;
    2595 UIC           0 :         sign = '-';
    2596 EUB             :     }
    2597                 : 
    2598 UIC           0 :     seconds = offset % SECSPERMIN;
    2599               0 :     offset /= SECSPERMIN;
    2600 UBC           0 :     minutes = offset % MINSPERHOUR;
    2601               0 :     offset /= MINSPERHOUR;
    2602               0 :     if (100 <= offset)
    2603 EUB             :     {
    2604 UBC           0 :         error(_("%%z UT offset magnitude exceeds 99:59:59"));
    2605 UIC           0 :         return "%z";
    2606 EUB             :     }
    2607                 :     else
    2608                 :     {
    2609 UIC           0 :         char       *p = buf;
    2610                 : 
    2611 UBC           0 :         *p++ = sign;
    2612 UIC           0 :         *p++ = '0' + offset / 10;
    2613 UBC           0 :         *p++ = '0' + offset % 10;
    2614               0 :         if (minutes | seconds)
    2615 EUB             :         {
    2616 UBC           0 :             *p++ = '0' + minutes / 10;
    2617 UIC           0 :             *p++ = '0' + minutes % 10;
    2618 UBC           0 :             if (seconds)
    2619 EUB             :             {
    2620 UBC           0 :                 *p++ = '0' + seconds / 10;
    2621 UIC           0 :                 *p++ = '0' + seconds % 10;
    2622 EUB             :             }
    2623                 :         }
    2624 UIC           0 :         *p = '\0';
    2625               0 :         return buf;
    2626 EUB             :     }
    2627                 : }
    2628                 : 
    2629                 : static size_t
    2630 GIC      139116 : doabbr(char *abbr, struct zone const *zp, char const *letters,
    2631                 :        bool isdst, zic_t save, bool doquotes)
    2632 CBC        3632 : {
    2633                 :     char       *cp;
    2634 ECB             :     char       *slashp;
    2635                 :     size_t      len;
    2636 GIC      139116 :     char const *format = zp->z_format;
    2637                 : 
    2638 CBC      139116 :     slashp = strchr(format, '/');
    2639 GIC      139116 :     if (slashp == NULL)
    2640 ECB             :     {
    2641                 :         char        letterbuf[PERCENT_Z_LEN_BOUND + 1];
    2642                 : 
    2643 GIC       82660 :         if (zp->z_format_specifier == 'z')
    2644 UIC           0 :             letters = abbroffset(letterbuf, zp->z_stdoff + save);
    2645 CBC       82660 :         else if (!letters)
    2646 GBC        4696 :             letters = "%s";
    2647 CBC       82660 :         sprintf(abbr, format, letters);
    2648 ECB             :     }
    2649 CBC       56456 :     else if (isdst)
    2650                 :     {
    2651           29728 :         strcpy(abbr, slashp + 1);
    2652                 :     }
    2653 ECB             :     else
    2654                 :     {
    2655 GIC       26728 :         memcpy(abbr, format, slashp - format);
    2656           26728 :         abbr[slashp - format] = '\0';
    2657 ECB             :     }
    2658 CBC      139116 :     len = strlen(abbr);
    2659 GIC      139116 :     if (!doquotes)
    2660 CBC      137256 :         return len;
    2661            5492 :     for (cp = abbr; is_alpha(*cp); cp++)
    2662            3632 :         continue;
    2663            1860 :     if (len > 0 && *cp == '\0')
    2664            1116 :         return len;
    2665             744 :     abbr[len + 2] = '\0';
    2666             744 :     abbr[len + 1] = '>';
    2667             744 :     memmove(abbr + 1, abbr, len);
    2668             744 :     abbr[0] = '<';
    2669             744 :     return len + 2;
    2670 ECB             : }
    2671                 : 
    2672                 : static void
    2673 GIC       87812 : updateminmax(const zic_t x)
    2674                 : {
    2675 CBC       87812 :     if (min_year > x)
    2676 GIC        1492 :         min_year = x;
    2677 CBC       87812 :     if (max_year < x)
    2678            4336 :         max_year = x;
    2679           87812 : }
    2680 ECB             : 
    2681                 : static int
    2682 GIC        1736 : stringoffset(char *result, zic_t offset)
    2683                 : {
    2684 ECB             :     int         hours;
    2685                 :     int         minutes;
    2686                 :     int         seconds;
    2687 GIC        1736 :     bool        negative = offset < 0;
    2688            1736 :     int         len = negative;
    2689 ECB             : 
    2690 CBC        1736 :     if (negative)
    2691                 :     {
    2692             732 :         offset = -offset;
    2693 GIC         732 :         result[0] = '-';
    2694 ECB             :     }
    2695 CBC        1736 :     seconds = offset % SECSPERMIN;
    2696 GIC        1736 :     offset /= SECSPERMIN;
    2697 CBC        1736 :     minutes = offset % MINSPERHOUR;
    2698            1736 :     offset /= MINSPERHOUR;
    2699            1736 :     hours = offset;
    2700            1736 :     if (hours >= HOURSPERDAY * DAYSPERWEEK)
    2701 ECB             :     {
    2702 LBC           0 :         result[0] = '\0';
    2703 UIC           0 :         return 0;
    2704 EUB             :     }
    2705 GBC        1736 :     len += sprintf(result + len, "%d", hours);
    2706 GIC        1736 :     if (minutes != 0 || seconds != 0)
    2707 ECB             :     {
    2708 CBC          64 :         len += sprintf(result + len, ":%02d", minutes);
    2709 GIC          64 :         if (seconds != 0)
    2710 LBC           0 :             len += sprintf(result + len, ":%02d", seconds);
    2711 ECB             :     }
    2712 GBC        1736 :     return len;
    2713                 : }
    2714 ECB             : 
    2715                 : static int
    2716 GIC         904 : stringrule(char *result, struct rule *const rp, zic_t save, zic_t stdoff)
    2717                 : {
    2718 CBC         904 :     zic_t       tod = rp->r_tod;
    2719 GIC         904 :     int         compat = 0;
    2720 ECB             : 
    2721 CBC         904 :     if (rp->r_dycode == DC_DOM)
    2722                 :     {
    2723 ECB             :         int         month,
    2724                 :                     total;
    2725                 : 
    2726 UIC           0 :         if (rp->r_dayofmonth == 29 && rp->r_month == TM_FEBRUARY)
    2727               0 :             return -1;
    2728 UBC           0 :         total = 0;
    2729               0 :         for (month = 0; month < rp->r_month; ++month)
    2730               0 :             total += len_months[0][month];
    2731 EUB             :         /* Omit the "J" in Jan and Feb, as that's shorter.  */
    2732 UBC           0 :         if (rp->r_month <= 1)
    2733 UIC           0 :             result += sprintf(result, "%d", total + rp->r_dayofmonth - 1);
    2734 EUB             :         else
    2735 UBC           0 :             result += sprintf(result, "J%d", total + rp->r_dayofmonth);
    2736                 :     }
    2737 EUB             :     else
    2738                 :     {
    2739                 :         int         week;
    2740 GIC         904 :         int         wday = rp->r_wday;
    2741                 :         int         wdayoff;
    2742 ECB             : 
    2743 GIC         904 :         if (rp->r_dycode == DC_DOWGEQ)
    2744                 :         {
    2745 CBC         548 :             wdayoff = (rp->r_dayofmonth - 1) % DAYSPERWEEK;
    2746 GIC         548 :             if (wdayoff)
    2747 CBC          20 :                 compat = 2013;
    2748             548 :             wday -= wdayoff;
    2749             548 :             tod += wdayoff * SECSPERDAY;
    2750             548 :             week = 1 + (rp->r_dayofmonth - 1) / DAYSPERWEEK;
    2751 ECB             :         }
    2752 CBC         356 :         else if (rp->r_dycode == DC_DOWLEQ)
    2753                 :         {
    2754             356 :             if (rp->r_dayofmonth == len_months[1][rp->r_month])
    2755 GIC         340 :                 week = 5;
    2756 ECB             :             else
    2757                 :             {
    2758 GIC          16 :                 wdayoff = rp->r_dayofmonth % DAYSPERWEEK;
    2759              16 :                 if (wdayoff)
    2760 CBC          16 :                     compat = 2013;
    2761              16 :                 wday -= wdayoff;
    2762              16 :                 tod += wdayoff * SECSPERDAY;
    2763              16 :                 week = rp->r_dayofmonth / DAYSPERWEEK;
    2764 ECB             :             }
    2765                 :         }
    2766                 :         else
    2767 UIC           0 :             return -1;          /* "cannot happen" */
    2768 GIC         904 :         if (wday < 0)
    2769 GBC          16 :             wday += DAYSPERWEEK;
    2770 CBC         904 :         result += sprintf(result, "M%d.%d.%d",
    2771             904 :                           rp->r_month + 1, week, wday);
    2772 ECB             :     }
    2773 CBC         904 :     if (rp->r_todisut)
    2774 GIC         312 :         tod += stdoff;
    2775 CBC         904 :     if (rp->r_todisstd && !rp->r_isdst)
    2776             204 :         tod += save;
    2777             904 :     if (tod != 2 * SECSPERMIN * MINSPERHOUR)
    2778 ECB             :     {
    2779 CBC         316 :         *result++ = '/';
    2780 GIC         316 :         if (!stringoffset(result, tod))
    2781 LBC           0 :             return -1;
    2782 CBC         316 :         if (tod < 0)
    2783 EUB             :         {
    2784 LBC           0 :             if (compat < 2013)
    2785 UIC           0 :                 compat = 2013;
    2786 EUB             :         }
    2787 GBC         316 :         else if (SECSPERDAY <= tod)
    2788                 :         {
    2789 CBC          28 :             if (compat < 1994)
    2790 UIC           0 :                 compat = 1994;
    2791 ECB             :         }
    2792 EUB             :     }
    2793 GIC         904 :     return compat;
    2794                 : }
    2795 ECB             : 
    2796                 : static int
    2797 GIC        6632 : rule_cmp(struct rule const *a, struct rule const *b)
    2798                 : {
    2799 CBC        6632 :     if (!a)
    2800 GIC         456 :         return -!!b;
    2801 CBC        6176 :     if (!b)
    2802 LBC           0 :         return 1;
    2803 CBC        6176 :     if (a->r_hiyear != b->r_hiyear)
    2804 GBC        5600 :         return a->r_hiyear < b->r_hiyear ? -1 : 1;
    2805 CBC         576 :     if (a->r_month - b->r_month != 0)
    2806             576 :         return a->r_month - b->r_month;
    2807 LBC           0 :     return a->r_dayofmonth - b->r_dayofmonth;
    2808 ECB             : }
    2809 EUB             : 
    2810                 : static int
    2811 GIC        1408 : stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount)
    2812                 : {
    2813 ECB             :     const struct zone *zp;
    2814                 :     struct rule *rp;
    2815                 :     struct rule *stdrp;
    2816                 :     struct rule *dstrp;
    2817                 :     ptrdiff_t   i;
    2818                 :     const char *abbrvar;
    2819 GIC        1408 :     int         compat = 0;
    2820                 :     int         c;
    2821 ECB             :     size_t      len;
    2822                 :     int         offsetlen;
    2823                 :     struct rule stdr,
    2824                 :                 dstr;
    2825                 : 
    2826 GIC        1408 :     result[0] = '\0';
    2827                 : 
    2828 ECB             :     /*
    2829                 :      * Internet RFC 8536 section 5.1 says to use an empty TZ string if future
    2830                 :      * timestamps are truncated.
    2831                 :      */
    2832 GIC        1408 :     if (hi_time < max_time)
    2833 UIC           0 :         return -1;
    2834 ECB             : 
    2835 GBC        1408 :     zp = zpfirst + zonecount - 1;
    2836 GIC        1408 :     stdrp = dstrp = NULL;
    2837 CBC       11396 :     for (i = 0; i < zp->z_nrules; ++i)
    2838 ECB             :     {
    2839 CBC        9988 :         rp = &zp->z_rules[i];
    2840 GIC        9988 :         if (rp->r_hiwasnum || rp->r_hiyear != ZIC_MAX)
    2841 CBC        9084 :             continue;
    2842             904 :         if (!rp->r_isdst)
    2843 ECB             :         {
    2844 CBC         452 :             if (stdrp == NULL)
    2845 GIC         452 :                 stdrp = rp;
    2846 ECB             :             else
    2847 LBC           0 :                 return -1;
    2848                 :         }
    2849 EUB             :         else
    2850                 :         {
    2851 GIC         452 :             if (dstrp == NULL)
    2852             452 :                 dstrp = rp;
    2853 ECB             :             else
    2854 LBC           0 :                 return -1;
    2855                 :         }
    2856 EUB             :     }
    2857 GIC        1408 :     if (stdrp == NULL && dstrp == NULL)
    2858                 :     {
    2859 ECB             :         /*
    2860                 :          * There are no rules running through "max". Find the latest std rule
    2861                 :          * in stdabbrrp and latest rule of any type in stdrp.
    2862                 :          */
    2863 GIC         956 :         struct rule *stdabbrrp = NULL;
    2864                 : 
    2865 CBC        5424 :         for (i = 0; i < zp->z_nrules; ++i)
    2866                 :         {
    2867            4468 :             rp = &zp->z_rules[i];
    2868 GIC        4468 :             if (!rp->r_isdst && rule_cmp(stdabbrrp, rp) < 0)
    2869 CBC        1044 :                 stdabbrrp = rp;
    2870            4468 :             if (rule_cmp(stdrp, rp) < 0)
    2871            1300 :                 stdrp = rp;
    2872 ECB             :         }
    2873 CBC         956 :         if (stdrp != NULL && stdrp->r_isdst)
    2874                 :         {
    2875 ECB             :             /* Perpetual DST.  */
    2876 UIC           0 :             dstr.r_month = TM_JANUARY;
    2877               0 :             dstr.r_dycode = DC_DOM;
    2878 UBC           0 :             dstr.r_dayofmonth = 1;
    2879               0 :             dstr.r_tod = 0;
    2880               0 :             dstr.r_todisstd = dstr.r_todisut = false;
    2881               0 :             dstr.r_isdst = stdrp->r_isdst;
    2882               0 :             dstr.r_save = stdrp->r_save;
    2883               0 :             dstr.r_abbrvar = stdrp->r_abbrvar;
    2884               0 :             stdr.r_month = TM_DECEMBER;
    2885               0 :             stdr.r_dycode = DC_DOM;
    2886               0 :             stdr.r_dayofmonth = 31;
    2887               0 :             stdr.r_tod = SECSPERDAY + stdrp->r_save;
    2888               0 :             stdr.r_todisstd = stdr.r_todisut = false;
    2889               0 :             stdr.r_isdst = false;
    2890               0 :             stdr.r_save = 0;
    2891 EUB             :             stdr.r_abbrvar
    2892 UBC           0 :                 = (stdabbrrp ? stdabbrrp->r_abbrvar : "");
    2893 UIC           0 :             dstrp = &dstr;
    2894 UBC           0 :             stdrp = &stdr;
    2895 EUB             :         }
    2896                 :     }
    2897 GIC        1408 :     if (stdrp == NULL && (zp->z_nrules != 0 || zp->z_isdst))
    2898 UIC           0 :         return -1;
    2899 CBC        1408 :     abbrvar = (stdrp == NULL) ? "" : stdrp->r_abbrvar;
    2900 GBC        1408 :     len = doabbr(result, zp, abbrvar, false, 0, true);
    2901 CBC        1408 :     offsetlen = stringoffset(result + len, -zp->z_stdoff);
    2902            1408 :     if (!offsetlen)
    2903 ECB             :     {
    2904 LBC           0 :         result[0] = '\0';
    2905 UIC           0 :         return -1;
    2906 EUB             :     }
    2907 GBC        1408 :     len += offsetlen;
    2908 GIC        1408 :     if (dstrp == NULL)
    2909 CBC         956 :         return compat;
    2910             904 :     len += doabbr(result + len, zp, dstrp->r_abbrvar,
    2911             452 :                   dstrp->r_isdst, dstrp->r_save, true);
    2912             452 :     if (dstrp->r_save != SECSPERMIN * MINSPERHOUR)
    2913 ECB             :     {
    2914 CBC          12 :         offsetlen = stringoffset(result + len,
    2915 GIC          12 :                                  -(zp->z_stdoff + dstrp->r_save));
    2916 CBC          12 :         if (!offsetlen)
    2917 ECB             :         {
    2918 LBC           0 :             result[0] = '\0';
    2919 UIC           0 :             return -1;
    2920 EUB             :         }
    2921 GBC          12 :         len += offsetlen;
    2922                 :     }
    2923 CBC         452 :     result[len++] = ',';
    2924 GIC         452 :     c = stringrule(result + len, dstrp, dstrp->r_save, zp->z_stdoff);
    2925 CBC         452 :     if (c < 0)
    2926 ECB             :     {
    2927 LBC           0 :         result[0] = '\0';
    2928 UIC           0 :         return -1;
    2929 EUB             :     }
    2930 GBC         452 :     if (compat < c)
    2931 GIC          20 :         compat = c;
    2932 CBC         452 :     len += strlen(result + len);
    2933             452 :     result[len++] = ',';
    2934             452 :     c = stringrule(result + len, stdrp, dstrp->r_save, zp->z_stdoff);
    2935             452 :     if (c < 0)
    2936 ECB             :     {
    2937 LBC           0 :         result[0] = '\0';
    2938 UIC           0 :         return -1;
    2939 EUB             :     }
    2940 GBC         452 :     if (compat < c)
    2941 UIC           0 :         compat = c;
    2942 CBC         452 :     return compat;
    2943 EUB             : }
    2944 ECB             : 
    2945                 : static void
    2946 GIC        1408 : outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
    2947                 : {
    2948 ECB             :     const struct zone *zp;
    2949                 :     struct rule *rp;
    2950                 :     ptrdiff_t   i,
    2951                 :                 j;
    2952                 :     bool        usestart,
    2953                 :                 useuntil;
    2954                 :     zic_t       starttime,
    2955                 :                 untiltime;
    2956                 :     zic_t       stdoff;
    2957                 :     zic_t       save;
    2958                 :     zic_t       year;
    2959                 :     zic_t       startoff;
    2960                 :     bool        startttisstd;
    2961                 :     bool        startttisut;
    2962                 :     int         type;
    2963                 :     char       *startbuf;
    2964                 :     char       *ab;
    2965                 :     char       *envvar;
    2966                 :     int         max_abbr_len;
    2967                 :     int         max_envvar_len;
    2968                 :     bool        prodstic;       /* all rules are min to max */
    2969                 :     int         compat;
    2970                 :     bool        do_extend;
    2971                 :     char        version;
    2972 GIC        1408 :     ptrdiff_t   lastatmax = -1;
    2973            1408 :     zic_t       one = 1;
    2974 CBC        1408 :     zic_t       y2038_boundary = one << 31;
    2975 ECB             :     zic_t       max_year0;
    2976 CBC        1408 :     int         defaulttype = -1;
    2977                 : 
    2978            1408 :     max_abbr_len = 2 + max_format_len + max_abbrvar_len;
    2979 GIC        1408 :     max_envvar_len = 2 * max_abbr_len + 5 * 9;
    2980 CBC        1408 :     startbuf = emalloc(max_abbr_len + 1);
    2981            1408 :     ab = emalloc(max_abbr_len + 1);
    2982            1408 :     envvar = emalloc(max_envvar_len + 1);
    2983            1408 :     INITIALIZE(untiltime);
    2984            1408 :     INITIALIZE(starttime);
    2985 ECB             : 
    2986                 :     /*
    2987                 :      * Now. . .finally. . .generate some useful data!
    2988                 :      */
    2989 GIC        1408 :     timecnt = 0;
    2990            1408 :     typecnt = 0;
    2991 CBC        1408 :     charcnt = 0;
    2992            1408 :     prodstic = zonecount == 1;
    2993 ECB             : 
    2994                 :     /*
    2995                 :      * Thanks to Earl Chew for noting the need to unconditionally initialize
    2996                 :      * startttisstd.
    2997                 :      */
    2998 GIC        1408 :     startttisstd = false;
    2999            1408 :     startttisut = false;
    3000 CBC        1408 :     min_year = max_year = EPOCH_YEAR;
    3001            1408 :     if (leapseen)
    3002 ECB             :     {
    3003 LBC           0 :         updateminmax(leapminyear);
    3004 UIC           0 :         updateminmax(leapmaxyear + (leapmaxyear < ZIC_MAX));
    3005 EUB             :     }
    3006 GBC        9220 :     for (i = 0; i < zonecount; ++i)
    3007                 :     {
    3008 CBC        7812 :         zp = &zpfirst[i];
    3009 GIC        7812 :         if (i < zonecount - 1)
    3010 CBC        6404 :             updateminmax(zp->z_untilrule.r_loyear);
    3011           70704 :         for (j = 0; j < zp->z_nrules; ++j)
    3012 ECB             :         {
    3013 CBC       62892 :             rp = &zp->z_rules[j];
    3014 GIC       62892 :             if (rp->r_lowasnum)
    3015 CBC       62892 :                 updateminmax(rp->r_loyear);
    3016           62892 :             if (rp->r_hiwasnum)
    3017           18516 :                 updateminmax(rp->r_hiyear);
    3018           62892 :             if (rp->r_lowasnum || rp->r_hiwasnum)
    3019           62892 :                 prodstic = false;
    3020 ECB             :         }
    3021                 :     }
    3022                 : 
    3023                 :     /*
    3024                 :      * Generate lots of data if a rule can't cover all future times.
    3025                 :      */
    3026 GIC        1408 :     compat = stringzone(envvar, zpfirst, zonecount);
    3027            1408 :     version = compat < 2013 ? ZIC_VERSION_PRE_2013 : ZIC_VERSION;
    3028 CBC        1408 :     do_extend = compat < 0;
    3029            1408 :     if (noise)
    3030 ECB             :     {
    3031 LBC           0 :         if (!*envvar)
    3032 UIC           0 :             warning("%s %s",
    3033 EUB             :                     _("no POSIX environment variable for zone"),
    3034 UBC           0 :                     zpfirst->z_name);
    3035 UIC           0 :         else if (compat != 0)
    3036 EUB             :         {
    3037                 :             /*
    3038                 :              * Circa-COMPAT clients, and earlier clients, might not work for
    3039                 :              * this zone when given dates before 1970 or after 2038.
    3040                 :              */
    3041 UIC           0 :             warning(_("%s: pre-%d clients may mishandle"
    3042                 :                       " distant timestamps"),
    3043 UBC           0 :                     zpfirst->z_name, compat);
    3044                 :         }
    3045 EUB             :     }
    3046 GIC        1408 :     if (do_extend)
    3047                 :     {
    3048 ECB             :         /*
    3049                 :          * Search through a couple of extra years past the obvious 400, to
    3050                 :          * avoid edge cases.  For example, suppose a non-POSIX rule applies
    3051                 :          * from 2012 onwards and has transitions in March and September, plus
    3052                 :          * some one-off transitions in November 2013.  If zic looked only at
    3053                 :          * the last 400 years, it would set max_year=2413, with the intent
    3054                 :          * that the 400 years 2014 through 2413 will be repeated.  The last
    3055                 :          * transition listed in the tzfile would be in 2413-09, less than 400
    3056                 :          * years after the last one-off transition in 2013-11.  Two years
    3057                 :          * might be overkill, but with the kind of edge cases available we're
    3058                 :          * not sure that one year would suffice.
    3059                 :          */
    3060                 :         enum
    3061                 :         {
    3062                 :         years_of_observations = YEARSPERREPEAT + 2};
    3063                 : 
    3064 UIC           0 :         if (min_year >= ZIC_MIN + years_of_observations)
    3065               0 :             min_year -= years_of_observations;
    3066 EUB             :         else
    3067 UBC           0 :             min_year = ZIC_MIN;
    3068 UIC           0 :         if (max_year <= ZIC_MAX - years_of_observations)
    3069 UBC           0 :             max_year += years_of_observations;
    3070 EUB             :         else
    3071 UBC           0 :             max_year = ZIC_MAX;
    3072                 : 
    3073 EUB             :         /*
    3074                 :          * Regardless of any of the above, for a "proDSTic" zone which
    3075                 :          * specifies that its rules always have and always will be in effect,
    3076                 :          * we only need one cycle to define the zone.
    3077                 :          */
    3078 UIC           0 :         if (prodstic)
    3079                 :         {
    3080 UBC           0 :             min_year = 1900;
    3081 UIC           0 :             max_year = min_year + years_of_observations;
    3082 EUB             :         }
    3083                 :     }
    3084 GIC        1408 :     max_year0 = max_year;
    3085            1408 :     if (want_bloat())
    3086 ECB             :     {
    3087                 :         /*
    3088                 :          * For the benefit of older systems, generate data from 1900 through
    3089                 :          * 2038.
    3090                 :          */
    3091 UIC           0 :         if (min_year > 1900)
    3092               0 :             min_year = 1900;
    3093 UBC           0 :         if (max_year < 2038)
    3094               0 :             max_year = 2038;
    3095 EUB             :     }
    3096                 : 
    3097 GIC        9220 :     for (i = 0; i < zonecount; ++i)
    3098                 :     {
    3099 CBC        7812 :         struct rule *prevrp = NULL;
    3100                 : 
    3101 ECB             :         /*
    3102                 :          * A guess that may well be corrected later.
    3103                 :          */
    3104 GIC        7812 :         save = 0;
    3105            7812 :         zp = &zpfirst[i];
    3106 CBC        7812 :         usestart = i > 0 && (zp - 1)->z_untiltime > min_time;
    3107            7812 :         useuntil = i < (zonecount - 1);
    3108            7812 :         if (useuntil && zp->z_untiltime <= min_time)
    3109 LBC           0 :             continue;
    3110 CBC        7812 :         stdoff = zp->z_stdoff;
    3111 GBC        7812 :         eat(zp->z_filename, zp->z_linenum);
    3112 CBC        7812 :         *startbuf = '\0';
    3113            7812 :         startoff = zp->z_stdoff;
    3114            7812 :         if (zp->z_nrules == 0)
    3115 ECB             :         {
    3116 CBC        4696 :             save = zp->z_save;
    3117 GIC        4696 :             doabbr(startbuf, zp, NULL, zp->z_isdst, save, false);
    3118 CBC        4696 :             type = addtype(oadd(zp->z_stdoff, save),
    3119            4696 :                            startbuf, zp->z_isdst, startttisstd,
    3120 ECB             :                            startttisut);
    3121 CBC        4696 :             if (usestart)
    3122                 :             {
    3123            3320 :                 addtt(starttime, type);
    3124 GIC        3320 :                 usestart = false;
    3125 ECB             :             }
    3126                 :             else
    3127 GIC        1376 :                 defaulttype = type;
    3128                 :         }
    3129 ECB             :         else
    3130 GIC      278248 :             for (year = min_year; year <= max_year; ++year)
    3131                 :             {
    3132 CBC      277428 :                 if (useuntil && year > zp->z_untilrule.r_hiyear)
    3133 GIC        2296 :                     break;
    3134 ECB             : 
    3135                 :                 /*
    3136                 :                  * Mark which rules to do in the current year. For those to
    3137                 :                  * do, calculate rpytime(rp, year); The former TYPE field was
    3138                 :                  * also considered here.
    3139                 :                  */
    3140 GIC     5791532 :                 for (j = 0; j < zp->z_nrules; ++j)
    3141                 :                 {
    3142 CBC     5516400 :                     rp = &zp->z_rules[j];
    3143 GIC     5516400 :                     eats(zp->z_filename, zp->z_linenum,
    3144 ECB             :                          rp->r_filename, rp->r_linenum);
    3145 CBC     7231848 :                     rp->r_todo = year >= rp->r_loyear &&
    3146 GIC     1715448 :                         year <= rp->r_hiyear;
    3147 CBC     5516400 :                     if (rp->r_todo)
    3148 ECB             :                     {
    3149 CBC      134544 :                         rp->r_temp = rpytime(rp, year);
    3150                 :                         rp->r_todo
    3151          269088 :                             = (rp->r_temp < y2038_boundary
    3152 GIC      134544 :                                || year <= max_year0);
    3153 ECB             :                     }
    3154                 :                 }
    3155                 :                 for (;;)
    3156 GIC      131076 :                 {
    3157                 :                     ptrdiff_t   k;
    3158 ECB             :                     zic_t       jtime,
    3159                 :                                 ktime;
    3160                 :                     zic_t       offset;
    3161                 : 
    3162 GIC      406208 :                     INITIALIZE(ktime);
    3163          406208 :                     if (useuntil)
    3164 ECB             :                     {
    3165                 :                         /*
    3166                 :                          * Turn untiltime into UT assuming the current stdoff
    3167                 :                          * and save values.
    3168                 :                          */
    3169 GIC      291628 :                         untiltime = zp->z_untiltime;
    3170          291628 :                         if (!zp->z_untilrule.r_todisut)
    3171 CBC      286428 :                             untiltime = tadd(untiltime,
    3172 ECB             :                                              -stdoff);
    3173 CBC      291628 :                         if (!zp->z_untilrule.r_todisstd)
    3174 GIC      208708 :                             untiltime = tadd(untiltime,
    3175 ECB             :                                              -save);
    3176                 :                     }
    3177                 : 
    3178                 :                     /*
    3179                 :                      * Find the rule (of those to do, if any) that takes
    3180                 :                      * effect earliest in the year.
    3181                 :                      */
    3182 GIC      406208 :                     k = -1;
    3183         9073588 :                     for (j = 0; j < zp->z_nrules; ++j)
    3184 ECB             :                     {
    3185 CBC     8667380 :                         rp = &zp->z_rules[j];
    3186 GIC     8667380 :                         if (!rp->r_todo)
    3187 CBC     8463784 :                             continue;
    3188          203596 :                         eats(zp->z_filename, zp->z_linenum,
    3189 ECB             :                              rp->r_filename, rp->r_linenum);
    3190 CBC      203596 :                         offset = rp->r_todisut ? 0 : stdoff;
    3191 GIC      203596 :                         if (!rp->r_todisstd)
    3192 CBC      133324 :                             offset = oadd(offset, save);
    3193          203596 :                         jtime = rp->r_temp;
    3194          203596 :                         if (jtime == min_time ||
    3195          203596 :                             jtime == max_time)
    3196 LBC           0 :                             continue;
    3197 CBC      203596 :                         jtime = tadd(jtime, -offset);
    3198 GBC      203596 :                         if (k < 0 || jtime < ktime)
    3199 ECB             :                         {
    3200 CBC      166212 :                             k = j;
    3201 GIC      166212 :                             ktime = jtime;
    3202 ECB             :                         }
    3203 CBC       37384 :                         else if (jtime == ktime)
    3204                 :                         {
    3205 LBC           0 :                             char const *dup_rules_msg =
    3206                 :                             _("two rules for same instant");
    3207 EUB             : 
    3208 UIC           0 :                             eats(zp->z_filename, zp->z_linenum,
    3209                 :                                  rp->r_filename, rp->r_linenum);
    3210 UBC           0 :                             warning("%s", dup_rules_msg);
    3211 UIC           0 :                             rp = &zp->z_rules[k];
    3212 UBC           0 :                             eats(zp->z_filename, zp->z_linenum,
    3213 EUB             :                                  rp->r_filename, rp->r_linenum);
    3214 UBC           0 :                             error("%s", dup_rules_msg);
    3215                 :                         }
    3216 EUB             :                     }
    3217 GIC      406208 :                     if (k < 0)
    3218          272912 :                         break;  /* go on to next year */
    3219 CBC      133296 :                     rp = &zp->z_rules[k];
    3220          133296 :                     rp->r_todo = false;
    3221          133296 :                     if (useuntil && ktime >= untiltime)
    3222            1516 :                         break;
    3223          131780 :                     save = rp->r_save;
    3224          131780 :                     if (usestart && ktime == starttime)
    3225             292 :                         usestart = false;
    3226          131780 :                     if (usestart)
    3227 ECB             :                     {
    3228 CBC      124528 :                         if (ktime < starttime)
    3229                 :                         {
    3230           68492 :                             startoff = oadd(zp->z_stdoff,
    3231                 :                                             save);
    3232           68492 :                             doabbr(startbuf, zp,
    3233                 :                                    rp->r_abbrvar,
    3234           68492 :                                    rp->r_isdst,
    3235                 :                                    rp->r_save,
    3236 ECB             :                                    false);
    3237 GIC       68492 :                             continue;
    3238                 :                         }
    3239 CBC       56036 :                         if (*startbuf == '\0'
    3240 GIC        1560 :                             && startoff == oadd(zp->z_stdoff,
    3241 ECB             :                                                 save))
    3242                 :                         {
    3243 GIC         780 :                             doabbr(startbuf,
    3244                 :                                    zp,
    3245 ECB             :                                    rp->r_abbrvar,
    3246 GIC         780 :                                    rp->r_isdst,
    3247                 :                                    rp->r_save,
    3248 ECB             :                                    false);
    3249                 :                         }
    3250                 :                     }
    3251 GIC       63288 :                     eats(zp->z_filename, zp->z_linenum,
    3252                 :                          rp->r_filename, rp->r_linenum);
    3253 CBC       63288 :                     doabbr(ab, zp, rp->r_abbrvar,
    3254 GIC       63288 :                            rp->r_isdst, rp->r_save, false);
    3255 CBC       63288 :                     offset = oadd(zp->z_stdoff, rp->r_save);
    3256           63288 :                     if (!want_bloat() && !useuntil && !do_extend
    3257           23356 :                         && prevrp
    3258           22696 :                         && rp->r_hiyear == ZIC_MAX
    3259            2584 :                         && prevrp->r_hiyear == ZIC_MAX)
    3260             704 :                         break;
    3261           62584 :                     type = addtype(offset, ab, rp->r_isdst,
    3262           62584 :                                    rp->r_todisstd, rp->r_todisut);
    3263           62584 :                     if (defaulttype < 0 && !rp->r_isdst)
    3264              32 :                         defaulttype = type;
    3265           62584 :                     if (rp->r_hiyear == ZIC_MAX
    3266            3848 :                         && !(0 <= lastatmax
    3267            3360 :                              && ktime < attypes[lastatmax].at))
    3268            3848 :                         lastatmax = timecnt;
    3269           62584 :                     addtt(ktime, type);
    3270           62584 :                     prevrp = rp;
    3271 ECB             :                 }
    3272                 :             }
    3273 GIC        7812 :         if (usestart)
    3274                 :         {
    3275 CBC        2792 :             if (*startbuf == '\0' &&
    3276 UIC           0 :                 zp->z_format != NULL &&
    3277 LBC           0 :                 strchr(zp->z_format, '%') == NULL &&
    3278 UBC           0 :                 strchr(zp->z_format, '/') == NULL)
    3279               0 :                 strcpy(startbuf, zp->z_format);
    3280 GBC        2792 :             eat(zp->z_filename, zp->z_linenum);
    3281            2792 :             if (*startbuf == '\0')
    3282 LBC           0 :                 error(_("cannot determine time zone abbreviation to use just after until time"));
    3283 ECB             :             else
    3284 EUB             :             {
    3285 GIC        2792 :                 bool        isdst = startoff != zp->z_stdoff;
    3286                 : 
    3287 CBC        2792 :                 type = addtype(startoff, startbuf, isdst,
    3288                 :                                startttisstd, startttisut);
    3289            2792 :                 if (defaulttype < 0 && !isdst)
    3290 UIC           0 :                     defaulttype = type;
    3291 CBC        2792 :                 addtt(starttime, type);
    3292 EUB             :             }
    3293 ECB             :         }
    3294                 : 
    3295                 :         /*
    3296                 :          * Now we may get to set starttime for the next zone line.
    3297                 :          */
    3298 GIC        7812 :         if (useuntil)
    3299                 :         {
    3300 CBC        6404 :             startttisstd = zp->z_untilrule.r_todisstd;
    3301 GIC        6404 :             startttisut = zp->z_untilrule.r_todisut;
    3302 CBC        6404 :             starttime = zp->z_untiltime;
    3303            6404 :             if (!startttisstd)
    3304            5284 :                 starttime = tadd(starttime, -save);
    3305            6404 :             if (!startttisut)
    3306            6128 :                 starttime = tadd(starttime, -stdoff);
    3307 ECB             :         }
    3308                 :     }
    3309 GIC        1408 :     if (defaulttype < 0)
    3310 UIC           0 :         defaulttype = 0;
    3311 CBC        1408 :     if (0 <= lastatmax)
    3312 GBC         488 :         attypes[lastatmax].dontmerge = true;
    3313 CBC        1408 :     if (do_extend)
    3314 ECB             :     {
    3315                 :         /*
    3316                 :          * If we're extending the explicitly listed observations for 400 years
    3317                 :          * because we can't fill the POSIX-TZ field, check whether we actually
    3318                 :          * ended up explicitly listing observations through that period.  If
    3319                 :          * there aren't any near the end of the 400-year period, add a
    3320                 :          * redundant one at the end of the final year, to make it clear that
    3321                 :          * we are claiming to have definite knowledge of the lack of
    3322                 :          * transitions up to that point.
    3323                 :          */
    3324                 :         struct rule xr;
    3325                 :         struct attype *lastat;
    3326                 : 
    3327 UIC           0 :         xr.r_month = TM_JANUARY;
    3328               0 :         xr.r_dycode = DC_DOM;
    3329 UBC           0 :         xr.r_dayofmonth = 1;
    3330               0 :         xr.r_tod = 0;
    3331               0 :         for (lastat = attypes, i = 1; i < timecnt; i++)
    3332               0 :             if (attypes[i].at > lastat->at)
    3333               0 :                 lastat = &attypes[i];
    3334               0 :         if (!lastat || lastat->at < rpytime(&xr, max_year - 1))
    3335 EUB             :         {
    3336 UBC           0 :             addtt(rpytime(&xr, max_year + 1),
    3337 UIC           0 :                   lastat ? lastat->type : defaulttype);
    3338 UBC           0 :             attypes[timecnt - 1].dontmerge = true;
    3339 EUB             :         }
    3340                 :     }
    3341 GIC        1408 :     writezone(zpfirst->z_name, envvar, version, defaulttype);
    3342            1408 :     free(startbuf);
    3343 CBC        1408 :     free(ab);
    3344            1408 :     free(envvar);
    3345            1408 : }
    3346 ECB             : 
    3347                 : static void
    3348 GIC       68696 : addtt(zic_t starttime, int type)
    3349                 : {
    3350 CBC       68696 :     attypes = growalloc(attypes, sizeof *attypes, timecnt, &timecnt_alloc);
    3351 GIC       68696 :     attypes[timecnt].at = starttime;
    3352 CBC       68696 :     attypes[timecnt].dontmerge = false;
    3353           68696 :     attypes[timecnt].type = type;
    3354           68696 :     ++timecnt;
    3355           68696 : }
    3356 ECB             : 
    3357                 : static int
    3358 GIC       70072 : addtype(zic_t utoff, char const *abbr, bool isdst, bool ttisstd, bool ttisut)
    3359                 : {
    3360 ECB             :     int         i,
    3361                 :                 j;
    3362                 : 
    3363 GIC       70072 :     if (!(-1L - 2147483647L <= utoff && utoff <= 2147483647L))
    3364                 :     {
    3365 LBC           0 :         error(_("UT offset out of range"));
    3366 UIC           0 :         exit(EXIT_FAILURE);
    3367 EUB             :     }
    3368 GBC       70072 :     if (!want_bloat())
    3369 GIC       70072 :         ttisstd = ttisut = false;
    3370 ECB             : 
    3371 CBC      749448 :     for (j = 0; j < charcnt; ++j)
    3372 GIC      743540 :         if (strcmp(&chars[j], abbr) == 0)
    3373 CBC       64164 :             break;
    3374           70072 :     if (j == charcnt)
    3375            5908 :         newabbr(abbr);
    3376 ECB             :     else
    3377                 :     {
    3378                 :         /* If there's already an entry, return its index.  */
    3379 GIC      233736 :         for (i = 0; i < typecnt; i++)
    3380          233184 :             if (utoff == utoffs[i] && isdst == isdsts[i] && j == desigidx[i]
    3381 CBC       63612 :                 && ttisstd == ttisstds[i] && ttisut == ttisuts[i])
    3382           63612 :                 return i;
    3383 ECB             :     }
    3384                 : 
    3385                 :     /*
    3386                 :      * There isn't one; add a new one, unless there are already too many.
    3387                 :      */
    3388 GIC        6460 :     if (typecnt >= TZ_MAX_TYPES)
    3389                 :     {
    3390 LBC           0 :         error(_("too many local time types"));
    3391 UIC           0 :         exit(EXIT_FAILURE);
    3392 EUB             :     }
    3393 GBC        6460 :     i = typecnt++;
    3394 GIC        6460 :     utoffs[i] = utoff;
    3395 CBC        6460 :     isdsts[i] = isdst;
    3396            6460 :     ttisstds[i] = ttisstd;
    3397            6460 :     ttisuts[i] = ttisut;
    3398            6460 :     desigidx[i] = j;
    3399            6460 :     return i;
    3400 ECB             : }
    3401                 : 
    3402                 : static void
    3403 UIC           0 : leapadd(zic_t t, int correction, int rolling)
    3404                 : {
    3405 EUB             :     int         i;
    3406                 : 
    3407 UIC           0 :     if (TZ_MAX_LEAPS <= leapcnt)
    3408                 :     {
    3409 UBC           0 :         error(_("too many leap seconds"));
    3410 UIC           0 :         exit(EXIT_FAILURE);
    3411 EUB             :     }
    3412 UBC           0 :     for (i = 0; i < leapcnt; ++i)
    3413 UIC           0 :         if (t <= trans[i])
    3414 UBC           0 :             break;
    3415               0 :     memmove(&trans[i + 1], &trans[i], (leapcnt - i) * sizeof *trans);
    3416               0 :     memmove(&corr[i + 1], &corr[i], (leapcnt - i) * sizeof *corr);
    3417               0 :     memmove(&roll[i + 1], &roll[i], (leapcnt - i) * sizeof *roll);
    3418               0 :     trans[i] = t;
    3419               0 :     corr[i] = correction;
    3420               0 :     roll[i] = rolling;
    3421               0 :     ++leapcnt;
    3422               0 : }
    3423 EUB             : 
    3424                 : static void
    3425 UIC           0 : adjleap(void)
    3426                 : {
    3427 EUB             :     int         i;
    3428 UIC           0 :     zic_t       last = 0;
    3429               0 :     zic_t       prevtrans = 0;
    3430 EUB             : 
    3431                 :     /*
    3432                 :      * propagate leap seconds forward
    3433                 :      */
    3434 UIC           0 :     for (i = 0; i < leapcnt; ++i)
    3435                 :     {
    3436 UBC           0 :         if (trans[i] - prevtrans < 28 * SECSPERDAY)
    3437                 :         {
    3438               0 :             error(_("Leap seconds too close together"));
    3439 UIC           0 :             exit(EXIT_FAILURE);
    3440 EUB             :         }
    3441 UBC           0 :         prevtrans = trans[i];
    3442 UIC           0 :         trans[i] = tadd(trans[i], last);
    3443 UBC           0 :         last = corr[i] += last;
    3444 EUB             :     }
    3445                 : 
    3446 UIC           0 :     if (leapexpires < 0)
    3447                 :     {
    3448 UBC           0 :         leapexpires = comment_leapexpires;
    3449 UIC           0 :         if (0 <= leapexpires)
    3450 UBC           0 :             warning(_("\"#expires\" is obsolescent; use \"Expires\""));
    3451 EUB             :     }
    3452                 : 
    3453 UIC           0 :     if (0 <= leapexpires)
    3454                 :     {
    3455 UBC           0 :         leapexpires = oadd(leapexpires, last);
    3456 UIC           0 :         if (!(leapcnt == 0 || (trans[leapcnt - 1] < leapexpires)))
    3457 EUB             :         {
    3458 UBC           0 :             error(_("last Leap time does not precede Expires time"));
    3459 UIC           0 :             exit(EXIT_FAILURE);
    3460 EUB             :         }
    3461 UBC           0 :         if (leapexpires <= hi_time)
    3462 UIC           0 :             hi_time = leapexpires - 1;
    3463 EUB             :     }
    3464 UBC           0 : }
    3465                 : 
    3466 EUB             : /* Is A a space character in the C locale?  */
    3467                 : static bool
    3468 GIC      555468 : is_space(char a)
    3469                 : {
    3470 CBC      555468 :     switch (a)
    3471                 :     {
    3472          335620 :         default:
    3473 GIC      335620 :             return false;
    3474 CBC      219848 :         case ' ':
    3475 ECB             :         case '\f':
    3476                 :         case '\n':
    3477                 :         case '\r':
    3478                 :         case '\t':
    3479                 :         case '\v':
    3480 GIC      219848 :             return true;
    3481                 :     }
    3482 ECB             : }
    3483                 : 
    3484                 : /* Is A an alphabetic character in the C locale?  */
    3485                 : static bool
    3486 GIC       30104 : is_alpha(char a)
    3487                 : {
    3488 CBC       30104 :     switch (a)
    3489                 :     {
    3490           13756 :         default:
    3491 GIC       13756 :             return false;
    3492 CBC       16348 :         case 'A':
    3493 ECB             :         case 'B':
    3494                 :         case 'C':
    3495                 :         case 'D':
    3496                 :         case 'E':
    3497                 :         case 'F':
    3498                 :         case 'G':
    3499                 :         case 'H':
    3500                 :         case 'I':
    3501                 :         case 'J':
    3502                 :         case 'K':
    3503                 :         case 'L':
    3504                 :         case 'M':
    3505                 :         case 'N':
    3506                 :         case 'O':
    3507                 :         case 'P':
    3508                 :         case 'Q':
    3509                 :         case 'R':
    3510                 :         case 'S':
    3511                 :         case 'T':
    3512                 :         case 'U':
    3513                 :         case 'V':
    3514                 :         case 'W':
    3515                 :         case 'X':
    3516                 :         case 'Y':
    3517                 :         case 'Z':
    3518                 :         case 'a':
    3519                 :         case 'b':
    3520                 :         case 'c':
    3521                 :         case 'd':
    3522                 :         case 'e':
    3523                 :         case 'f':
    3524                 :         case 'g':
    3525                 :         case 'h':
    3526                 :         case 'i':
    3527                 :         case 'j':
    3528                 :         case 'k':
    3529                 :         case 'l':
    3530                 :         case 'm':
    3531                 :         case 'n':
    3532                 :         case 'o':
    3533                 :         case 'p':
    3534                 :         case 'q':
    3535                 :         case 'r':
    3536                 :         case 's':
    3537                 :         case 't':
    3538                 :         case 'u':
    3539                 :         case 'v':
    3540                 :         case 'w':
    3541                 :         case 'x':
    3542                 :         case 'y':
    3543                 :         case 'z':
    3544 GIC       16348 :             return true;
    3545                 :     }
    3546 ECB             : }
    3547                 : 
    3548                 : /* If A is an uppercase character in the C locale, return its lowercase
    3549                 :    counterpart.  Otherwise, return A.  */
    3550                 : static char
    3551 GIC     1781944 : lowerit(char a)
    3552                 : {
    3553 CBC     1781944 :     switch (a)
    3554                 :     {
    3555          896116 :         default:
    3556 GIC      896116 :             return a;
    3557 CBC      114608 :         case 'A':
    3558          114608 :             return 'a';
    3559 LBC           0 :         case 'B':
    3560               0 :             return 'b';
    3561 UBC           0 :         case 'C':
    3562               0 :             return 'c';
    3563 GBC       36864 :         case 'D':
    3564           36864 :             return 'd';
    3565 LBC           0 :         case 'E':
    3566               0 :             return 'e';
    3567 GBC       47772 :         case 'F':
    3568           47772 :             return 'f';
    3569 LBC           0 :         case 'G':
    3570               0 :             return 'g';
    3571 UBC           0 :         case 'H':
    3572               0 :             return 'h';
    3573               0 :         case 'I':
    3574               0 :             return 'i';
    3575 GBC      154352 :         case 'J':
    3576          154352 :             return 'j';
    3577 LBC           0 :         case 'K':
    3578               0 :             return 'k';
    3579 GBC       26712 :         case 'L':
    3580           26712 :             return 'l';
    3581 CBC      116240 :         case 'M':
    3582          116240 :             return 'm';
    3583           42816 :         case 'N':
    3584           42816 :             return 'n';
    3585           89184 :         case 'O':
    3586           89184 :             return 'o';
    3587 LBC           0 :         case 'P':
    3588               0 :             return 'p';
    3589 UBC           0 :         case 'Q':
    3590               0 :             return 'q';
    3591 GBC       69000 :         case 'R':
    3592           69000 :             return 'r';
    3593 CBC      140500 :         case 'S':
    3594          140500 :             return 's';
    3595           12540 :         case 'T':
    3596           12540 :             return 't';
    3597 LBC           0 :         case 'U':
    3598               0 :             return 'u';
    3599 UBC           0 :         case 'V':
    3600               0 :             return 'v';
    3601 GBC        5960 :         case 'W':
    3602            5960 :             return 'w';
    3603 LBC           0 :         case 'X':
    3604               0 :             return 'x';
    3605 UBC           0 :         case 'Y':
    3606               0 :             return 'y';
    3607 GBC       29280 :         case 'Z':
    3608           29280 :             return 'z';
    3609 ECB             :     }
    3610                 : }
    3611                 : 
    3612                 : /* case-insensitive equality */
    3613                 : static bool
    3614 GIC      381620 : ciequal(const char *ap, const char *bp)
    3615                 : {
    3616 CBC      476416 :     while (lowerit(*ap) == lowerit(*bp++))
    3617 GIC      102240 :         if (*ap++ == '\0')
    3618 CBC        7444 :             return true;
    3619          374176 :     return false;
    3620 ECB             : }
    3621                 : 
    3622                 : static bool
    3623 UIC           0 : itsabbr(const char *abbr, const char *word)
    3624                 : {
    3625 UBC           0 :     if (lowerit(*abbr) != lowerit(*word))
    3626 UIC           0 :         return false;
    3627 UBC           0 :     ++word;
    3628               0 :     while (*++abbr != '\0')
    3629 EUB             :         do
    3630                 :         {
    3631 UIC           0 :             if (*word == '\0')
    3632               0 :                 return false;
    3633 UBC           0 :         } while (lowerit(*word++) != lowerit(*abbr));
    3634               0 :     return true;
    3635 EUB             : }
    3636                 : 
    3637                 : /* Return true if ABBR is an initial prefix of WORD, ignoring ASCII case.  */
    3638                 : 
    3639                 : static bool
    3640 GIC      371640 : ciprefix(char const *abbr, char const *word)
    3641                 : {
    3642 ECB             :     do
    3643 GIC      441092 :         if (!*abbr)
    3644           33752 :             return true;
    3645 CBC      407340 :     while (lowerit(*abbr++) == lowerit(*word++));
    3646 ECB             : 
    3647 CBC      337888 :     return false;
    3648                 : }
    3649 ECB             : 
    3650                 : static const struct lookup *
    3651 GIC       69756 : byword(const char *word, const struct lookup *table)
    3652                 : {
    3653 ECB             :     const struct lookup *foundlp;
    3654                 :     const struct lookup *lp;
    3655                 : 
    3656 GIC       69756 :     if (word == NULL || table == NULL)
    3657 UIC           0 :         return NULL;
    3658 ECB             : 
    3659 EUB             :     /*
    3660                 :      * If TABLE is LASTS and the word starts with "last" followed by a
    3661                 :      * non-'-', skip the "last" and look in WDAY_NAMES instead. Warn about any
    3662                 :      * usage of the undocumented prefix "last-".
    3663                 :      */
    3664 GIC       69756 :     if (table == lasts && ciprefix("last", word) && word[4])
    3665                 :     {
    3666 CBC        1368 :         if (word[4] == '-')
    3667 UIC           0 :             warning(_("\"%s\" is undocumented; use \"last%s\" instead"),
    3668 ECB             :                     word, word + 5);
    3669 EUB             :         else
    3670                 :         {
    3671 GIC        1368 :             word += 4;
    3672            1368 :             table = wday_names;
    3673 ECB             :         }
    3674                 :     }
    3675                 : 
    3676                 :     /*
    3677                 :      * Look for exact match.
    3678                 :      */
    3679 GIC      443932 :     for (lp = table; lp->l_word != NULL; ++lp)
    3680          381620 :         if (ciequal(word, lp->l_word))
    3681 CBC        7444 :             return lp;
    3682 ECB             : 
    3683                 :     /*
    3684                 :      * Look for inexact match.
    3685                 :      */
    3686 GIC       62312 :     foundlp = NULL;
    3687          419520 :     for (lp = table; lp->l_word != NULL; ++lp)
    3688 CBC      357208 :         if (ciprefix(word, lp->l_word))
    3689 ECB             :         {
    3690 CBC       32384 :             if (foundlp == NULL)
    3691 GIC       32384 :                 foundlp = lp;
    3692 ECB             :             else
    3693 LBC           0 :                 return NULL;    /* multiple inexact matches */
    3694                 :         }
    3695 EUB             : 
    3696 GIC       62312 :     if (foundlp && noise)
    3697                 :     {
    3698 ECB             :         /* Warn about any backward-compatibility issue with pre-2017c zic.  */
    3699 UIC           0 :         bool        pre_2017c_match = false;
    3700                 : 
    3701 UBC           0 :         for (lp = table; lp->l_word; lp++)
    3702 UIC           0 :             if (itsabbr(word, lp->l_word))
    3703 EUB             :             {
    3704 UBC           0 :                 if (pre_2017c_match)
    3705                 :                 {
    3706               0 :                     warning(_("\"%s\" is ambiguous in pre-2017c zic"), word);
    3707 UIC           0 :                     break;
    3708 EUB             :                 }
    3709 UBC           0 :                 pre_2017c_match = true;
    3710                 :             }
    3711 EUB             :     }
    3712                 : 
    3713 GIC       62312 :     return foundlp;
    3714                 : }
    3715 ECB             : 
    3716                 : static char **
    3717 GIC       16828 : getfields(char *cp)
    3718                 : {
    3719 ECB             :     char       *dp;
    3720                 :     char      **array;
    3721                 :     int         nsubs;
    3722                 : 
    3723 GIC       16828 :     if (cp == NULL)
    3724 UIC           0 :         return NULL;
    3725 CBC       16828 :     array = emalloc(size_product(strlen(cp) + 1, sizeof *array));
    3726 GBC       16828 :     nsubs = 0;
    3727 ECB             :     for (;;)
    3728                 :     {
    3729 GIC      143572 :         while (is_space(*cp))
    3730 UIC           0 :             ++cp;
    3731 CBC      143572 :         if (*cp == '\0' || *cp == '#')
    3732 EUB             :             break;
    3733 CBC      126744 :         array[nsubs++] = dp = cp;
    3734                 :         do
    3735 ECB             :         {
    3736 GIC      301972 :             if ((*dp = *cp++) != '"')
    3737          301972 :                 ++dp;
    3738 ECB             :             else
    3739 LBC           0 :                 while ((*dp = *cp++) != '"')
    3740 UIC           0 :                     if (*dp != '\0')
    3741 UBC           0 :                         ++dp;
    3742 EUB             :                     else
    3743                 :                     {
    3744 UIC           0 :                         error(_("Odd number of quotation marks"));
    3745               0 :                         exit(EXIT_FAILURE);
    3746 EUB             :                     }
    3747 GBC      301972 :         } while (*cp && *cp != '#' && !is_space(*cp));
    3748 GIC      126744 :         if (is_space(*cp))
    3749 CBC      109924 :             ++cp;
    3750          126744 :         *dp = '\0';
    3751 ECB             :     }
    3752 CBC       16828 :     array[nsubs] = NULL;
    3753 GIC       16828 :     return array;
    3754 ECB             : }
    3755                 : 
    3756                 : static void
    3757 UIC           0 : time_overflow(void)
    3758                 : {
    3759 UBC           0 :     error(_("time overflow"));
    3760 UIC           0 :     exit(EXIT_FAILURE);
    3761 EUB             : }
    3762                 : 
    3763                 : static zic_t
    3764 GIC     5081904 : oadd(zic_t t1, zic_t t2)
    3765                 : {
    3766 CBC     5081904 :     if (t1 < 0 ? t2 < ZIC_MIN - t1 : ZIC_MAX - t1 < t2)
    3767 UIC           0 :         time_overflow();
    3768 CBC     5081904 :     return t1 + t2;
    3769 EUB             : }
    3770 ECB             : 
    3771                 : static zic_t
    3772 GIC      851092 : tadd(zic_t t1, zic_t t2)
    3773                 : {
    3774 CBC      851092 :     if (t1 < 0)
    3775                 :     {
    3776          257108 :         if (t2 < min_time - t1)
    3777                 :         {
    3778 LBC           0 :             if (t1 != min_time)
    3779 UIC           0 :                 time_overflow();
    3780 UBC           0 :             return min_time;
    3781 EUB             :         }
    3782                 :     }
    3783                 :     else
    3784                 :     {
    3785 GIC      593984 :         if (max_time - t1 < t2)
    3786                 :         {
    3787 LBC           0 :             if (t1 != max_time)
    3788 UIC           0 :                 time_overflow();
    3789 UBC           0 :             return max_time;
    3790 EUB             :         }
    3791                 :     }
    3792 GIC      851092 :     return t1 + t2;
    3793                 : }
    3794 ECB             : 
    3795                 : /*
    3796                 :  * Given a rule, and a year, compute the date (in seconds since January 1,
    3797                 :  * 1970, 00:00 LOCAL time) in that year that the rule refers to.
    3798                 :  */
    3799                 : 
    3800                 : static zic_t
    3801 GIC      140948 : rpytime(const struct rule *rp, zic_t wantedy)
    3802                 : {
    3803 ECB             :     int         m,
    3804                 :                 i;
    3805                 :     zic_t       dayoff;         /* with a nod to Margaret O. */
    3806                 :     zic_t       t,
    3807                 :                 y;
    3808                 : 
    3809 GIC      140948 :     if (wantedy == ZIC_MIN)
    3810 UIC           0 :         return min_time;
    3811 CBC      140948 :     if (wantedy == ZIC_MAX)
    3812 UBC           0 :         return max_time;
    3813 CBC      140948 :     dayoff = 0;
    3814 GBC      140948 :     m = TM_JANUARY;
    3815 CBC      140948 :     y = EPOCH_YEAR;
    3816          140948 :     if (y < wantedy)
    3817 ECB             :     {
    3818 CBC       85940 :         wantedy -= y;
    3819 GIC       85940 :         dayoff = (wantedy / YEARSPERREPEAT) * (SECSPERREPEAT / SECSPERDAY);
    3820 CBC       85940 :         wantedy %= YEARSPERREPEAT;
    3821           85940 :         wantedy += y;
    3822 ECB             :     }
    3823 CBC       55008 :     else if (wantedy < 0)
    3824                 :     {
    3825 LBC           0 :         dayoff = (wantedy / YEARSPERREPEAT) * (SECSPERREPEAT / SECSPERDAY);
    3826 UIC           0 :         wantedy %= YEARSPERREPEAT;
    3827 EUB             :     }
    3828 GBC     3726092 :     while (wantedy != y)
    3829                 :     {
    3830 CBC     3585144 :         if (wantedy > y)
    3831                 :         {
    3832         1882932 :             i = len_years[isleap(y)];
    3833 GIC     1882932 :             ++y;
    3834 ECB             :         }
    3835                 :         else
    3836                 :         {
    3837 GIC     1702212 :             --y;
    3838         1702212 :             i = -len_years[isleap(y)];
    3839 ECB             :         }
    3840 CBC     3585144 :         dayoff = oadd(dayoff, i);
    3841                 :     }
    3842          933656 :     while (m != rp->r_month)
    3843                 :     {
    3844          792708 :         i = len_months[isleap(y)][m];
    3845 GIC      792708 :         dayoff = oadd(dayoff, i);
    3846 CBC      792708 :         ++m;
    3847 ECB             :     }
    3848 CBC      140948 :     i = rp->r_dayofmonth;
    3849 GIC      140948 :     if (m == TM_FEBRUARY && i == 29 && !isleap(y))
    3850 ECB             :     {
    3851 CBC         320 :         if (rp->r_dycode == DC_DOWLEQ)
    3852 GIC         320 :             --i;
    3853 ECB             :         else
    3854                 :         {
    3855 UIC           0 :             error(_("use of 2/29 in non leap-year"));
    3856               0 :             exit(EXIT_FAILURE);
    3857 EUB             :         }
    3858                 :     }
    3859 GIC      140948 :     --i;
    3860          140948 :     dayoff = oadd(dayoff, i);
    3861 CBC      140948 :     if (rp->r_dycode == DC_DOWGEQ || rp->r_dycode == DC_DOWLEQ)
    3862 ECB             :     {
    3863                 :         zic_t       wday;
    3864                 : 
    3865                 : #define LDAYSPERWEEK    ((zic_t) DAYSPERWEEK)
    3866 GIC       90264 :         wday = EPOCH_WDAY;
    3867                 : 
    3868 ECB             :         /*
    3869                 :          * Don't trust mod of negative numbers.
    3870                 :          */
    3871 GIC       90264 :         if (dayoff >= 0)
    3872           70744 :             wday = (wday + dayoff) % LDAYSPERWEEK;
    3873 ECB             :         else
    3874                 :         {
    3875 GIC       19520 :             wday -= ((-dayoff) % LDAYSPERWEEK);
    3876           19520 :             if (wday < 0)
    3877 CBC        5316 :                 wday += LDAYSPERWEEK;
    3878 ECB             :         }
    3879 CBC      351508 :         while (wday != rp->r_wday)
    3880 GIC      261244 :             if (rp->r_dycode == DC_DOWGEQ)
    3881 ECB             :             {
    3882 CBC       82872 :                 dayoff = oadd(dayoff, 1);
    3883 GIC       82872 :                 if (++wday >= LDAYSPERWEEK)
    3884 CBC       21360 :                     wday = 0;
    3885           82872 :                 ++i;
    3886 ECB             :             }
    3887                 :             else
    3888                 :             {
    3889 GIC      178372 :                 dayoff = oadd(dayoff, -1);
    3890          178372 :                 if (--wday < 0)
    3891 CBC         908 :                     wday = LDAYSPERWEEK - 1;
    3892          178372 :                 --i;
    3893 ECB             :             }
    3894 CBC       90264 :         if (i < 0 || i >= len_months[isleap(y)][m])
    3895                 :         {
    3896             124 :             if (noise)
    3897 UIC           0 :                 warning(_("rule goes past start/end of month; \
    3898 ECB             : will not work with pre-2004 versions of zic"));
    3899 EUB             :         }
    3900                 :     }
    3901 GIC      140948 :     if (dayoff < min_time / SECSPERDAY)
    3902 UIC           0 :         return min_time;
    3903 CBC      140948 :     if (dayoff > max_time / SECSPERDAY)
    3904 UBC           0 :         return max_time;
    3905 CBC      140948 :     t = (zic_t) dayoff * SECSPERDAY;
    3906 GBC      140948 :     return tadd(t, rp->r_tod);
    3907 ECB             : }
    3908                 : 
    3909                 : static void
    3910 GIC        5908 : newabbr(const char *string)
    3911                 : {
    3912 ECB             :     int         i;
    3913                 : 
    3914 GIC        5908 :     if (strcmp(string, GRANDPARENTED) != 0)
    3915                 :     {
    3916 ECB             :         const char *cp;
    3917                 :         const char *mp;
    3918                 : 
    3919 GIC        5908 :         cp = string;
    3920            5908 :         mp = NULL;
    3921 CBC       36508 :         while (is_alpha(*cp) || ('0' <= *cp && *cp <= '9')
    3922           32372 :                || *cp == '-' || *cp == '+')
    3923           18704 :             ++cp;
    3924            5908 :         if (noise && cp - string < 3)
    3925 LBC           0 :             mp = _("time zone abbreviation has fewer than 3 characters");
    3926 CBC        5908 :         if (cp - string > ZIC_MAX_ABBR_LEN_WO_WARN)
    3927 UBC           0 :             mp = _("time zone abbreviation has too many characters");
    3928 CBC        5908 :         if (*cp != '\0')
    3929 UBC           0 :             mp = _("time zone abbreviation differs from POSIX standard");
    3930 CBC        5908 :         if (mp != NULL)
    3931 UBC           0 :             warning("%s (%s)", mp, string);
    3932 ECB             :     }
    3933 GBC        5908 :     i = strlen(string) + 1;
    3934 GIC        5908 :     if (charcnt + i > TZ_MAX_CHARS)
    3935 ECB             :     {
    3936 LBC           0 :         error(_("too many, or too long, time zone abbreviations"));
    3937 UIC           0 :         exit(EXIT_FAILURE);
    3938 EUB             :     }
    3939 GBC        5908 :     strcpy(&chars[charcnt], string);
    3940 GIC        5908 :     charcnt += i;
    3941 CBC        5908 : }
    3942 ECB             : 
    3943                 : /* Ensure that the directories of ARGNAME exist, by making any missing
    3944                 :    ones.  If ANCESTORS, do this only for ARGNAME's ancestors; otherwise,
    3945                 :    do it for ARGNAME too.  Exit with failure if there is trouble.
    3946                 :    Do not consider an existing non-directory to be trouble.  */
    3947                 : static void
    3948 GIC          42 : mkdirs(char const *argname, bool ancestors)
    3949                 : {
    3950 ECB             :     char       *name;
    3951                 :     char       *cp;
    3952                 : 
    3953 GIC          42 :     cp = name = ecpyalloc(argname);
    3954                 : 
    3955 ECB             :     /*
    3956                 :      * On MS-Windows systems, do not worry about drive letters or backslashes,
    3957                 :      * as this should suffice in practice.  Time zone names do not use drive
    3958                 :      * letters and backslashes.  If the -d option of zic does not name an
    3959                 :      * already-existing directory, it can use slashes to separate the
    3960                 :      * already-existing ancestor prefix from the to-be-created subdirectories.
    3961                 :      */
    3962                 : 
    3963                 :     /* Do not mkdir a root directory, as it must exist.  */
    3964 GIC          44 :     while (*cp == '/')
    3965               2 :         cp++;
    3966 ECB             : 
    3967 CBC         152 :     while (cp && ((cp = strchr(cp, '/')) || !ancestors))
    3968                 :     {
    3969              68 :         if (cp)
    3970 GIC          66 :             *cp = '\0';
    3971 ECB             : 
    3972                 :         /*
    3973                 :          * Try to create it.  It's OK if creation fails because the directory
    3974                 :          * already exists, perhaps because some other process just created it.
    3975                 :          * For simplicity do not check first whether it already exists, as
    3976                 :          * that is checked anyway if the mkdir fails.
    3977                 :          */
    3978 GIC          68 :         if (mkdir(name, MKDIR_UMASK) != 0)
    3979                 :         {
    3980 ECB             :             /*
    3981                 :              * For speed, skip itsdir if errno == EEXIST.  Since mkdirs is
    3982                 :              * called only after open fails with ENOENT on a subfile, EEXIST
    3983                 :              * implies itsdir here.
    3984                 :              */
    3985 GIC          26 :             int         err = errno;
    3986                 : 
    3987 CBC          26 :             if (err != EEXIST && !itsdir(name))
    3988                 :             {
    3989 LBC           0 :                 error(_("%s: Cannot create directory %s: %s"),
    3990                 :                       progname, name, strerror(err));
    3991 UBC           0 :                 exit(EXIT_FAILURE);
    3992                 :             }
    3993 EUB             :         }
    3994 GIC          68 :         if (cp)
    3995              66 :             *cp++ = '/';
    3996 ECB             :     }
    3997 CBC          42 :     free(name);
    3998 GIC          42 : }
    3999 ECB             : 
    4000                 : 
    4001                 : #ifdef WIN32
    4002                 : /*
    4003                 :  * To run on win32
    4004                 :  */
    4005                 : int
    4006                 : link(const char *oldpath, const char *newpath)
    4007                 : {
    4008                 :     if (!CopyFile(oldpath, newpath, false))
    4009                 :     {
    4010                 :         _dosmaperr(GetLastError());
    4011                 :         return -1;
    4012                 :     }
    4013                 :     return 0;
    4014                 : }
    4015                 : #endif
        

Generated by: LCOV version v1.16-55-g56c0a2a