[BACK]Return to zic.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libc / time

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/lib/libc/time/zic.c between version 1.74 and 1.75

version 1.74, 2019/04/04 18:18:31 version 1.75, 2019/07/03 15:50:16
Line 3 
Line 3 
 ** This file is in the public domain, so clarified as of  ** This file is in the public domain, so clarified as of
 ** 2006-07-17 by Arthur David Olson.  ** 2006-07-17 by Arthur David Olson.
 */  */
   /* Compile .zi time zone data into TZif binary files.  */
   
 #if HAVE_NBTOOL_CONFIG_H  #if HAVE_NBTOOL_CONFIG_H
 #include "nbtool_config.h"  #include "nbtool_config.h"
Line 101  struct rule {
Line 102  struct rule {
         int             r_wday;          int             r_wday;
   
         zic_t           r_tod;          /* time from midnight */          zic_t           r_tod;          /* time from midnight */
         bool            r_todisstd;     /* above is standard time if 1 */          bool            r_todisstd;     /* is r_tod standard time? */
                                         /* or wall clock time if 0 */          bool            r_todisut;      /* is r_tod UT? */
         bool            r_todisgmt;     /* above is GMT if 1 */  
                                         /* or local time if 0 */  
         bool            r_isdst;        /* is this daylight saving time? */          bool            r_isdst;        /* is this daylight saving time? */
         zic_t           r_stdoff;       /* offset from default time (which is          zic_t           r_save;         /* offset from standard time */
                                            usually standard time) */  
         const char *    r_abbrvar;      /* variable part of abbreviation */          const char *    r_abbrvar;      /* variable part of abbreviation */
   
         bool            r_todo;         /* a rule to do (used in outzone) */          bool            r_todo;         /* a rule to do (used in outzone) */
Line 127  struct zone {
Line 125  struct zone {
         lineno          z_linenum;          lineno          z_linenum;
   
         const char *    z_name;          const char *    z_name;
         zic_t           z_gmtoff;          zic_t           z_stdoff;
         char *          z_rule;          char *          z_rule;
         const char *    z_format;          const char *    z_format;
         char            z_format_specifier;          char            z_format_specifier;
   
         bool            z_isdst;          bool            z_isdst;
         zic_t           z_stdoff;          zic_t           z_save;
   
         struct rule *   z_rules;          struct rule *   z_rules;
         ptrdiff_t       z_nrules;          ptrdiff_t       z_nrules;
Line 171  static void associate(void);
Line 169  static void associate(void);
 static void     dolink(const char *, const char *, bool);  static void     dolink(const char *, const char *, bool);
 static char **  getfields(char * buf);  static char **  getfields(char * buf);
 static zic_t    gethms(const char * string, const char * errstring);  static zic_t    gethms(const char * string, const char * errstring);
 static zic_t    getstdoff(char *, bool *);  static zic_t    getsave(char *, bool *);
 static void     infile(const char * filename);  static void     infile(const char * filename);
 static void     inleap(char ** fields, int nfields);  static void     inleap(char ** fields, int nfields);
 static void     inlink(char ** fields, int nfields);  static void     inlink(char ** fields, int nfields);
Line 242  static int  typecnt;
Line 240  static int  typecnt;
 */  */
   
 #define ZF_NAME         1  #define ZF_NAME         1
 #define ZF_GMTOFF       2  #define ZF_STDOFF       2
 #define ZF_RULE         3  #define ZF_RULE         3
 #define ZF_FORMAT       4  #define ZF_FORMAT       4
 #define ZF_TILYEAR      5  #define ZF_TILYEAR      5
Line 256  static int  typecnt;
Line 254  static int  typecnt;
 ** Which fields are which on a Zone continuation line.  ** Which fields are which on a Zone continuation line.
 */  */
   
 #define ZFC_GMTOFF      0  #define ZFC_STDOFF      0
 #define ZFC_RULE        1  #define ZFC_RULE        1
 #define ZFC_FORMAT      2  #define ZFC_FORMAT      2
 #define ZFC_TILYEAR     3  #define ZFC_TILYEAR     3
Line 277  static int  typecnt;
Line 275  static int  typecnt;
 #define RF_MONTH        5  #define RF_MONTH        5
 #define RF_DAY          6  #define RF_DAY          6
 #define RF_TOD          7  #define RF_TOD          7
 #define RF_STDOFF       8  #define RF_SAVE         8
 #define RF_ABBRVAR      9  #define RF_ABBRVAR      9
 #define RULE_FIELDS     10  #define RULE_FIELDS     10
   
Line 418  static struct attype {
Line 416  static struct attype {
         bool            dontmerge;          bool            dontmerge;
         unsigned char   type;          unsigned char   type;
 } *                     attypes;  } *                     attypes;
 static zic_t            gmtoffs[TZ_MAX_TYPES];  static zic_t            utoffs[TZ_MAX_TYPES];
 static char             isdsts[TZ_MAX_TYPES];  static char             isdsts[TZ_MAX_TYPES];
 static unsigned char    abbrinds[TZ_MAX_TYPES];  static unsigned char    desigidx[TZ_MAX_TYPES];
 static bool             ttisstds[TZ_MAX_TYPES];  static bool             ttisstds[TZ_MAX_TYPES];
 static bool             ttisgmts[TZ_MAX_TYPES];  static bool             ttisuts[TZ_MAX_TYPES];
 static char             chars[TZ_MAX_CHARS];  static char             chars[TZ_MAX_CHARS];
 static zic_t            trans[TZ_MAX_LEAPS];  static zic_t            trans[TZ_MAX_LEAPS];
 static zic_t            corr[TZ_MAX_LEAPS];  static zic_t            corr[TZ_MAX_LEAPS];
Line 584  usage(FILE *stream, int status)
Line 582  usage(FILE *stream, int status)
 {  {
   fprintf(stream,    fprintf(stream,
           _("%s: usage is %s [ --version ] [ --help ] [ -v ] \\\n"            _("%s: usage is %s [ --version ] [ --help ] [ -v ] \\\n"
             "\t[ -l localtime ] [ -p posixrules ] [ -d directory ] \\\n"              "\t[ -b {slim|fat} ] [ -d directory ] [ -l localtime ]"
             "\t[ -t localtime-link ] [ -L leapseconds ] [ -r '[@lo][/@hi]' ] \\\n"              " [ -L leapseconds ] \\\n"
               "\t[ -p posixrules ] [ -r '[@lo][/@hi]' ] [ -t localtime-link ] \\\n"
             "\t[ filename ... ]\n\n"              "\t[ filename ... ]\n\n"
             "Report bugs to %s.\n"),              "Report bugs to %s.\n"),
           progname, progname, REPORT_BUGS_TO);            progname, progname, REPORT_BUGS_TO);
Line 660  static const char * leapsec;
Line 659  static const char * leapsec;
 static const char *     tzdefault;  static const char *     tzdefault;
 static const char *     yitcommand;  static const char *     yitcommand;
   
   /* -1 if the TZif output file should be slim, 0 if default, 1 if the
      output should be fat for backward compatibility.  Currently the
      default is fat, although this may change.  */
   static int bloat;
   
   static bool
   want_bloat(void)
   {
     return 0 <= bloat;
   }
   
   #ifndef ZIC_BLOAT_DEFAULT
   # define ZIC_BLOAT_DEFAULT "fat"
   #endif
   
 int  int
 main(int argc, char **argv)  main(int argc, char **argv)
 {  {
Line 691  main(int argc, char **argv)
Line 705  main(int argc, char **argv)
                 } else if (strcmp(argv[k], "--help") == 0) {                  } else if (strcmp(argv[k], "--help") == 0) {
                         usage(stdout, EXIT_SUCCESS);                          usage(stdout, EXIT_SUCCESS);
                 }                  }
         while ((c = getopt(argc, argv, "d:l:L:p:r:st:vy:")) != EOF && c != -1)          while ((c = getopt(argc, argv, "b:d:l:L:p:r:st:vy:")) != EOF && c != -1)
                 switch (c) {                  switch (c) {
                         default:                          default:
                                 usage(stderr, EXIT_FAILURE);                                  usage(stderr, EXIT_FAILURE);
                           case 'b':
                                   if (strcmp(optarg, "slim") == 0) {
                                     if (0 < bloat)
                                       error(_("incompatible -b options"));
                                     bloat = -1;
                                   } else if (strcmp(optarg, "fat") == 0) {
                                     if (bloat < 0)
                                       error(_("incompatible -b options"));
                                     bloat = 1;
                                   } else
                                     error(_("invalid option: -b '%s'"), optarg);
                                   break;
                         case 'd':                          case 'd':
                                 if (directory == NULL)                                  if (directory == NULL)
                                         directory = optarg;                                          directory = optarg;
Line 780  _("%s: invalid time range: %s\n"),
Line 806  _("%s: invalid time range: %s\n"),
                 }                  }
         if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)          if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
                 usage(stderr, EXIT_FAILURE);    /* usage message by request */                  usage(stderr, EXIT_FAILURE);    /* usage message by request */
           if (bloat == 0)
             bloat = strcmp(ZIC_BLOAT_DEFAULT, "slim") == 0 ? -1 : 1;
         if (directory == NULL)          if (directory == NULL)
                 directory = TZDIR;                  directory = TZDIR;
         if (tzdefault == NULL)          if (tzdefault == NULL)
Line 1078  associate(void)
Line 1106  associate(void)
 {  {
         struct zone *   zp;          struct zone *   zp;
         struct rule *   rp;          struct rule *   rp;
         ptrdiff_t       base, out;          ptrdiff_t       i, j, base, out;
         int             i, j;  
   
         if (nrules != 0) {          if (nrules != 0) {
                 qsort(rules, (size_t)nrules, sizeof *rules, rcomp);                  qsort(rules, (size_t)nrules, sizeof *rules, rcomp);
Line 1134  associate(void)
Line 1161  associate(void)
                         ** Maybe we have a local standard time offset.                          ** Maybe we have a local standard time offset.
                         */                          */
                         eat(zp->z_filename, zp->z_linenum);                          eat(zp->z_filename, zp->z_linenum);
                         zp->z_stdoff = getstdoff(zp->z_rule, &zp->z_isdst);                          zp->z_save = getsave(zp->z_rule, &zp->z_isdst);
                         /*                          /*
                         ** Note, though, that if there's no rule,                          ** Note, though, that if there's no rule,
                         ** a '%s' in the format is a bad thing.                          ** a '%s' in the format is a bad thing.
Line 1292  warning(_("values over 24 hours not hand
Line 1319  warning(_("values over 24 hours not hand
 }  }
   
 static zic_t  static zic_t
 getstdoff(char *field, bool *isdst)  getsave(char *field, bool *isdst)
 {  {
   int dst = -1;    int dst = -1;
   zic_t stdoff;    zic_t save;
   size_t fieldlen = strlen(field);    size_t fieldlen = strlen(field);
   if (fieldlen != 0) {    if (fieldlen != 0) {
     char *ep = field + fieldlen - 1;      char *ep = field + fieldlen - 1;
Line 1304  getstdoff(char *field, bool *isdst)
Line 1331  getstdoff(char *field, bool *isdst)
       case 's': dst = 0; *ep = '\0'; break;        case 's': dst = 0; *ep = '\0'; break;
     }      }
   }    }
   stdoff = gethms(field, _("invalid saved time"));    save = gethms(field, _("invalid saved time"));
   *isdst = dst < 0 ? stdoff != 0 : dst;    *isdst = dst < 0 ? save != 0 : dst;
   return stdoff;    return save;
 }  }
   
 static void  static void
Line 1329  inrule(char **fields, int nfields)
Line 1356  inrule(char **fields, int nfields)
         }          }
         r.r_filename = filename;          r.r_filename = filename;
         r.r_linenum = linenum;          r.r_linenum = linenum;
         r.r_stdoff = getstdoff(fields[RF_STDOFF], &r.r_isdst);          r.r_save = getsave(fields[RF_SAVE], &r.r_isdst);
         rulesub(&r, fields[RF_LOYEAR], fields[RF_HIYEAR], fields[RF_COMMAND],          rulesub(&r, fields[RF_LOYEAR], fields[RF_HIYEAR], fields[RF_COMMAND],
                 fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]);                  fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]);
         r.r_name = ecpyalloc(fields[RF_NAME]);          r.r_name = ecpyalloc(fields[RF_NAME]);
Line 1390  inzsub(char **fields, int nfields, bool 
Line 1417  inzsub(char **fields, int nfields, bool 
         char *          cp;          char *          cp;
         char *          cp1;          char *          cp1;
         static struct zone      z;          static struct zone      z;
         int             i_gmtoff, i_rule, i_format;          int             i_stdoff, i_rule, i_format;
         int             i_untilyear, i_untilmonth;          int             i_untilyear, i_untilmonth;
         int             i_untilday, i_untiltime;          int             i_untilday, i_untiltime;
         bool            hasuntil;          bool            hasuntil;
   
         if (iscont) {          if (iscont) {
                 i_gmtoff = ZFC_GMTOFF;                  i_stdoff = ZFC_STDOFF;
                 i_rule = ZFC_RULE;                  i_rule = ZFC_RULE;
                 i_format = ZFC_FORMAT;                  i_format = ZFC_FORMAT;
                 i_untilyear = ZFC_TILYEAR;                  i_untilyear = ZFC_TILYEAR;
Line 1407  inzsub(char **fields, int nfields, bool 
Line 1434  inzsub(char **fields, int nfields, bool 
         } else if (!namecheck(fields[ZF_NAME]))          } else if (!namecheck(fields[ZF_NAME]))
                 return false;                  return false;
         else {          else {
                 i_gmtoff = ZF_GMTOFF;                  i_stdoff = ZF_STDOFF;
                 i_rule = ZF_RULE;                  i_rule = ZF_RULE;
                 i_format = ZF_FORMAT;                  i_format = ZF_FORMAT;
                 i_untilyear = ZF_TILYEAR;                  i_untilyear = ZF_TILYEAR;
Line 1418  inzsub(char **fields, int nfields, bool 
Line 1445  inzsub(char **fields, int nfields, bool 
         }          }
         z.z_filename = filename;          z.z_filename = filename;
         z.z_linenum = linenum;          z.z_linenum = linenum;
         z.z_gmtoff = gethms(fields[i_gmtoff], _("invalid UT offset"));          z.z_stdoff = gethms(fields[i_stdoff], _("invalid UT offset"));
         if ((cp = strchr(fields[i_format], '%')) != 0) {          if ((cp = strchr(fields[i_format], '%')) != 0) {
                 if ((*++cp != 's' && *cp != 'z') || strchr(cp, '%')                  if ((*++cp != 's' && *cp != 'z') || strchr(cp, '%')
                     || strchr(fields[i_format], '/')) {                      || strchr(fields[i_format], '/')) {
Line 1611  rulesub(struct rule *rp, const char *loy
Line 1638  rulesub(struct rule *rp, const char *loy
         }          }
         rp->r_month = lp->l_value;          rp->r_month = lp->l_value;
         rp->r_todisstd = false;          rp->r_todisstd = false;
         rp->r_todisgmt = false;          rp->r_todisut = false;
         dp = ecpyalloc(timep);          dp = ecpyalloc(timep);
         if (*dp != '\0') {          if (*dp != '\0') {
                 ep = dp + strlen(dp) - 1;                  ep = dp + strlen(dp) - 1;
                 switch (lowerit(*ep)) {                  switch (lowerit(*ep)) {
                         case 's':       /* Standard */                          case 's':       /* Standard */
                                 rp->r_todisstd = true;                                  rp->r_todisstd = true;
                                 rp->r_todisgmt = false;                                  rp->r_todisut = false;
                                 *ep = '\0';                                  *ep = '\0';
                                 break;                                  break;
                         case 'w':       /* Wall */                          case 'w':       /* Wall */
                                 rp->r_todisstd = false;                                  rp->r_todisstd = false;
                                 rp->r_todisgmt = false;                                  rp->r_todisut = false;
                                 *ep = '\0';                                  *ep = '\0';
                                 break;                                  break;
                         case 'g':       /* Greenwich */                          case 'g':       /* Greenwich */
                         case 'u':       /* Universal */                          case 'u':       /* Universal */
                         case 'z':       /* Zulu */                          case 'z':       /* Zulu */
                                 rp->r_todisstd = true;                                  rp->r_todisstd = true;
                                 rp->r_todisgmt = true;                                  rp->r_todisut = true;
                                 *ep = '\0';                                  *ep = '\0';
                                 break;                                  break;
                 }                  }
Line 1797  atcomp(const void *avp, const void *bvp)
Line 1824  atcomp(const void *avp, const void *bvp)
         return (a < b) ? -1 : (a > b);          return (a < b) ? -1 : (a > b);
 }  }
   
 static void  
 swaptypes(int i, int j)  
 {  
   { zic_t t = gmtoffs[i]; gmtoffs[i] = gmtoffs[j]; gmtoffs[j] = t; }  
   { char t = isdsts[i]; isdsts[i] = isdsts[j]; isdsts[j] = t; }  
   { unsigned char t = abbrinds[i]; abbrinds[i] = abbrinds[j];  
     abbrinds[j] = t; }  
   { bool t = ttisstds[i]; ttisstds[i] = ttisstds[j]; ttisstds[j] = t; }  
   { bool t = ttisgmts[i]; ttisgmts[i] = ttisgmts[j]; ttisgmts[j] = t; }  
 }  
   
 struct timerange {  struct timerange {
   int defaulttype;    int defaulttype;
   ptrdiff_t base, count;    ptrdiff_t base, count;
Line 1874  writezone(const char *const name, const 
Line 1890  writezone(const char *const name, const 
                 toi = 0;                  toi = 0;
                 fromi = 0;                  fromi = 0;
                 for ( ; fromi < timecnt; ++fromi) {                  for ( ; fromi < timecnt; ++fromi) {
                         if (toi != 0 && ((attypes[fromi].at +                          if (toi != 0
                                 gmtoffs[attypes[toi - 1].type]) <=                              && ((attypes[fromi].at
                                 (attypes[toi - 1].at + gmtoffs[toi == 1 ? 0                                   + utoffs[attypes[toi - 1].type])
                                 : attypes[toi - 2].type]))) {                                  <= (attypes[toi - 1].at
                                       + utoffs[toi == 1 ? 0
                                                : attypes[toi - 2].type]))) {
                                         attypes[toi - 1].type =                                          attypes[toi - 1].type =
                                                 attypes[fromi].type;                                                  attypes[fromi].type;
                                         continue;                                          continue;
                         }                          }
                         if (toi == 0                          if (toi == 0
                             || attypes[fromi].dontmerge                              || attypes[fromi].dontmerge
                             || attypes[toi - 1].type != attypes[fromi].type)                              || (utoffs[attypes[toi - 1].type]
                                   != utoffs[attypes[fromi].type])
                               || (isdsts[attypes[toi - 1].type]
                                   != isdsts[attypes[fromi].type])
                               || (desigidx[attypes[toi - 1].type]
                                   != desigidx[attypes[fromi].type]))
                                         attypes[toi++] = attypes[fromi];                                          attypes[toi++] = attypes[fromi];
                 }                  }
                 timecnt = toi;                  timecnt = toi;
Line 1927  writezone(const char *const name, const 
Line 1950  writezone(const char *const name, const 
            seconds, as the idea is to insert a transition just before             seconds, as the idea is to insert a transition just before
            32-bit time_t rolls around, and this occurs at a slightly             32-bit time_t rolls around, and this occurs at a slightly
            different moment if transitions are leap-second corrected.  */             different moment if transitions are leap-second corrected.  */
         if (WORK_AROUND_QTBUG_53071 && timecnt != 0          if (WORK_AROUND_QTBUG_53071 && timecnt != 0 && want_bloat()
             && ats[timecnt - 1] < y2038_boundary - 1 && strchr(string, '<')) {              && ats[timecnt - 1] < y2038_boundary - 1 && strchr(string, '<')) {
           ats[timecnt] = y2038_boundary - 1;            ats[timecnt] = y2038_boundary - 1;
           types[timecnt] = types[timecnt - 1];            types[timecnt] = types[timecnt - 1];
Line 1976  writezone(const char *const name, const 
Line 1999  writezone(const char *const name, const 
                 int old0;                  int old0;
                 char            omittype[TZ_MAX_TYPES];                  char            omittype[TZ_MAX_TYPES];
                 int             typemap[TZ_MAX_TYPES];                  int             typemap[TZ_MAX_TYPES];
                 int     thistypecnt;                  int             thistypecnt, stdcnt, utcnt;
                 char            thischars[TZ_MAX_CHARS];                  char            thischars[TZ_MAX_CHARS];
                 int             thischarcnt;                  int             thischarcnt;
                 bool            toomanytimes;                  bool            toomanytimes;
Line 2048  writezone(const char *const name, const 
Line 2071  writezone(const char *const name, const 
                    THISDEFAULTTYPE appears as type 0 in the output instead                     THISDEFAULTTYPE appears as type 0 in the output instead
                    of OLD0.  TYPEMAP also omits unused types.  */                     of OLD0.  TYPEMAP also omits unused types.  */
                 old0 = strlen(omittype);                  old0 = strlen(omittype);
                 swaptypes(old0, thisdefaulttype);  
   
 #ifndef LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH  #ifndef LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH
                 /*                  /*
Line 2059  writezone(const char *const name, const 
Line 2081  writezone(const char *const name, const 
                 ** (to help get global "altzone" and "timezone" variables                  ** (to help get global "altzone" and "timezone" variables
                 ** set correctly).                  ** set correctly).
                 */                  */
                 {                  if (want_bloat()) {
                         int     mrudst, mrustd, hidst, histd, type;                          int     mrudst, mrustd, hidst, histd, type;
   
                         hidst = histd = mrudst = mrustd = -1;                          hidst = histd = mrudst = mrustd = -1;
Line 2067  writezone(const char *const name, const 
Line 2089  writezone(const char *const name, const 
                                 if (isdsts[types[i]])                                  if (isdsts[types[i]])
                                         mrudst = types[i];                                          mrudst = types[i];
                                 else    mrustd = types[i];                                  else    mrustd = types[i];
                         for (i = old0; i < typecnt; i++)                          for (i = old0; i < typecnt; i++) {
                                 if (!omittype[i]) {                            int h = (i == old0 ? thisdefaulttype
                                         if (isdsts[i])                                     : i == thisdefaulttype ? old0 : i);
                                                 hidst = i;                            if (!omittype[h]) {
                                         else    histd = i;                              if (isdsts[h])
                                 }                                hidst = i;
                               else
                                 histd = i;
                             }
                           }
                         if (hidst >= 0 && mrudst >= 0 && hidst != mrudst &&                          if (hidst >= 0 && mrudst >= 0 && hidst != mrudst &&
                                 gmtoffs[hidst] != gmtoffs[mrudst]) {                                  utoffs[hidst] != utoffs[mrudst]) {
                                         isdsts[mrudst] = -1;                                          isdsts[mrudst] = -1;
                                         type = addtype(gmtoffs[mrudst],                                          type = addtype(utoffs[mrudst],
                                                 &chars[abbrinds[mrudst]],                                                  &chars[desigidx[mrudst]],
                                                 true,                                                  true,
                                                 ttisstds[mrudst],                                                  ttisstds[mrudst],
                                                 ttisgmts[mrudst]);                                                  ttisuts[mrudst]);
                                         isdsts[mrudst] = 1;                                          isdsts[mrudst] = 1;
                                         omittype[type] = false;                                          omittype[type] = false;
                         }                          }
                         if (histd >= 0 && mrustd >= 0 && histd != mrustd &&                          if (histd >= 0 && mrustd >= 0 && histd != mrustd &&
                                 gmtoffs[histd] != gmtoffs[mrustd]) {                                  utoffs[histd] != utoffs[mrustd]) {
                                         isdsts[mrustd] = -1;                                          isdsts[mrustd] = -1;
                                         type = addtype(gmtoffs[mrustd],                                          type = addtype(utoffs[mrustd],
                                                 &chars[abbrinds[mrustd]],                                                  &chars[desigidx[mrustd]],
                                                 false,                                                  false,
                                                 ttisstds[mrustd],                                                  ttisstds[mrustd],
                                                 ttisgmts[mrustd]);                                                  ttisuts[mrustd]);
                                         isdsts[mrustd] = 0;                                          isdsts[mrustd] = 0;
                                         omittype[type] = true;                                          omittype[type] = false;
                         }                          }
                 }                  }
 #endif /* !defined LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH */  #endif /* !defined LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH */
Line 2106  writezone(const char *const name, const 
Line 2132  writezone(const char *const name, const 
   
                 for (i = 0; i < (int)(sizeof indmap / sizeof indmap[0]); ++i)                  for (i = 0; i < (int)(sizeof indmap / sizeof indmap[0]); ++i)
                         indmap[i] = -1;                          indmap[i] = -1;
                 thischarcnt = 0;                  thischarcnt = stdcnt = utcnt = 0;
                 for (i = old0; i < typecnt; i++) {                  for (i = old0; i < typecnt; i++) {
                         char *  thisabbr;                          char *  thisabbr;
   
                         if (omittype[i])                          if (omittype[i])
                                 continue;                                  continue;
                         if (indmap[abbrinds[i]] >= 0)                          if (ttisstds[i])
                             stdcnt = thistypecnt;
                           if (ttisuts[i])
                             utcnt = thistypecnt;
                           if (indmap[desigidx[i]] >= 0)
                                 continue;                                  continue;
                         thisabbr = &chars[abbrinds[i]];                          thisabbr = &chars[desigidx[i]];
                         for (j = 0; j < thischarcnt; ++j)                          for (j = 0; j < thischarcnt; ++j)
                                 if (strcmp(&thischars[j], thisabbr) == 0)                                  if (strcmp(&thischars[j], thisabbr) == 0)
                                         break;                                          break;
Line 2122  writezone(const char *const name, const 
Line 2152  writezone(const char *const name, const 
                                 strcpy(&thischars[thischarcnt], thisabbr);                                  strcpy(&thischars[thischarcnt], thisabbr);
                                 thischarcnt += strlen(thisabbr) + 1;                                  thischarcnt += strlen(thisabbr) + 1;
                         }                          }
                         indmap[abbrinds[i]] = j;                          indmap[desigidx[i]] = j;
                   }
                   if (pass == 1 && !want_bloat()) {
                     utcnt = stdcnt = thisleapcnt = 0;
                     thistimecnt = - locut - hicut;
                     thistypecnt = thischarcnt = 1;
                     thistimelim = thistimei;
                 }                  }
 #define DO(field)       fwrite(tzh.field, sizeof tzh.field, (size_t) 1, fp)  #define DO(field)       fwrite(tzh.field, sizeof tzh.field, (size_t) 1, fp)
                 tzh = tzh0;                  tzh = tzh0;
                 memcpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic);                  memcpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic);
                 tzh.tzh_version[0] = version;                  tzh.tzh_version[0] = version;
                 convert(thistypecnt, tzh.tzh_ttisgmtcnt);                  convert(utcnt, tzh.tzh_ttisutcnt);
                 convert(thistypecnt, tzh.tzh_ttisstdcnt);                  convert(stdcnt, tzh.tzh_ttisstdcnt);
                 convert(thisleapcnt, tzh.tzh_leapcnt);                  convert(thisleapcnt, tzh.tzh_leapcnt);
                 convert(locut + thistimecnt + hicut, tzh.tzh_timecnt);                  convert(locut + thistimecnt + hicut, tzh.tzh_timecnt);
                 convert(thistypecnt, tzh.tzh_typecnt);                  convert(thistypecnt, tzh.tzh_typecnt);
Line 2137  writezone(const char *const name, const 
Line 2173  writezone(const char *const name, const 
                 DO(tzh_magic);                  DO(tzh_magic);
                 DO(tzh_version);                  DO(tzh_version);
                 DO(tzh_reserved);                  DO(tzh_reserved);
                 DO(tzh_ttisgmtcnt);                  DO(tzh_ttisutcnt);
                 DO(tzh_ttisstdcnt);                  DO(tzh_ttisstdcnt);
                 DO(tzh_leapcnt);                  DO(tzh_leapcnt);
                 DO(tzh_timecnt);                  DO(tzh_timecnt);
                 DO(tzh_typecnt);                  DO(tzh_typecnt);
                 DO(tzh_charcnt);                  DO(tzh_charcnt);
 #undef DO  #undef DO
                   if (pass == 1 && !want_bloat()) {
                     /* Output a minimal data block with just one time type.  */
                     puttzcode(0, fp);     /* utoff */
                     putc(0, fp);          /* dst */
                     putc(0, fp);          /* index of abbreviation */
                     putc(0, fp);          /* empty-string abbreviation */
                     continue;
                   }
   
                 /* Output a LO_TIME transition if needed; see limitrange.                  /* Output a LO_TIME transition if needed; see limitrange.
                    But do not go below the minimum representable value                     But do not go below the minimum representable value
                    for this pass.  */                     for this pass.  */
Line 2167  writezone(const char *const name, const 
Line 2212  writezone(const char *const name, const 
                 if (hicut)                  if (hicut)
                   putc(currenttype, fp);                    putc(currenttype, fp);
   
                 for (i = old0; i < typecnt; i++)                  for (i = old0; i < typecnt; i++) {
                         if (!omittype[i]) {                    int h = (i == old0 ? thisdefaulttype
                                 puttzcode(gmtoffs[i], fp);                             : i == thisdefaulttype ? old0 : i);
                                 putc(isdsts[i], fp);                    if (!omittype[h]) {
                                 putc((unsigned char) indmap[abbrinds[i]], fp);                      puttzcode(utoffs[h], fp);
                         }                      putc(isdsts[h], fp);
                       putc(indmap[desigidx[h]], fp);
                     }
                   }
                 if (thischarcnt != 0)                  if (thischarcnt != 0)
                         fwrite(thischars, sizeof thischars[0],                          fwrite(thischars, sizeof thischars[0],
                                 (size_t) thischarcnt, fp);                                  (size_t) thischarcnt, fp);
Line 2194  writezone(const char *const name, const 
Line 2242  writezone(const char *const name, const 
                                                         ++j;                                                          ++j;
                                         j = types[j - 1];                                          j = types[j - 1];
                                 }                                  }
                                 todo = tadd(trans[i], -gmtoffs[j]);                                  todo = tadd(trans[i], -utoffs[j]);
                         } else  todo = trans[i];                          } else  todo = trans[i];
                         puttzcodepass(todo, fp, pass);                          puttzcodepass(todo, fp, pass);
                         puttzcode(corr[i], fp);                          puttzcode(corr[i], fp);
                 }                  }
                 for (i = old0; i < typecnt; i++)                  if (stdcnt != 0)
                     for (i = old0; i < typecnt; i++)
                         if (!omittype[i])                          if (!omittype[i])
                                 putc(ttisstds[i], fp);                                  putc(ttisstds[i], fp);
                 for (i = old0; i < typecnt; i++)                  if (utcnt != 0)
                     for (i = old0; i < typecnt; i++)
                         if (!omittype[i])                          if (!omittype[i])
                                 putc(ttisgmts[i], fp);                                  putc(ttisuts[i], fp);
                 swaptypes(old0, thisdefaulttype);  
         }          }
         fprintf(fp, "\n%s\n", string);          fprintf(fp, "\n%s\n", string);
         close_file(fp, directory, name);          close_file(fp, directory, name);
Line 2250  abbroffset(char *buf, zic_t offset)
Line 2299  abbroffset(char *buf, zic_t offset)
   
 static size_t  static size_t
 doabbr(char *abbr, int abbrlen, struct zone const *zp, const char *letters,  doabbr(char *abbr, int abbrlen, struct zone const *zp, const char *letters,
     bool isdst, zic_t stdoff, bool doquotes)      bool isdst, zic_t save, bool doquotes)
 {  {
         char *  cp;          char *  cp;
         char *  slashp;          char *  slashp;
Line 2261  doabbr(char *abbr, int abbrlen, struct z
Line 2310  doabbr(char *abbr, int abbrlen, struct z
         if (slashp == NULL) {          if (slashp == NULL) {
                 char letterbuf[PERCENT_Z_LEN_BOUND + 1];                  char letterbuf[PERCENT_Z_LEN_BOUND + 1];
                 if (zp->z_format_specifier == 'z')                  if (zp->z_format_specifier == 'z')
                         letters = abbroffset(letterbuf, zp->z_gmtoff + stdoff);                          letters = abbroffset(letterbuf, zp->z_stdoff + save);
                 else if (!letters)                  else if (!letters)
                         letters = "%s";                          letters = "%s";
                 snprintf(abbr, abbrlen, format, letters);                  snprintf(abbr, abbrlen, format, letters);
Line 2326  stringoffset(char *result, zic_t offset)
Line 2375  stringoffset(char *result, zic_t offset)
 }  }
   
 static int  static int
 stringrule(char *result, const struct rule *const rp, const zic_t dstoff,  stringrule(char *result, struct rule *const rp, zic_t save, const zic_t stdoff)
     const zic_t gmtoff)  
 {  {
         zic_t   tod = rp->r_tod;          zic_t   tod = rp->r_tod;
         int     compat = 0;          int     compat = 0;
Line 2374  stringrule(char *result, const struct ru
Line 2422  stringrule(char *result, const struct ru
                 result += sprintf(result, "M%d.%d.%d",                  result += sprintf(result, "M%d.%d.%d",
                                   rp->r_month + 1, week, wday);                                    rp->r_month + 1, week, wday);
         }          }
         if (rp->r_todisgmt)          if (rp->r_todisut)
                 tod += gmtoff;            tod += stdoff;
         if (rp->r_todisstd && !rp->r_isdst)          if (rp->r_todisstd && !rp->r_isdst)
                 tod += dstoff;            tod += save;
         if (tod != 2 * SECSPERMIN * MINSPERHOUR) {          if (tod != 2 * SECSPERMIN * MINSPERHOUR) {
                 *result++ = '/';                  *result++ = '/';
                 if (! stringoffset(result, tod))                  if (! stringoffset(result, tod))
Line 2407  rule_cmp(struct rule const *a, struct ru
Line 2455  rule_cmp(struct rule const *a, struct ru
         return a->r_dayofmonth - b->r_dayofmonth;          return a->r_dayofmonth - b->r_dayofmonth;
 }  }
   
 enum { YEAR_BY_YEAR_ZONE = 1 };  
   
 static int  static int
 stringzone(char *result, const int resultlen, const struct zone *const zpfirst,  stringzone(char *result, int resultlen, const struct zone *const zpfirst,
     const int zonecount)      const int zonecount)
 {  {
         const struct zone *     zp;          const struct zone *     zp;
Line 2464  stringzone(char *result, const int resul
Line 2510  stringzone(char *result, const int resul
                         if (rule_cmp(stdrp, rp) < 0)                          if (rule_cmp(stdrp, rp) < 0)
                                 stdrp = rp;                                  stdrp = rp;
                 }                  }
                 /*  
                 ** Horrid special case: if year is 2037,  
                 ** presume this is a zone handled on a year-by-year basis;  
                 ** do not try to apply a rule to the zone.  
                 */  
                 if (stdrp != NULL && stdrp->r_hiyear == 2037)  
                         return YEAR_BY_YEAR_ZONE;  
   
                 if (stdrp != NULL && stdrp->r_isdst) {                  if (stdrp != NULL && stdrp->r_isdst) {
                         /* Perpetual DST.  */                          /* Perpetual DST.  */
                         dstr.r_month = TM_JANUARY;                          dstr.r_month = TM_JANUARY;
                         dstr.r_dycode = DC_DOM;                          dstr.r_dycode = DC_DOM;
                         dstr.r_dayofmonth = 1;                          dstr.r_dayofmonth = 1;
                         dstr.r_tod = 0;                          dstr.r_tod = 0;
                         dstr.r_todisstd = dstr.r_todisgmt = false;                          dstr.r_todisstd = dstr.r_todisut = false;
                         dstr.r_isdst = stdrp->r_isdst;                          dstr.r_isdst = stdrp->r_isdst;
                         dstr.r_stdoff = stdrp->r_stdoff;                          dstr.r_save = stdrp->r_save;
                         dstr.r_abbrvar = stdrp->r_abbrvar;                          dstr.r_abbrvar = stdrp->r_abbrvar;
                         stdr.r_month = TM_DECEMBER;                          stdr.r_month = TM_DECEMBER;
                         stdr.r_dycode = DC_DOM;                          stdr.r_dycode = DC_DOM;
                         stdr.r_dayofmonth = 31;                          stdr.r_dayofmonth = 31;
                         stdr.r_tod = SECSPERDAY + stdrp->r_stdoff;                          stdr.r_tod = SECSPERDAY + stdrp->r_save;
                         stdr.r_todisstd = stdr.r_todisgmt = false;                          stdr.r_todisstd = stdr.r_todisut = false;
                         stdr.r_isdst = false;                          stdr.r_isdst = false;
                         stdr.r_stdoff = 0;                          stdr.r_save = 0;
                         stdr.r_abbrvar                          stdr.r_abbrvar
                           = (stdabbrrp ? stdabbrrp->r_abbrvar : "");                            = (stdabbrrp ? stdabbrrp->r_abbrvar : "");
                         dstrp = &dstr;                          dstrp = &dstr;
Line 2499  stringzone(char *result, const int resul
Line 2537  stringzone(char *result, const int resul
                 return -1;                  return -1;
         abbrvar = (stdrp == NULL) ? "" : stdrp->r_abbrvar;          abbrvar = (stdrp == NULL) ? "" : stdrp->r_abbrvar;
         len = doabbr(result, resultlen, zp, abbrvar, false, 0, true);          len = doabbr(result, resultlen, zp, abbrvar, false, 0, true);
         offsetlen = stringoffset(result + len, -zp->z_gmtoff);          offsetlen = stringoffset(result + len, -zp->z_stdoff);
         if (! offsetlen) {          if (! offsetlen) {
                 result[0] = '\0';                  result[0] = '\0';
                 return -1;                  return -1;
Line 2508  stringzone(char *result, const int resul
Line 2546  stringzone(char *result, const int resul
         if (dstrp == NULL)          if (dstrp == NULL)
                 return compat;                  return compat;
         len += doabbr(result + len, resultlen - len, zp, dstrp->r_abbrvar,          len += doabbr(result + len, resultlen - len, zp, dstrp->r_abbrvar,
                       dstrp->r_isdst, dstrp->r_stdoff, true);                        dstrp->r_isdst, dstrp->r_save, true);
         if (dstrp->r_stdoff != SECSPERMIN * MINSPERHOUR) {          if (dstrp->r_save != SECSPERMIN * MINSPERHOUR) {
                 offsetlen = stringoffset(result + len,                  offsetlen = stringoffset(result + len,
                     -(zp->z_gmtoff + dstrp->r_stdoff));                     - (zp->z_stdoff + dstrp->r_save));
                 if (! offsetlen) {                  if (! offsetlen) {
                         result[0] = '\0';                          result[0] = '\0';
                         return -1;                          return -1;
Line 2519  stringzone(char *result, const int resul
Line 2557  stringzone(char *result, const int resul
                 len += offsetlen;                  len += offsetlen;
         }          }
         result[len++] = ',';          result[len++] = ',';
         c = stringrule(result + len, dstrp, dstrp->r_stdoff, zp->z_gmtoff);          c = stringrule(result + len, dstrp, dstrp->r_save, zp->z_stdoff);
         if (c < 0) {          if (c < 0) {
                 result[0] = '\0';                  result[0] = '\0';
                 return -1;                  return -1;
Line 2528  stringzone(char *result, const int resul
Line 2566  stringzone(char *result, const int resul
                 compat = c;                  compat = c;
         len += strlen(result + len);          len += strlen(result + len);
         result[len++] = ',';          result[len++] = ',';
         c = stringrule(result + len, stdrp, dstrp->r_stdoff, zp->z_gmtoff);          c = stringrule(result + len, stdrp, dstrp->r_save, zp->z_stdoff);
         if (c < 0) {          if (c < 0) {
                 result[0] = '\0';                  result[0] = '\0';
                 return -1;                  return -1;
Line 2546  outzone(const struct zone *zpfirst, ptrd
Line 2584  outzone(const struct zone *zpfirst, ptrd
         ptrdiff_t               i, j;          ptrdiff_t               i, j;
         bool                    usestart, useuntil;          bool                    usestart, useuntil;
         zic_t                   starttime, untiltime;          zic_t                   starttime, untiltime;
         zic_t                   gmtoff;  
         zic_t                   stdoff;          zic_t                   stdoff;
           zic_t                   save;
         zic_t                   year;          zic_t                   year;
         zic_t                   startoff;          zic_t                   startoff;
         bool                    startttisstd;          bool                    startttisstd;
         bool                    startttisgmt;          bool                    startttisut;
         int                     type;          int                     type;
         char *                  startbuf;          char *                  startbuf;
         char *                  ab;          char *                  ab;
Line 2561  outzone(const struct zone *zpfirst, ptrd
Line 2599  outzone(const struct zone *zpfirst, ptrd
         bool                    prodstic; /* all rules are min to max */          bool                    prodstic; /* all rules are min to max */
         int                     compat;          int                     compat;
         bool                    do_extend;          bool                    do_extend;
         int                     version;          char                    version;
         ptrdiff_t lastatmax = -1;          ptrdiff_t lastatmax = -1;
         zic_t one = 1;          zic_t one = 1;
         zic_t y2038_boundary = one << 31;          zic_t y2038_boundary = one << 31;
Line 2587  outzone(const struct zone *zpfirst, ptrd
Line 2625  outzone(const struct zone *zpfirst, ptrd
         ** for noting the need to unconditionally initialize startttisstd.          ** for noting the need to unconditionally initialize startttisstd.
         */          */
         startttisstd = false;          startttisstd = false;
         startttisgmt = false;          startttisut = false;
         min_year = max_year = EPOCH_YEAR;          min_year = max_year = EPOCH_YEAR;
         if (leapseen) {          if (leapseen) {
                 updateminmax(leapminyear);                  updateminmax(leapminyear);
Line 2612  outzone(const struct zone *zpfirst, ptrd
Line 2650  outzone(const struct zone *zpfirst, ptrd
         */          */
         compat = stringzone(envvar, max_envvar_len + 1, zpfirst, zonecount);          compat = stringzone(envvar, max_envvar_len + 1, zpfirst, zonecount);
         version = compat < 2013 ? ZIC_VERSION_PRE_2013 : ZIC_VERSION;          version = compat < 2013 ? ZIC_VERSION_PRE_2013 : ZIC_VERSION;
         do_extend = compat < 0 || compat == YEAR_BY_YEAR_ZONE;          do_extend = compat < 0;
         if (noise) {          if (noise) {
                 if (!*envvar)                  if (!*envvar)
                         warning("%s %s",                          warning("%s %s",
                                 _("no POSIX environment variable for zone"),                                  _("no POSIX environment variable for zone"),
                                 zpfirst->z_name);                                  zpfirst->z_name);
                 else if (compat != 0 && compat != YEAR_BY_YEAR_ZONE) {                  else if (compat != 0) {
                         /* Circa-COMPAT clients, and earlier clients, might                          /* Circa-COMPAT clients, and earlier clients, might
                            not work for this zone when given dates before                             not work for this zone when given dates before
                            1970 or after 2038.  */                             1970 or after 2038.  */
Line 2660  outzone(const struct zone *zpfirst, ptrd
Line 2698  outzone(const struct zone *zpfirst, ptrd
                         max_year = min_year + years_of_observations;                          max_year = min_year + years_of_observations;
                 }                  }
         }          }
         /*  
         ** For the benefit of older systems,  
         ** generate data from 1900 through 2038.  
         */  
         if (min_year > 1900)  
                 min_year = 1900;  
         max_year0 = max_year;          max_year0 = max_year;
         if (max_year < 2038)          if (want_bloat()) {
             /* For the benefit of older systems,
                generate data from 1900 through 2038.  */
             if (min_year > 1900)
                   min_year = 1900;
             if (max_year < 2038)
                 max_year = 2038;                  max_year = 2038;
           }
   
         for (i = 0; i < zonecount; ++i) {          for (i = 0; i < zonecount; ++i) {
                   struct rule *prevrp = NULL;
                 /*                  /*
                 ** A guess that may well be corrected later.                  ** A guess that may well be corrected later.
                 */                  */
                 stdoff = 0;                  save = 0;
                 zp = &zpfirst[i];                  zp = &zpfirst[i];
                 usestart = i > 0 && (zp - 1)->z_untiltime > min_time;                  usestart = i > 0 && (zp - 1)->z_untiltime > min_time;
                 useuntil = i < (zonecount - 1);                  useuntil = i < (zonecount - 1);
                 if (useuntil && zp->z_untiltime <= min_time)                  if (useuntil && zp->z_untiltime <= min_time)
                         continue;                          continue;
                 gmtoff = zp->z_gmtoff;                  stdoff = zp->z_stdoff;
                 eat(zp->z_filename, zp->z_linenum);                  eat(zp->z_filename, zp->z_linenum);
                 *startbuf = '\0';                  *startbuf = '\0';
                 startoff = zp->z_gmtoff;                  startoff = zp->z_stdoff;
                 if (zp->z_nrules == 0) {                  if (zp->z_nrules == 0) {
                         stdoff = zp->z_stdoff;                          save = zp->z_save;
                         doabbr(startbuf, max_abbr_len + 1, zp,                          doabbr(startbuf, max_abbr_len + 1,
                             NULL, zp->z_isdst, stdoff, false);                              zp, NULL, zp->z_isdst, save, false);
                         type = addtype(oadd(zp->z_gmtoff, stdoff),                          type = addtype(oadd(zp->z_stdoff, save),
                                 startbuf, zp->z_isdst, startttisstd,                                  startbuf, zp->z_isdst, startttisstd,
                                 startttisgmt);                                  startttisut);
                         if (usestart) {                          if (usestart) {
                                 addtt(starttime, type);                                  addtt(starttime, type);
                                 usestart = false;                                  usestart = false;
Line 2725  outzone(const struct zone *zpfirst, ptrd
Line 2765  outzone(const struct zone *zpfirst, ptrd
                                 if (useuntil) {                                  if (useuntil) {
                                         /*                                          /*
                                         ** Turn untiltime into UT                                          ** Turn untiltime into UT
                                         ** assuming the current gmtoff and                                          ** assuming the current stdoff and
                                         ** stdoff values.                                          ** save values.
                                         */                                          */
                                         untiltime = zp->z_untiltime;                                          untiltime = zp->z_untiltime;
                                         if (!zp->z_untilrule.r_todisgmt)                                          if (!zp->z_untilrule.r_todisut)
                                                 untiltime = tadd(untiltime,                                                  untiltime = tadd(untiltime,
                                                         -gmtoff);                                                                   -stdoff);
                                         if (!zp->z_untilrule.r_todisstd)                                          if (!zp->z_untilrule.r_todisstd)
                                                 untiltime = tadd(untiltime,                                                  untiltime = tadd(untiltime,
                                                         -stdoff);                                                                   -save);
                                 }                                  }
                                 /*                                  /*
                                 ** Find the rule (of those to do, if any)                                  ** Find the rule (of those to do, if any)
Line 2747  outzone(const struct zone *zpfirst, ptrd
Line 2787  outzone(const struct zone *zpfirst, ptrd
                                                 continue;                                                  continue;
                                         eats(zp->z_filename, zp->z_linenum,                                          eats(zp->z_filename, zp->z_linenum,
                                                 rp->r_filename, rp->r_linenum);                                                  rp->r_filename, rp->r_linenum);
                                         offset = rp->r_todisgmt ? 0 : gmtoff;                                          offset = rp->r_todisut ? 0 : stdoff;
                                         if (!rp->r_todisstd)                                          if (!rp->r_todisstd)
                                                 offset = oadd(offset, stdoff);                                                  offset = oadd(offset, save);
                                         jtime = rp->r_temp;                                          jtime = rp->r_temp;
                                         if (jtime == min_time ||                                          if (jtime == min_time ||
                                                 jtime == max_time)                                                  jtime == max_time)
Line 2776  outzone(const struct zone *zpfirst, ptrd
Line 2816  outzone(const struct zone *zpfirst, ptrd
                                 rp->r_todo = false;                                  rp->r_todo = false;
                                 if (useuntil && ktime >= untiltime)                                  if (useuntil && ktime >= untiltime)
                                         break;                                          break;
                                 stdoff = rp->r_stdoff;                                  save = rp->r_save;
                                 if (usestart && ktime == starttime)                                  if (usestart && ktime == starttime)
                                         usestart = false;                                          usestart = false;
                                 if (usestart) {                                  if (usestart) {
                                         if (ktime < starttime) {                                          if (ktime < starttime) {
                                                 startoff = oadd(zp->z_gmtoff,                                                  startoff = oadd(zp->z_stdoff,
                                                         stdoff);                                                                  save);
                                                 doabbr(startbuf,                                                  doabbr(startbuf,
                                                         max_abbr_len + 1,                                                          max_abbr_len + 1,
                                                         zp,                                                          zp,
                                                         rp->r_abbrvar,                                                          rp->r_abbrvar,
                                                         rp->r_isdst,                                                          rp->r_isdst,
                                                         rp->r_stdoff,                                                          rp->r_save,
                                                         false);                                                          false);
                                                 continue;                                                  continue;
                                         }                                          }
                                         if (*startbuf == '\0' &&                                          if (*startbuf == '\0'
                                                 startoff == oadd(zp->z_gmtoff,                                              && startoff == oadd(zp->z_stdoff,
                                                 stdoff)) {                                                                  save)) {
                                                         doabbr(startbuf,                                                          doabbr(startbuf,
                                                                 max_abbr_len + 1,                                                                  max_abbr_len + 1,
                                                                 zp,                                                                  zp,
                                                                 rp->r_abbrvar,                                                                  rp->r_abbrvar,
                                                                 rp->r_isdst,                                                                  rp->r_isdst,
                                                                 rp->r_stdoff,                                                                  rp->r_save,
                                                                 false);                                                                  false);
                                         }                                          }
                                 }                                  }
                                 eats(zp->z_filename, zp->z_linenum,                                  eats(zp->z_filename, zp->z_linenum,
                                         rp->r_filename, rp->r_linenum);                                          rp->r_filename, rp->r_linenum);
                                 doabbr(ab, max_abbr_len + 1, zp, rp->r_abbrvar,                                  doabbr(ab, max_abbr_len + 1, zp, rp->r_abbrvar,
                                        rp->r_isdst, rp->r_stdoff, false);                                         rp->r_isdst, rp->r_save, false);
                                 offset = oadd(zp->z_gmtoff, rp->r_stdoff);                                  offset = oadd(zp->z_stdoff, rp->r_save);
                                   if (!want_bloat() && !useuntil && !do_extend
                                       && prevrp
                                       && rp->r_hiyear == ZIC_MAX
                                       && prevrp->r_hiyear == ZIC_MAX)
                                     break;
                                 type = addtype(offset, ab, rp->r_isdst,                                  type = addtype(offset, ab, rp->r_isdst,
                                         rp->r_todisstd, rp->r_todisgmt);                                          rp->r_todisstd, rp->r_todisut);
                                 if (defaulttype < 0 && !rp->r_isdst)                                  if (defaulttype < 0 && !rp->r_isdst)
                                   defaulttype = type;                                    defaulttype = type;
                                 if (rp->r_hiyear == ZIC_MAX                                  if (rp->r_hiyear == ZIC_MAX
Line 2818  outzone(const struct zone *zpfirst, ptrd
Line 2863  outzone(const struct zone *zpfirst, ptrd
                                           && ktime < attypes[lastatmax].at))                                            && ktime < attypes[lastatmax].at))
                                   lastatmax = timecnt;                                    lastatmax = timecnt;
                                 addtt(ktime, type);                                  addtt(ktime, type);
                                   prevrp = rp;
                         }                          }
                 }                  }
                 if (usestart) {                  if (usestart) {
Line 2831  outzone(const struct zone *zpfirst, ptrd
Line 2877  outzone(const struct zone *zpfirst, ptrd
                         if (*startbuf == '\0')                          if (*startbuf == '\0')
 error(_("can't determine time zone abbreviation to use just after until time"));  error(_("can't determine time zone abbreviation to use just after until time"));
                         else {                          else {
                           bool isdst = startoff != zp->z_gmtoff;                            bool isdst = startoff != zp->z_stdoff;
                           type = addtype(startoff, startbuf, isdst,                            type = addtype(startoff, startbuf, isdst,
                                          startttisstd, startttisgmt);                                           startttisstd, startttisut);
                           if (defaulttype < 0 && !isdst)                            if (defaulttype < 0 && !isdst)
                             defaulttype = type;                              defaulttype = type;
                           addtt(starttime, type);                            addtt(starttime, type);
Line 2844  error(_("can't determine time zone abbre
Line 2890  error(_("can't determine time zone abbre
                 */                  */
                 if (useuntil) {                  if (useuntil) {
                         startttisstd = zp->z_untilrule.r_todisstd;                          startttisstd = zp->z_untilrule.r_todisstd;
                         startttisgmt = zp->z_untilrule.r_todisgmt;                          startttisut = zp->z_untilrule.r_todisut;
                         starttime = zp->z_untiltime;                          starttime = zp->z_untiltime;
                         if (!startttisstd)                          if (!startttisstd)
                                 starttime = tadd(starttime, -stdoff);                            starttime = tadd(starttime, -save);
                         if (!startttisgmt)                          if (!startttisut)
                                 starttime = tadd(starttime, -gmtoff);                            starttime = tadd(starttime, -stdoff);
                 }                  }
         }          }
         if (defaulttype < 0)          if (defaulttype < 0)
Line 2900  addtt(zic_t starttime, int type)
Line 2946  addtt(zic_t starttime, int type)
 }  }
   
 static int  static int
 addtype(zic_t gmtoff, char const *abbr, bool isdst, bool ttisstd, bool ttisgmt)  addtype(zic_t utoff, char const *abbr, bool isdst, bool ttisstd, bool ttisut)
 {  {
         int     i, j;          int     i, j;
   
         /*          if (! (-1L - 2147483647L <= utoff && utoff <= 2147483647L)) {
         ** See if there's already an entry for this zone type.                  error(_("UT offset out of range"));
         ** If so, just return its index.                  exit(EXIT_FAILURE);
         */          }
         for (i = 0; i < typecnt; ++i) {          if (!want_bloat())
                 if (gmtoff == gmtoffs[i] && isdst == isdsts[i] &&            ttisstd = ttisut = false;
                         strcmp(abbr, &chars[abbrinds[i]]) == 0 &&  
                         ttisstd == ttisstds[i] &&          for (j = 0; j < charcnt; ++j)
                         ttisgmt == ttisgmts[i])                  if (strcmp(&chars[j], abbr) == 0)
                                 return i;                          break;
           if (j == charcnt)
                   newabbr(abbr);
           else {
             /* If there's already an entry, return its index.  */
             for (i = 0; i < typecnt; i++)
               if (utoff == utoffs[i] && isdst == isdsts[i] && j == desigidx[i]
                   && ttisstd == ttisstds[i] && ttisut == ttisuts[i])
                 return i;
         }          }
         /*          /*
         ** There isn't one; add a new one, unless there are already too          ** There isn't one; add a new one, unless there are already too
Line 2923  addtype(zic_t gmtoff, char const *abbr, 
Line 2977  addtype(zic_t gmtoff, char const *abbr, 
                 error(_("too many local time types"));                  error(_("too many local time types"));
                 exit(EXIT_FAILURE);                  exit(EXIT_FAILURE);
         }          }
         if (! (-1L - 2147483647L <= gmtoff && gmtoff <= 2147483647L)) {          i = typecnt++;
                 error(_("UT offset out of range"));          utoffs[i] = utoff;
                 exit(EXIT_FAILURE);  
         }  
         gmtoffs[i] = gmtoff;  
         isdsts[i] = isdst;          isdsts[i] = isdst;
         ttisstds[i] = ttisstd;          ttisstds[i] = ttisstd;
         ttisgmts[i] = ttisgmt;          ttisuts[i] = ttisut;
           desigidx[i] = j;
         for (j = 0; j < charcnt; ++j)  
                 if (strcmp(&chars[j], abbr) == 0)  
                         break;  
         if (j == charcnt)  
                 newabbr(abbr);  
         abbrinds[i] = j;  
         ++typecnt;  
         return i;          return i;
 }  }
   
Line 3159  byword(const char *word, const struct lo
Line 3203  byword(const char *word, const struct lo
                         else    return NULL;    /* multiple inexact matches */                          else    return NULL;    /* multiple inexact matches */
                 }                  }
   
         /* Warn about any backward-compatibility issue with pre-2017c zic.  */          if (foundlp && noise) {
         if (foundlp) {            /* Warn about any backward-compatibility issue with pre-2017c zic.  */
           bool pre_2017c_match = false;            bool pre_2017c_match = false;
           for (lp = table; lp->l_word; lp++)            for (lp = table; lp->l_word; lp++)
             if (itsabbr(word, lp->l_word)) {              if (itsabbr(word, lp->l_word)) {

Legend:
Removed from v.1.74  
changed lines
  Added in v.1.75

CVSweb <webmaster@jp.NetBSD.org>