Annotation of 43BSDReno/share/zoneinfo/zic.c, revision 1.1

1.1     ! root        1: #ifndef lint
        !             2: #ifndef NOID
        !             3: static char    elsieid[] = "@(#)zic.c  4.12";
        !             4: #endif /* !defined NOID */
        !             5: #endif /* !defined lint */
        !             6: 
        !             7: #include "stdio.h"
        !             8: #include "tzfile.h"
        !             9: #include "ctype.h"
        !            10: #include "time.h"
        !            11: #include "string.h"
        !            12: #include "stdlib.h"
        !            13: #include "sys/stat.h"
        !            14: #include "nonstd.h"
        !            15: 
        !            16: #ifndef TRUE
        !            17: #define TRUE   1
        !            18: #define FALSE  0
        !            19: #endif /* !defined TRUE */
        !            20: 
        !            21: struct rule {
        !            22:        const char *    r_filename;
        !            23:        int             r_linenum;
        !            24:        const char *    r_name;
        !            25: 
        !            26:        int             r_loyear;       /* for example, 1986 */
        !            27:        int             r_hiyear;       /* for example, 1986 */
        !            28:        const char *    r_yrtype;
        !            29: 
        !            30:        int             r_month;        /* 0..11 */
        !            31: 
        !            32:        int             r_dycode;       /* see below */
        !            33:        int             r_dayofmonth;
        !            34:        int             r_wday;
        !            35: 
        !            36:        long            r_tod;          /* time from midnight */
        !            37:        int             r_todisstd;     /* above is standard time if TRUE */
        !            38:                                        /* or wall clock time if FALSE */
        !            39:        long            r_stdoff;       /* offset from standard time */
        !            40:        const char *    r_abbrvar;      /* variable part of abbreviation */
        !            41: 
        !            42:        int             r_todo;         /* a rule to do (used in outzone) */
        !            43:        time_t          r_temp;         /* used in outzone */
        !            44: };
        !            45: 
        !            46: /*
        !            47: **     r_dycode                r_dayofmonth    r_wday
        !            48: */
        !            49: 
        !            50: #define DC_DOM         0       /* 1..31 */     /* unused */
        !            51: #define DC_DOWGEQ      1       /* 1..31 */     /* 0..6 (Sun..Sat) */
        !            52: #define DC_DOWLEQ      2       /* 1..31 */     /* 0..6 (Sun..Sat) */
        !            53: 
        !            54: struct zone {
        !            55:        const char *    z_filename;
        !            56:        int             z_linenum;
        !            57: 
        !            58:        const char *    z_name;
        !            59:        long            z_gmtoff;
        !            60:        const char *    z_rule;
        !            61:        const char *    z_format;
        !            62: 
        !            63:        long            z_stdoff;
        !            64: 
        !            65:        struct rule *   z_rules;
        !            66:        int             z_nrules;
        !            67: 
        !            68:        struct rule     z_untilrule;
        !            69:        time_t          z_untiltime;
        !            70: };
        !            71: 
        !            72: extern int     emkdir P((const char * name, int mode));
        !            73: extern int     getopt P((int argc, char * argv[], const char * options));
        !            74: extern char *  icatalloc P((char * old, const char * new));
        !            75: extern char *  icpyalloc P((const char * string));
        !            76: extern void    ifree P((char * p));
        !            77: extern char *  imalloc P((int n));
        !            78: extern char *  irealloc P((char * old, int n));
        !            79: extern int     link P((const char * fromname, const char * toname));
        !            80: extern char *  optarg;
        !            81: extern int     optind;
        !            82: extern void    perror P((const char * string));
        !            83: extern char *  scheck P((const char * string, const char * format));
        !            84: 
        !            85: static void    addtt P((time_t starttime, int type));
        !            86: static int     addtype P((long gmtoff, const char * abbr, int isdst,
        !            87:     int ttisstd));
        !            88: static void    addleap P((time_t t, int positive, int rolling));
        !            89: static void    adjleap P((void));
        !            90: static void    associate P((void));
        !            91: static int     ciequal P((const char * ap, const char * bp));
        !            92: static void    convert P((long val, char * buf));
        !            93: static void    dolink P((const char * fromfile, const char * tofile));
        !            94: static void    eat P((const char * name, int num));
        !            95: static void    eats P((const char * name, int num,
        !            96:                        const char * rname, int rnum));
        !            97: static long    eitol P((int i));
        !            98: static void    error P((const char * message));
        !            99: static char ** getfields P((char * buf));
        !           100: static long    gethms P((const char * string, const char * errstrng,
        !           101:                        int signable));
        !           102: static void    infile P((const char * filename));
        !           103: static void    inleap P((char ** fields, int nfields));
        !           104: static void    inlink P((char ** fields, int nfields));
        !           105: static void    inrule P((char ** fields, int nfields));
        !           106: static int     inzcont P((char ** fields, int nfields));
        !           107: static int     inzone P((char ** fields, int nfields));
        !           108: static int     inzsub P((char ** fields, int nfields, int iscont));
        !           109: static int     itsabbr P((const char * abbr, const char * word));
        !           110: static int     itsdir P((const char * name));
        !           111: static int     lowerit P((int c));
        !           112: static char *  memcheck P((char * tocheck));
        !           113: static int     mkdirs P((char * filename));
        !           114: static void    newabbr P((const char * abbr));
        !           115: static long    oadd P((long t1, long t2));
        !           116: static void    outzone P((const struct zone * zp, int ntzones));
        !           117: static void    puttzcode P((long code, FILE * fp));
        !           118: static int     rcomp P((const genericptr_t leftp, const genericptr_t rightp));
        !           119: static time_t  rpytime P((const struct rule * rp, int wantedy));
        !           120: static void    rulesub P((struct rule * rp,
        !           121:                        char * loyearp, char * hiyearp,
        !           122:                        char * typep, char * monthp,
        !           123:                        char * dayp, char * timep));
        !           124: static void    setboundaries P((void));
        !           125: static time_t  tadd P((time_t t1, long t2));
        !           126: static void    usage P((void));
        !           127: static void    writezone P((const char * name));
        !           128: static int     yearistype P((int year, const char * type));
        !           129: 
        !           130: static int             charcnt;
        !           131: static int             errors;
        !           132: static const char *    filename;
        !           133: static int             leapcnt;
        !           134: static int             linenum;
        !           135: static time_t          max_time;
        !           136: static int             max_year;
        !           137: static time_t          min_time;
        !           138: static int             min_year;
        !           139: static int             noise;
        !           140: static const char *    rfilename;
        !           141: static int             rlinenum;
        !           142: static const char *    progname;
        !           143: static int             timecnt;
        !           144: static int             typecnt;
        !           145: static int             tt_signed;
        !           146: 
        !           147: /*
        !           148: ** Line codes.
        !           149: */
        !           150: 
        !           151: #define LC_RULE                0
        !           152: #define LC_ZONE                1
        !           153: #define LC_LINK                2
        !           154: #define LC_LEAP                3
        !           155: 
        !           156: /*
        !           157: ** Which fields are which on a Zone line.
        !           158: */
        !           159: 
        !           160: #define ZF_NAME                1
        !           161: #define ZF_GMTOFF      2
        !           162: #define ZF_RULE                3
        !           163: #define ZF_FORMAT      4
        !           164: #define ZF_TILYEAR     5
        !           165: #define ZF_TILMONTH    6
        !           166: #define ZF_TILDAY      7
        !           167: #define ZF_TILTIME     8
        !           168: #define ZONE_MINFIELDS 5
        !           169: #define ZONE_MAXFIELDS 9
        !           170: 
        !           171: /*
        !           172: ** Which fields are which on a Zone continuation line.
        !           173: */
        !           174: 
        !           175: #define ZFC_GMTOFF     0
        !           176: #define ZFC_RULE       1
        !           177: #define ZFC_FORMAT     2
        !           178: #define ZFC_TILYEAR    3
        !           179: #define ZFC_TILMONTH   4
        !           180: #define ZFC_TILDAY     5
        !           181: #define ZFC_TILTIME    6
        !           182: #define ZONEC_MINFIELDS        3
        !           183: #define ZONEC_MAXFIELDS        7
        !           184: 
        !           185: /*
        !           186: ** Which files are which on a Rule line.
        !           187: */
        !           188: 
        !           189: #define RF_NAME                1
        !           190: #define RF_LOYEAR      2
        !           191: #define RF_HIYEAR      3
        !           192: #define RF_COMMAND     4
        !           193: #define RF_MONTH       5
        !           194: #define RF_DAY         6
        !           195: #define RF_TOD         7
        !           196: #define RF_STDOFF      8
        !           197: #define RF_ABBRVAR     9
        !           198: #define RULE_FIELDS    10
        !           199: 
        !           200: /*
        !           201: ** Which fields are which on a Link line.
        !           202: */
        !           203: 
        !           204: #define LF_FROM                1
        !           205: #define LF_TO          2
        !           206: #define LINK_FIELDS    3
        !           207: 
        !           208: /*
        !           209: ** Which fields are which on a Leap line.
        !           210: */
        !           211: 
        !           212: #define LP_YEAR                1
        !           213: #define LP_MONTH       2
        !           214: #define LP_DAY         3
        !           215: #define LP_TIME                4
        !           216: #define LP_CORR                5
        !           217: #define LP_ROLL                6
        !           218: #define LEAP_FIELDS    7
        !           219: 
        !           220: /*
        !           221: ** Year synonyms.
        !           222: */
        !           223: 
        !           224: #define YR_MINIMUM     0
        !           225: #define YR_MAXIMUM     1
        !           226: #define YR_ONLY                2
        !           227: 
        !           228: static struct rule *   rules;
        !           229: static int             nrules; /* number of rules */
        !           230: 
        !           231: static struct zone *   zones;
        !           232: static int             nzones; /* number of zones */
        !           233: 
        !           234: struct link {
        !           235:        const char *    l_filename;
        !           236:        int             l_linenum;
        !           237:        const char *    l_from;
        !           238:        const char *    l_to;
        !           239: };
        !           240: 
        !           241: static struct link *   links;
        !           242: static int             nlinks;
        !           243: 
        !           244: struct lookup {
        !           245:        const char *    l_word;
        !           246:        const int       l_value;
        !           247: };
        !           248: 
        !           249: static struct lookup const *   byword P((const char * string,
        !           250:                                        const struct lookup * lp));
        !           251: 
        !           252: static struct lookup const     line_codes[] = {
        !           253:        "Rule",         LC_RULE,
        !           254:        "Zone",         LC_ZONE,
        !           255:        "Link",         LC_LINK,
        !           256:        "Leap",         LC_LEAP,
        !           257:        NULL,           0
        !           258: };
        !           259: 
        !           260: static struct lookup const     mon_names[] = {
        !           261:        "January",      TM_JANUARY,
        !           262:        "February",     TM_FEBRUARY,
        !           263:        "March",        TM_MARCH,
        !           264:        "April",        TM_APRIL,
        !           265:        "May",          TM_MAY,
        !           266:        "June",         TM_JUNE,
        !           267:        "July",         TM_JULY,
        !           268:        "August",       TM_AUGUST,
        !           269:        "September",    TM_SEPTEMBER,
        !           270:        "October",      TM_OCTOBER,
        !           271:        "November",     TM_NOVEMBER,
        !           272:        "December",     TM_DECEMBER,
        !           273:        NULL,           0
        !           274: };
        !           275: 
        !           276: static struct lookup const     wday_names[] = {
        !           277:        "Sunday",       TM_SUNDAY,
        !           278:        "Monday",       TM_MONDAY,
        !           279:        "Tuesday",      TM_TUESDAY,
        !           280:        "Wednesday",    TM_WEDNESDAY,
        !           281:        "Thursday",     TM_THURSDAY,
        !           282:        "Friday",       TM_FRIDAY,
        !           283:        "Saturday",     TM_SATURDAY,
        !           284:        NULL,           0
        !           285: };
        !           286: 
        !           287: static struct lookup const     lasts[] = {
        !           288:        "last-Sunday",          TM_SUNDAY,
        !           289:        "last-Monday",          TM_MONDAY,
        !           290:        "last-Tuesday",         TM_TUESDAY,
        !           291:        "last-Wednesday",       TM_WEDNESDAY,
        !           292:        "last-Thursday",        TM_THURSDAY,
        !           293:        "last-Friday",          TM_FRIDAY,
        !           294:        "last-Saturday",        TM_SATURDAY,
        !           295:        NULL,                   0
        !           296: };
        !           297: 
        !           298: static struct lookup const     begin_years[] = {
        !           299:        "minimum",              YR_MINIMUM,
        !           300:        "maximum",              YR_MAXIMUM,
        !           301:        NULL,                   0
        !           302: };
        !           303: 
        !           304: static struct lookup const     end_years[] = {
        !           305:        "minimum",              YR_MINIMUM,
        !           306:        "maximum",              YR_MAXIMUM,
        !           307:        "only",                 YR_ONLY,
        !           308:        NULL,                   0
        !           309: };
        !           310: 
        !           311: static struct lookup const     leap_types[] = {
        !           312:        "Rolling",              TRUE,
        !           313:        "Stationary",           FALSE,
        !           314:        NULL,                   0
        !           315: };
        !           316: 
        !           317: static const int       len_months[2][MONSPERYEAR] = {
        !           318:        31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
        !           319:        31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
        !           320: };
        !           321: 
        !           322: static const int       len_years[2] = {
        !           323:        DAYSPERNYEAR, DAYSPERLYEAR
        !           324: };
        !           325: 
        !           326: static time_t          ats[TZ_MAX_TIMES];
        !           327: static unsigned char   types[TZ_MAX_TIMES];
        !           328: static long            gmtoffs[TZ_MAX_TYPES];
        !           329: static char            isdsts[TZ_MAX_TYPES];
        !           330: static char            abbrinds[TZ_MAX_TYPES];
        !           331: static char            ttisstds[TZ_MAX_TYPES];
        !           332: static char            chars[TZ_MAX_CHARS];
        !           333: static time_t          trans[TZ_MAX_LEAPS];
        !           334: static long            corr[TZ_MAX_LEAPS];
        !           335: static char            roll[TZ_MAX_LEAPS];
        !           336: 
        !           337: /*
        !           338: ** Memory allocation.
        !           339: */
        !           340: 
        !           341: static char *
        !           342: memcheck(ptr)
        !           343: char * const   ptr;
        !           344: {
        !           345:        if (ptr == NULL) {
        !           346:                (void) perror(progname);
        !           347:                (void) exit(EXIT_FAILURE);
        !           348:        }
        !           349:        return ptr;
        !           350: }
        !           351: 
        !           352: #define emalloc(size)          memcheck(imalloc(size))
        !           353: #define erealloc(ptr, size)    memcheck(irealloc(ptr, size))
        !           354: #define ecpyalloc(ptr)         memcheck(icpyalloc(ptr))
        !           355: #define ecatalloc(oldp, newp)  memcheck(icatalloc(oldp, newp))
        !           356: 
        !           357: /*
        !           358: ** Error handling.
        !           359: */
        !           360: 
        !           361: static void
        !           362: eats(name, num, rname, rnum)
        !           363: const char * const     name;
        !           364: const int              num;
        !           365: const char * const     rname;
        !           366: const int              rnum;
        !           367: {
        !           368:        filename = name;
        !           369:        linenum = num;
        !           370:        rfilename = rname;
        !           371:        rlinenum = rnum;
        !           372: }
        !           373: 
        !           374: static void
        !           375: eat(name, num)
        !           376: const char * const     name;
        !           377: const int              num;
        !           378: {
        !           379:        eats(name, num, (char *) NULL, -1);
        !           380: }
        !           381: 
        !           382: static void
        !           383: error(string)
        !           384: const char * const     string;
        !           385: {
        !           386:        /*
        !           387:        ** Match the format of "cc" to allow sh users to
        !           388:        **      zic ... 2>&1 | error -t "*" -v
        !           389:        ** on BSD systems.
        !           390:        */
        !           391:        (void) fprintf(stderr, "\"%s\", line %d: %s",
        !           392:                filename, linenum, string);
        !           393:        if (rfilename != NULL)
        !           394:                (void) fprintf(stderr, " (rule from \"%s\", line %d)",
        !           395:                        rfilename, rlinenum);
        !           396:        (void) fprintf(stderr, "\n");
        !           397:        ++errors;
        !           398: }
        !           399: 
        !           400: static void
        !           401: usage()
        !           402: {
        !           403:        (void) fprintf(stderr,
        !           404: "%s: usage is %s [ -s ] [ -v ] [ -l localtime ] [ -p posixrules ] [ -d directory ]\n\
        !           405: \t[ -L leapseconds ] [ filename ... ]\n",
        !           406:                progname, progname);
        !           407:        (void) exit(EXIT_FAILURE);
        !           408: }
        !           409: 
        !           410: static const char *    psxrules = NULL;
        !           411: static const char *    lcltime = NULL;
        !           412: static const char *    directory = NULL;
        !           413: static const char *    leapsec = NULL;
        !           414: static int             sflag = FALSE;
        !           415: 
        !           416: int
        !           417: main(argc, argv)
        !           418: int    argc;
        !           419: char * argv[];
        !           420: {
        !           421:        register int    i, j;
        !           422:        register int    c;
        !           423: 
        !           424: #ifdef unix
        !           425:        (void) umask(umask(022) | 022);
        !           426: #endif /* defined unix */
        !           427:        progname = argv[0];
        !           428:        while ((c = getopt(argc, argv, "d:l:p:L:vs")) != EOF)
        !           429:                switch (c) {
        !           430:                        default:
        !           431:                                usage();
        !           432:                        case 'd':
        !           433:                                if (directory == NULL)
        !           434:                                        directory = optarg;
        !           435:                                else {
        !           436:                                        (void) fprintf(stderr,
        !           437: "%s: More than one -d option specified\n",
        !           438:                                                progname);
        !           439:                                        (void) exit(EXIT_FAILURE);
        !           440:                                }
        !           441:                                break;
        !           442:                        case 'l':
        !           443:                                if (lcltime == NULL)
        !           444:                                        lcltime = optarg;
        !           445:                                else {
        !           446:                                        (void) fprintf(stderr,
        !           447: "%s: More than one -l option specified\n",
        !           448:                                                progname);
        !           449:                                        (void) exit(EXIT_FAILURE);
        !           450:                                }
        !           451:                                break;
        !           452:                        case 'p':
        !           453:                                if (psxrules == NULL)
        !           454:                                        psxrules = optarg;
        !           455:                                else {
        !           456:                                        (void) fprintf(stderr,
        !           457: "%s: More than one -p option specified\n",
        !           458:                                                progname);
        !           459:                                        (void) exit(EXIT_FAILURE);
        !           460:                                }
        !           461:                                break;
        !           462:                        case 'L':
        !           463:                                if (leapsec == NULL)
        !           464:                                        leapsec = optarg;
        !           465:                                else {
        !           466:                                        (void) fprintf(stderr,
        !           467: "%s: More than one -L option specified\n",
        !           468:                                                progname);
        !           469:                                        (void) exit(EXIT_FAILURE);
        !           470:                                }
        !           471:                                break;
        !           472:                        case 'v':
        !           473:                                noise = TRUE;
        !           474:                                break;
        !           475:                        case 's':
        !           476:                                sflag = TRUE;
        !           477:                                break;
        !           478:                }
        !           479:        if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
        !           480:                usage();        /* usage message by request */
        !           481:        if (directory == NULL)
        !           482:                directory = TZDIR;
        !           483: 
        !           484:        setboundaries();
        !           485: 
        !           486:        if (optind < argc && leapsec != NULL) {
        !           487:                infile(leapsec);
        !           488:                adjleap();
        !           489:        }
        !           490: 
        !           491:        zones = (struct zone *) emalloc(0);
        !           492:        rules = (struct rule *) emalloc(0);
        !           493:        links = (struct link *) emalloc(0);
        !           494:        for (i = optind; i < argc; ++i)
        !           495:                infile(argv[i]);
        !           496:        if (errors)
        !           497:                (void) exit(EXIT_FAILURE);
        !           498:        associate();
        !           499:        for (i = 0; i < nzones; i = j) {
        !           500:                /*
        !           501:                ** Find the next non-continuation zone entry.
        !           502:                */
        !           503:                for (j = i + 1; j < nzones && zones[j].z_name == NULL; ++j)
        !           504:                        ;
        !           505:                outzone(&zones[i], j - i);
        !           506:        }
        !           507:        /*
        !           508:        ** Make links.
        !           509:        */
        !           510:        for (i = 0; i < nlinks; ++i)
        !           511:                dolink(links[i].l_from, links[i].l_to);
        !           512:        if (lcltime != NULL)
        !           513:                dolink(lcltime, TZDEFAULT);
        !           514:        if (psxrules != NULL)
        !           515:                dolink(psxrules, TZDEFRULES);
        !           516:        return (errors == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
        !           517: }
        !           518: 
        !           519: static void
        !           520: dolink(fromfile, tofile)
        !           521: const char * const     fromfile;
        !           522: const char * const     tofile;
        !           523: {
        !           524:        register char * fromname;
        !           525:        register char * toname;
        !           526: 
        !           527:        fromname = ecpyalloc(directory);
        !           528:        fromname = ecatalloc(fromname, "/");
        !           529:        fromname = ecatalloc(fromname, fromfile);
        !           530:        toname = ecpyalloc(directory);
        !           531:        toname = ecatalloc(toname, "/");
        !           532:        toname = ecatalloc(toname, tofile);
        !           533:        /*
        !           534:        ** We get to be careful here since
        !           535:        ** there's a fair chance of root running us.
        !           536:        */
        !           537:        if (!itsdir(toname))
        !           538:                (void) remove(toname);
        !           539:        if (link(fromname, toname) != 0) {
        !           540:                (void) fprintf(stderr, "%s: Can't link from %s to ",
        !           541:                        progname, fromname);
        !           542:                (void) perror(toname);
        !           543:                (void) exit(EXIT_FAILURE);
        !           544:        }
        !           545:        ifree(fromname);
        !           546:        ifree(toname);
        !           547: }
        !           548: 
        !           549: static void
        !           550: setboundaries()
        !           551: {
        !           552:        register time_t bit;
        !           553: 
        !           554:        for (bit = 1; bit > 0; bit <<= 1)
        !           555:                ;
        !           556:        if (bit == 0) {         /* time_t is an unsigned type */
        !           557:                tt_signed = FALSE;
        !           558:                min_time = 0;
        !           559:                max_time = ~(time_t) 0;
        !           560:                if (sflag)
        !           561:                        max_time >>= 1;
        !           562:        } else {
        !           563:                tt_signed = TRUE;
        !           564:                min_time = bit;
        !           565:                max_time = bit;
        !           566:                ++max_time;
        !           567:                max_time = -max_time;
        !           568:                if (sflag)
        !           569:                        min_time = 0;
        !           570:        }
        !           571:        min_year = TM_YEAR_BASE + gmtime(&min_time)->tm_year;
        !           572:        max_year = TM_YEAR_BASE + gmtime(&max_time)->tm_year;
        !           573: }
        !           574: 
        !           575: static int
        !           576: itsdir(name)
        !           577: const char * const     name;
        !           578: {
        !           579:        struct stat     s;
        !           580: 
        !           581:        return stat(name, &s) == 0 && (s.st_mode & S_IFMT) == S_IFDIR;
        !           582: }
        !           583: 
        !           584: /*
        !           585: ** Associate sets of rules with zones.
        !           586: */
        !           587: 
        !           588: /*
        !           589: ** Sort by rule name.
        !           590: */
        !           591: 
        !           592: static int
        !           593: rcomp(cp1, cp2)
        !           594: const genericptr_t     cp1;
        !           595: const genericptr_t     cp2;
        !           596: {
        !           597:        return strcmp(((struct rule *) cp1)->r_name,
        !           598:                ((struct rule *) cp2)->r_name);
        !           599: }
        !           600: 
        !           601: static void
        !           602: associate()
        !           603: {
        !           604:        register struct zone *  zp;
        !           605:        register struct rule *  rp;
        !           606:        register int            base, out;
        !           607:        register int            i;
        !           608: 
        !           609:        if (nrules != 0)
        !           610:                (void) qsort((genericptr_t) rules,
        !           611:                        (qsort_size_t) nrules,
        !           612:                        (qsort_size_t) sizeof *rules, rcomp);
        !           613:        for (i = 0; i < nzones; ++i) {
        !           614:                zp = &zones[i];
        !           615:                zp->z_rules = NULL;
        !           616:                zp->z_nrules = 0;
        !           617:        }
        !           618:        for (base = 0; base < nrules; base = out) {
        !           619:                rp = &rules[base];
        !           620:                for (out = base + 1; out < nrules; ++out)
        !           621:                        if (strcmp(rp->r_name, rules[out].r_name) != 0)
        !           622:                                break;
        !           623:                for (i = 0; i < nzones; ++i) {
        !           624:                        zp = &zones[i];
        !           625:                        if (strcmp(zp->z_rule, rp->r_name) != 0)
        !           626:                                continue;
        !           627:                        zp->z_rules = rp;
        !           628:                        zp->z_nrules = out - base;
        !           629:                }
        !           630:        }
        !           631:        for (i = 0; i < nzones; ++i) {
        !           632:                zp = &zones[i];
        !           633:                if (zp->z_nrules == 0) {
        !           634:                        /*
        !           635:                        ** Maybe we have a local standard time offset.
        !           636:                        */
        !           637:                        eat(zp->z_filename, zp->z_linenum);
        !           638:                        zp->z_stdoff = gethms(zp->z_rule, "unruly zone", TRUE);
        !           639:                        /*
        !           640:                        ** Note, though, that if there's no rule,
        !           641:                        ** a '%s' in the format is a bad thing.
        !           642:                        */
        !           643:                        if (strchr(zp->z_format, '%') != 0)
        !           644:                                error("%s in ruleless zone");
        !           645:                }
        !           646:        }
        !           647:        if (errors)
        !           648:                (void) exit(EXIT_FAILURE);
        !           649: }
        !           650: 
        !           651: static void
        !           652: infile(name)
        !           653: const char *   name;
        !           654: {
        !           655:        register FILE *                 fp;
        !           656:        register char **                fields;
        !           657:        register char *                 cp;
        !           658:        register const struct lookup *  lp;
        !           659:        register int                    nfields;
        !           660:        register int                    wantcont;
        !           661:        register int                    num;
        !           662:        char                            buf[BUFSIZ];
        !           663: 
        !           664:        if (strcmp(name, "-") == 0) {
        !           665:                name = "standard input";
        !           666:                fp = stdin;
        !           667:        } else if ((fp = fopen(name, "r")) == NULL) {
        !           668:                (void) fprintf(stderr, "%s: Can't open ", progname);
        !           669:                (void) perror(name);
        !           670:                (void) exit(EXIT_FAILURE);
        !           671:        }
        !           672:        wantcont = FALSE;
        !           673:        for (num = 1; ; ++num) {
        !           674:                eat(name, num);
        !           675:                if (fgets(buf, (int) sizeof buf, fp) != buf)
        !           676:                        break;
        !           677:                cp = strchr(buf, '\n');
        !           678:                if (cp == NULL) {
        !           679:                        error("line too long");
        !           680:                        (void) exit(EXIT_FAILURE);
        !           681:                }
        !           682:                *cp = '\0';
        !           683:                fields = getfields(buf);
        !           684:                nfields = 0;
        !           685:                while (fields[nfields] != NULL) {
        !           686:                        if (ciequal(fields[nfields], "-"))
        !           687:                                fields[nfields] = "";
        !           688:                        ++nfields;
        !           689:                }
        !           690:                if (nfields == 0) {
        !           691:                        /* nothing to do */
        !           692:                } else if (wantcont) {
        !           693:                        wantcont = inzcont(fields, nfields);
        !           694:                } else {
        !           695:                        lp = byword(fields[0], line_codes);
        !           696:                        if (lp == NULL)
        !           697:                                error("input line of unknown type");
        !           698:                        else switch ((int) (lp->l_value)) {
        !           699:                                case LC_RULE:
        !           700:                                        inrule(fields, nfields);
        !           701:                                        wantcont = FALSE;
        !           702:                                        break;
        !           703:                                case LC_ZONE:
        !           704:                                        wantcont = inzone(fields, nfields);
        !           705:                                        break;
        !           706:                                case LC_LINK:
        !           707:                                        inlink(fields, nfields);
        !           708:                                        wantcont = FALSE;
        !           709:                                        break;
        !           710:                                case LC_LEAP:
        !           711:                                        if (name != leapsec)
        !           712:                                                (void) fprintf(stderr,
        !           713: "%s: Leap line in non leap seconds file %s\n",
        !           714:                                                        progname, name);
        !           715:                                        else    inleap(fields, nfields);
        !           716:                                        wantcont = FALSE;
        !           717:                                        break;
        !           718:                                default:        /* "cannot happen" */
        !           719:                                        (void) fprintf(stderr,
        !           720: "%s: panic: Invalid l_value %d\n",
        !           721:                                                progname, lp->l_value);
        !           722:                                        (void) exit(EXIT_FAILURE);
        !           723:                        }
        !           724:                }
        !           725:                ifree((char *) fields);
        !           726:        }
        !           727:        if (ferror(fp)) {
        !           728:                (void) fprintf(stderr, "%s: Error reading ", progname);
        !           729:                (void) perror(filename);
        !           730:                (void) exit(EXIT_FAILURE);
        !           731:        }
        !           732:        if (fp != stdin && fclose(fp)) {
        !           733:                (void) fprintf(stderr, "%s: Error closing ", progname);
        !           734:                (void) perror(filename);
        !           735:                (void) exit(EXIT_FAILURE);
        !           736:        }
        !           737:        if (wantcont)
        !           738:                error("expected continuation line not found");
        !           739: }
        !           740: 
        !           741: /*
        !           742: ** Convert a string of one of the forms
        !           743: **     h       -h      hh:mm   -hh:mm  hh:mm:ss        -hh:mm:ss
        !           744: ** into a number of seconds.
        !           745: ** A null string maps to zero.
        !           746: ** Call error with errstring and return zero on errors.
        !           747: */
        !           748: 
        !           749: static long
        !           750: gethms(string, errstring, signable)
        !           751: const char *           string;
        !           752: const char * const     errstring;
        !           753: const int              signable;
        !           754: {
        !           755:        int     hh, mm, ss, sign;
        !           756: 
        !           757:        if (string == NULL || *string == '\0')
        !           758:                return 0;
        !           759:        if (!signable)
        !           760:                sign = 1;
        !           761:        else if (*string == '-') {
        !           762:                sign = -1;
        !           763:                ++string;
        !           764:        } else  sign = 1;
        !           765:        if (sscanf(string, scheck(string, "%d"), &hh) == 1)
        !           766:                mm = ss = 0;
        !           767:        else if (sscanf(string, scheck(string, "%d:%d"), &hh, &mm) == 2)
        !           768:                ss = 0;
        !           769:        else if (sscanf(string, scheck(string, "%d:%d:%d"),
        !           770:                &hh, &mm, &ss) != 3) {
        !           771:                        error(errstring);
        !           772:                        return 0;
        !           773:        }
        !           774:        if (hh < 0 || hh >= HOURSPERDAY ||
        !           775:                mm < 0 || mm >= MINSPERHOUR ||
        !           776:                ss < 0 || ss > SECSPERMIN) {
        !           777:                        error(errstring);
        !           778:                        return 0;
        !           779:        }
        !           780:        return eitol(sign) *
        !           781:                (eitol(hh * MINSPERHOUR + mm) *
        !           782:                eitol(SECSPERMIN) + eitol(ss));
        !           783: }
        !           784: 
        !           785: static void
        !           786: inrule(fields, nfields)
        !           787: register char ** const fields;
        !           788: const int              nfields;
        !           789: {
        !           790:        static struct rule      r;
        !           791: 
        !           792:        if (nfields != RULE_FIELDS) {
        !           793:                error("wrong number of fields on Rule line");
        !           794:                return;
        !           795:        }
        !           796:        if (*fields[RF_NAME] == '\0') {
        !           797:                error("nameless rule");
        !           798:                return;
        !           799:        }
        !           800:        r.r_filename = filename;
        !           801:        r.r_linenum = linenum;
        !           802:        r.r_stdoff = gethms(fields[RF_STDOFF], "invalid saved time", TRUE);
        !           803:        rulesub(&r, fields[RF_LOYEAR], fields[RF_HIYEAR], fields[RF_COMMAND],
        !           804:                fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]);
        !           805:        r.r_name = ecpyalloc(fields[RF_NAME]);
        !           806:        r.r_abbrvar = ecpyalloc(fields[RF_ABBRVAR]);
        !           807:        rules = (struct rule *) erealloc((char *) rules,
        !           808:                (int) ((nrules + 1) * sizeof *rules));
        !           809:        rules[nrules++] = r;
        !           810: }
        !           811: 
        !           812: static int
        !           813: inzone(fields, nfields)
        !           814: register char ** const fields;
        !           815: const int              nfields;
        !           816: {
        !           817:        register int    i;
        !           818:        char            buf[132];
        !           819: 
        !           820:        if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS) {
        !           821:                error("wrong number of fields on Zone line");
        !           822:                return FALSE;
        !           823:        }
        !           824:        if (strcmp(fields[ZF_NAME], TZDEFAULT) == 0 && lcltime != NULL) {
        !           825:                (void) sprintf(buf,
        !           826:                        "\"Zone %s\" line and -l option are mutually exclusive",
        !           827:                        TZDEFAULT);
        !           828:                error(buf);
        !           829:                return FALSE;
        !           830:        }
        !           831:        if (strcmp(fields[ZF_NAME], TZDEFRULES) == 0 && psxrules != NULL) {
        !           832:                (void) sprintf(buf,
        !           833:                        "\"Zone %s\" line and -p option are mutually exclusive",
        !           834:                        TZDEFRULES);
        !           835:                error(buf);
        !           836:                return FALSE;
        !           837:        }
        !           838:        for (i = 0; i < nzones; ++i)
        !           839:                if (zones[i].z_name != NULL &&
        !           840:                        strcmp(zones[i].z_name, fields[ZF_NAME]) == 0) {
        !           841:                                (void) sprintf(buf,
        !           842: "duplicate zone name %s (file \"%s\", line %d)",
        !           843:                                        fields[ZF_NAME],
        !           844:                                        zones[i].z_filename,
        !           845:                                        zones[i].z_linenum);
        !           846:                                error(buf);
        !           847:                                return FALSE;
        !           848:                }
        !           849:        return inzsub(fields, nfields, FALSE);
        !           850: }
        !           851: 
        !           852: static int
        !           853: inzcont(fields, nfields)
        !           854: register char ** const fields;
        !           855: const int              nfields;
        !           856: {
        !           857:        if (nfields < ZONEC_MINFIELDS || nfields > ZONEC_MAXFIELDS) {
        !           858:                error("wrong number of fields on Zone continuation line");
        !           859:                return FALSE;
        !           860:        }
        !           861:        return inzsub(fields, nfields, TRUE);
        !           862: }
        !           863: 
        !           864: static int
        !           865: inzsub(fields, nfields, iscont)
        !           866: register char ** const fields;
        !           867: const int              nfields;
        !           868: const int              iscont;
        !           869: {
        !           870:        register char *         cp;
        !           871:        static struct zone      z;
        !           872:        register int            i_gmtoff, i_rule, i_format;
        !           873:        register int            i_untilyear, i_untilmonth;
        !           874:        register int            i_untilday, i_untiltime;
        !           875:        register int            hasuntil;
        !           876: 
        !           877:        if (iscont) {
        !           878:                i_gmtoff = ZFC_GMTOFF;
        !           879:                i_rule = ZFC_RULE;
        !           880:                i_format = ZFC_FORMAT;
        !           881:                i_untilyear = ZFC_TILYEAR;
        !           882:                i_untilmonth = ZFC_TILMONTH;
        !           883:                i_untilday = ZFC_TILDAY;
        !           884:                i_untiltime = ZFC_TILTIME;
        !           885:                z.z_name = NULL;
        !           886:        } else {
        !           887:                i_gmtoff = ZF_GMTOFF;
        !           888:                i_rule = ZF_RULE;
        !           889:                i_format = ZF_FORMAT;
        !           890:                i_untilyear = ZF_TILYEAR;
        !           891:                i_untilmonth = ZF_TILMONTH;
        !           892:                i_untilday = ZF_TILDAY;
        !           893:                i_untiltime = ZF_TILTIME;
        !           894:                z.z_name = ecpyalloc(fields[ZF_NAME]);
        !           895:        }
        !           896:        z.z_filename = filename;
        !           897:        z.z_linenum = linenum;
        !           898:        z.z_gmtoff = gethms(fields[i_gmtoff], "invalid GMT offset", TRUE);
        !           899:        if ((cp = strchr(fields[i_format], '%')) != 0) {
        !           900:                if (*++cp != 's' || strchr(cp, '%') != 0) {
        !           901:                        error("invalid abbreviation format");
        !           902:                        return FALSE;
        !           903:                }
        !           904:        }
        !           905:        z.z_rule = ecpyalloc(fields[i_rule]);
        !           906:        z.z_format = ecpyalloc(fields[i_format]);
        !           907:        hasuntil = nfields > i_untilyear;
        !           908:        if (hasuntil) {
        !           909:                z.z_untilrule.r_filename = filename;
        !           910:                z.z_untilrule.r_linenum = linenum;
        !           911:                rulesub(&z.z_untilrule,
        !           912:                        fields[i_untilyear],
        !           913:                        "only",
        !           914:                        "",
        !           915:                        (nfields > i_untilmonth) ? fields[i_untilmonth] : "Jan",
        !           916:                        (nfields > i_untilday) ? fields[i_untilday] : "1",
        !           917:                        (nfields > i_untiltime) ? fields[i_untiltime] : "0");
        !           918:                z.z_untiltime = rpytime(&z.z_untilrule, z.z_untilrule.r_loyear);
        !           919:                if (iscont && nzones > 0 && z.z_untiltime < max_time &&
        !           920:                        z.z_untiltime > min_time &&
        !           921:                        zones[nzones - 1].z_untiltime >= z.z_untiltime) {
        !           922: error("Zone continuation line end time is not after end time of previous line");
        !           923:                        return FALSE;
        !           924:                }
        !           925:        }
        !           926:        zones = (struct zone *) erealloc((char *) zones,
        !           927:                (int) ((nzones + 1) * sizeof *zones));
        !           928:        zones[nzones++] = z;
        !           929:        /*
        !           930:        ** If there was an UNTIL field on this line,
        !           931:        ** there's more information about the zone on the next line.
        !           932:        */
        !           933:        return hasuntil;
        !           934: }
        !           935: 
        !           936: static void
        !           937: inleap(fields, nfields)
        !           938: register char ** const fields;
        !           939: const int              nfields;
        !           940: {
        !           941:        register const char *           cp;
        !           942:        register const struct lookup *  lp;
        !           943:        register int                    i, j;
        !           944:        int                             year, month, day;
        !           945:        long                            dayoff, tod;
        !           946:        time_t                          t;
        !           947: 
        !           948:        if (nfields != LEAP_FIELDS) {
        !           949:                error("wrong number of fields on Leap line");
        !           950:                return;
        !           951:        }
        !           952:        dayoff = 0;
        !           953:        cp = fields[LP_YEAR];
        !           954:        if (sscanf(cp, scheck(cp, "%d"), &year) != 1 ||
        !           955:                year < min_year || year > max_year) {
        !           956:                        /*
        !           957:                         * Leapin' Lizards!
        !           958:                         */
        !           959:                        error("invalid leaping year");
        !           960:                        return;
        !           961:        }
        !           962:        j = EPOCH_YEAR;
        !           963:        while (j != year) {
        !           964:                if (year > j) {
        !           965:                        i = len_years[isleap(j)];
        !           966:                        ++j;
        !           967:                } else {
        !           968:                        --j;
        !           969:                        i = -len_years[isleap(j)];
        !           970:                }
        !           971:                dayoff = oadd(dayoff, eitol(i));
        !           972:        }
        !           973:        if ((lp = byword(fields[LP_MONTH], mon_names)) == NULL) {
        !           974:                error("invalid month name");
        !           975:                return;
        !           976:        }
        !           977:        month = lp->l_value;
        !           978:        j = TM_JANUARY;
        !           979:        while (j != month) {
        !           980:                i = len_months[isleap(year)][j];
        !           981:                dayoff = oadd(dayoff, eitol(i));
        !           982:                ++j;
        !           983:        }
        !           984:        cp = fields[LP_DAY];
        !           985:        if (sscanf(cp, scheck(cp, "%d"), &day) != 1 ||
        !           986:                day <= 0 || day > len_months[isleap(year)][month]) {
        !           987:                        error("invalid day of month");
        !           988:                        return;
        !           989:        }
        !           990:        dayoff = oadd(dayoff, eitol(day - 1));
        !           991:        if (dayoff < 0 && !tt_signed) {
        !           992:                error("time before zero");
        !           993:                return;
        !           994:        }
        !           995:        t = (time_t) dayoff * SECSPERDAY;
        !           996:        /*
        !           997:        ** Cheap overflow check.
        !           998:        */
        !           999:        if (t / SECSPERDAY != dayoff) {
        !          1000:                error("time overflow");
        !          1001:                return;
        !          1002:        }
        !          1003:        tod = gethms(fields[LP_TIME], "invalid time of day", FALSE);
        !          1004:        cp = fields[LP_CORR];
        !          1005:        if (strcmp(cp, "+") != 0 && strcmp(cp, "") != 0) {
        !          1006:                /* infile() turned "-" into "" */
        !          1007:                error("illegal CORRECTION field on Leap line");
        !          1008:                return;
        !          1009:        }
        !          1010:        if ((lp = byword(fields[LP_ROLL], leap_types)) == NULL) {
        !          1011:                error("illegal Rolling/Stationary field on Leap line");
        !          1012:                return;
        !          1013:        }
        !          1014:        addleap(tadd(t, tod), *cp == '+', lp->l_value);
        !          1015: }
        !          1016: 
        !          1017: static void
        !          1018: inlink(fields, nfields)
        !          1019: register char ** const fields;
        !          1020: const int              nfields;
        !          1021: {
        !          1022:        struct link     l;
        !          1023: 
        !          1024:        if (nfields != LINK_FIELDS) {
        !          1025:                error("wrong number of fields on Link line");
        !          1026:                return;
        !          1027:        }
        !          1028:        if (*fields[LF_FROM] == '\0') {
        !          1029:                error("blank FROM field on Link line");
        !          1030:                return;
        !          1031:        }
        !          1032:        if (*fields[LF_TO] == '\0') {
        !          1033:                error("blank TO field on Link line");
        !          1034:                return;
        !          1035:        }
        !          1036:        l.l_filename = filename;
        !          1037:        l.l_linenum = linenum;
        !          1038:        l.l_from = ecpyalloc(fields[LF_FROM]);
        !          1039:        l.l_to = ecpyalloc(fields[LF_TO]);
        !          1040:        links = (struct link *) erealloc((char *) links,
        !          1041:                (int) ((nlinks + 1) * sizeof *links));
        !          1042:        links[nlinks++] = l;
        !          1043: }
        !          1044: 
        !          1045: static void
        !          1046: rulesub(rp, loyearp, hiyearp, typep, monthp, dayp, timep)
        !          1047: register struct rule * const   rp;
        !          1048: char * const                   loyearp;
        !          1049: char * const                   hiyearp;
        !          1050: char * const                   typep;
        !          1051: char * const                   monthp;
        !          1052: char * const                   dayp;
        !          1053: char * const                   timep;
        !          1054: {
        !          1055:        register struct lookup const *  lp;
        !          1056:        register char *                 cp;
        !          1057: 
        !          1058:        if ((lp = byword(monthp, mon_names)) == NULL) {
        !          1059:                error("invalid month name");
        !          1060:                return;
        !          1061:        }
        !          1062:        rp->r_month = lp->l_value;
        !          1063:        rp->r_todisstd = FALSE;
        !          1064:        cp = timep;
        !          1065:        if (*cp != '\0') {
        !          1066:                cp += strlen(cp) - 1;
        !          1067:                switch (lowerit(*cp)) {
        !          1068:                        case 's':
        !          1069:                                rp->r_todisstd = TRUE;
        !          1070:                                *cp = '\0';
        !          1071:                                break;
        !          1072:                        case 'w':
        !          1073:                                rp->r_todisstd = FALSE;
        !          1074:                                *cp = '\0';
        !          1075:                                break;
        !          1076:                }
        !          1077:        }
        !          1078:        rp->r_tod = gethms(timep, "invalid time of day", FALSE);
        !          1079:        /*
        !          1080:        ** Year work.
        !          1081:        */
        !          1082:        cp = loyearp;
        !          1083:        if ((lp = byword(cp, begin_years)) != NULL) switch ((int) lp->l_value) {
        !          1084:                case YR_MINIMUM:
        !          1085:                        rp->r_loyear = min_year;
        !          1086:                        break;
        !          1087:                case YR_MAXIMUM:
        !          1088:                        rp->r_loyear = max_year;
        !          1089:                        break;
        !          1090:                default:        /* "cannot happen" */
        !          1091:                        (void) fprintf(stderr,
        !          1092:                                "%s: panic: Invalid l_value %d\n",
        !          1093:                                progname, lp->l_value);
        !          1094:                        (void) exit(EXIT_FAILURE);
        !          1095:        } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_loyear) != 1 ||
        !          1096:                rp->r_loyear < min_year || rp->r_loyear > max_year) {
        !          1097:                        if (noise)
        !          1098:                                error("invalid starting year");
        !          1099:                        if (rp->r_loyear > max_year)
        !          1100:                                return;
        !          1101:        }
        !          1102:        cp = hiyearp;
        !          1103:        if ((lp = byword(cp, end_years)) != NULL) switch ((int) lp->l_value) {
        !          1104:                case YR_MINIMUM:
        !          1105:                        rp->r_hiyear = min_year;
        !          1106:                        break;
        !          1107:                case YR_MAXIMUM:
        !          1108:                        rp->r_hiyear = max_year;
        !          1109:                        break;
        !          1110:                case YR_ONLY:
        !          1111:                        rp->r_hiyear = rp->r_loyear;
        !          1112:                        break;
        !          1113:                default:        /* "cannot happen" */
        !          1114:                        (void) fprintf(stderr,
        !          1115:                                "%s: panic: Invalid l_value %d\n",
        !          1116:                                progname, lp->l_value);
        !          1117:                        (void) exit(EXIT_FAILURE);
        !          1118:        } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_hiyear) != 1 ||
        !          1119:                rp->r_hiyear < min_year || rp->r_hiyear > max_year) {
        !          1120:                        if (noise)
        !          1121:                                error("invalid ending year");
        !          1122:                        if (rp->r_hiyear < min_year)
        !          1123:                                return;
        !          1124:        }
        !          1125:        if (rp->r_hiyear < min_year)
        !          1126:                return;
        !          1127:        if (rp->r_loyear < min_year)
        !          1128:                rp->r_loyear = min_year;
        !          1129:        if (rp->r_hiyear > max_year)
        !          1130:                rp->r_hiyear = max_year;
        !          1131:        if (rp->r_loyear > rp->r_hiyear) {
        !          1132:                error("starting year greater than ending year");
        !          1133:                return;
        !          1134:        }
        !          1135:        if (*typep == '\0')
        !          1136:                rp->r_yrtype = NULL;
        !          1137:        else {
        !          1138:                if (rp->r_loyear == rp->r_hiyear) {
        !          1139:                        error("typed single year");
        !          1140:                        return;
        !          1141:                }
        !          1142:                rp->r_yrtype = ecpyalloc(typep);
        !          1143:        }
        !          1144:        /*
        !          1145:        ** Day work.
        !          1146:        ** Accept things such as:
        !          1147:        **      1
        !          1148:        **      last-Sunday
        !          1149:        **      Sun<=20
        !          1150:        **      Sun>=7
        !          1151:        */
        !          1152:        if ((lp = byword(dayp, lasts)) != NULL) {
        !          1153:                rp->r_dycode = DC_DOWLEQ;
        !          1154:                rp->r_wday = lp->l_value;
        !          1155:                rp->r_dayofmonth = len_months[1][rp->r_month];
        !          1156:        } else {
        !          1157:                if ((cp = strchr(dayp, '<')) != 0)
        !          1158:                        rp->r_dycode = DC_DOWLEQ;
        !          1159:                else if ((cp = strchr(dayp, '>')) != 0)
        !          1160:                        rp->r_dycode = DC_DOWGEQ;
        !          1161:                else {
        !          1162:                        cp = dayp;
        !          1163:                        rp->r_dycode = DC_DOM;
        !          1164:                }
        !          1165:                if (rp->r_dycode != DC_DOM) {
        !          1166:                        *cp++ = 0;
        !          1167:                        if (*cp++ != '=') {
        !          1168:                                error("invalid day of month");
        !          1169:                                return;
        !          1170:                        }
        !          1171:                        if ((lp = byword(dayp, wday_names)) == NULL) {
        !          1172:                                error("invalid weekday name");
        !          1173:                                return;
        !          1174:                        }
        !          1175:                        rp->r_wday = lp->l_value;
        !          1176:                }
        !          1177:                if (sscanf(cp, scheck(cp, "%d"), &rp->r_dayofmonth) != 1 ||
        !          1178:                        rp->r_dayofmonth <= 0 ||
        !          1179:                        (rp->r_dayofmonth > len_months[1][rp->r_month])) {
        !          1180:                                error("invalid day of month");
        !          1181:                                return;
        !          1182:                }
        !          1183:        }
        !          1184: }
        !          1185: 
        !          1186: static void
        !          1187: convert(val, buf)
        !          1188: const long     val;
        !          1189: char * const   buf;
        !          1190: {
        !          1191:        register int    i;
        !          1192:        register long   shift;
        !          1193: 
        !          1194:        for (i = 0, shift = 24; i < 4; ++i, shift -= 8)
        !          1195:                buf[i] = val >> shift;
        !          1196: }
        !          1197: 
        !          1198: static void
        !          1199: puttzcode(val, fp)
        !          1200: const long     val;
        !          1201: FILE * const   fp;
        !          1202: {
        !          1203:        char    buf[4];
        !          1204: 
        !          1205:        convert(val, buf);
        !          1206:        (void) fwrite((genericptr_t) buf,
        !          1207:                (fwrite_size_t) sizeof buf,
        !          1208:                (fwrite_size_t) 1, fp);
        !          1209: }
        !          1210: 
        !          1211: static void
        !          1212: writezone(name)
        !          1213: const char * const     name;
        !          1214: {
        !          1215:        register FILE *         fp;
        !          1216:        register int            i, j;
        !          1217:        char                    fullname[BUFSIZ];
        !          1218:        static struct tzhead    tzh;
        !          1219: 
        !          1220:        if (strlen(directory) + 1 + strlen(name) >= sizeof fullname) {
        !          1221:                (void) fprintf(stderr,
        !          1222:                        "%s: File name %s/%s too long\n", progname,
        !          1223:                        directory, name);
        !          1224:                (void) exit(EXIT_FAILURE);
        !          1225:        }
        !          1226:        (void) sprintf(fullname, "%s/%s", directory, name);
        !          1227:        if ((fp = fopen(fullname, "wb")) == NULL) {
        !          1228:                if (mkdirs(fullname) != 0)
        !          1229:                        (void) exit(EXIT_FAILURE);
        !          1230:                if ((fp = fopen(fullname, "wb")) == NULL) {
        !          1231:                        (void) fprintf(stderr, "%s: Can't create ", progname);
        !          1232:                        (void) perror(fullname);
        !          1233:                        (void) exit(EXIT_FAILURE);
        !          1234:                }
        !          1235:        }
        !          1236:        convert(eitol(typecnt), tzh.tzh_ttisstdcnt);
        !          1237:        convert(eitol(leapcnt), tzh.tzh_leapcnt);
        !          1238:        convert(eitol(timecnt), tzh.tzh_timecnt);
        !          1239:        convert(eitol(typecnt), tzh.tzh_typecnt);
        !          1240:        convert(eitol(charcnt), tzh.tzh_charcnt);
        !          1241:        (void) fwrite((genericptr_t) &tzh,
        !          1242:                (fwrite_size_t) sizeof tzh,
        !          1243:                (fwrite_size_t) 1, fp);
        !          1244:        for (i = 0; i < timecnt; ++i) {
        !          1245:                j = leapcnt;
        !          1246:                while (--j >= 0)
        !          1247:                        if (ats[i] >= trans[j]) {
        !          1248:                                ats[i] = tadd(ats[i], corr[j]);
        !          1249:                                break;
        !          1250:                        }
        !          1251:                puttzcode((long) ats[i], fp);
        !          1252:        }
        !          1253:        if (timecnt > 0)
        !          1254:                (void) fwrite((genericptr_t) types,
        !          1255:                        (fwrite_size_t) sizeof types[0],
        !          1256:                        (fwrite_size_t) timecnt, fp);
        !          1257:        for (i = 0; i < typecnt; ++i) {
        !          1258:                puttzcode((long) gmtoffs[i], fp);
        !          1259:                (void) putc(isdsts[i], fp);
        !          1260:                (void) putc(abbrinds[i], fp);
        !          1261:        }
        !          1262:        if (charcnt != 0)
        !          1263:                (void) fwrite((genericptr_t) chars,
        !          1264:                        (fwrite_size_t) sizeof chars[0],
        !          1265:                        (fwrite_size_t) charcnt, fp);
        !          1266:        for (i = 0; i < leapcnt; ++i) {
        !          1267:                if (roll[i]) {
        !          1268:                        if (timecnt == 0 || trans[i] < ats[0]) {
        !          1269:                                j = 0;
        !          1270:                                while (isdsts[j])
        !          1271:                                        if (++j >= typecnt) {
        !          1272:                                                j = 0;
        !          1273:                                                break;
        !          1274:                                        }
        !          1275:                        } else {
        !          1276:                                j = 1;
        !          1277:                                while (j < timecnt && trans[i] >= ats[j])
        !          1278:                                        ++j;
        !          1279:                                j = types[j - 1];
        !          1280:                        }
        !          1281:                        puttzcode((long) tadd(trans[i], -gmtoffs[j]), fp);
        !          1282:                } else  puttzcode((long) trans[i], fp);
        !          1283:                puttzcode((long) corr[i], fp);
        !          1284:        }
        !          1285:        for (i = 0; i < typecnt; ++i)
        !          1286:                (void) putc(ttisstds[i], fp);
        !          1287:        if (ferror(fp) || fclose(fp)) {
        !          1288:                (void) fprintf(stderr, "%s: Write error on ", progname);
        !          1289:                (void) perror(fullname);
        !          1290:                (void) exit(EXIT_FAILURE);
        !          1291:        }
        !          1292: }
        !          1293: 
        !          1294: static void
        !          1295: outzone(zpfirst, zonecount)
        !          1296: const struct zone * const      zpfirst;
        !          1297: const int                      zonecount;
        !          1298: {
        !          1299:        register const struct zone *    zp;
        !          1300:        register struct rule *          rp;
        !          1301:        register int                    i, j;
        !          1302:        register int                    usestart, useuntil;
        !          1303:        register time_t                 starttime, untiltime;
        !          1304:        register long                   gmtoff;
        !          1305:        register long                   stdoff;
        !          1306:        register int                    year;
        !          1307:        register long                   startoff;
        !          1308:        register int                    startisdst;
        !          1309:        register int                    startttisstd;
        !          1310:        register int                    type;
        !          1311:        char                            startbuf[BUFSIZ];
        !          1312: 
        !          1313:        /*
        !          1314:        ** Now. . .finally. . .generate some useful data!
        !          1315:        */
        !          1316:        timecnt = 0;
        !          1317:        typecnt = 0;
        !          1318:        charcnt = 0;
        !          1319:        /*
        !          1320:        ** Two guesses. . .the second may well be corrected later.
        !          1321:        */
        !          1322:        gmtoff = zpfirst->z_gmtoff;
        !          1323:        stdoff = 0;
        !          1324: #ifdef lint
        !          1325:        starttime = 0;
        !          1326:        startttisstd = FALSE;
        !          1327: #endif /* defined lint */
        !          1328:        for (i = 0; i < zonecount; ++i) {
        !          1329:                usestart = i > 0;
        !          1330:                useuntil = i < (zonecount - 1);
        !          1331:                zp = &zpfirst[i];
        !          1332:                eat(zp->z_filename, zp->z_linenum);
        !          1333:                startisdst = -1;
        !          1334:                if (zp->z_nrules == 0) {
        !          1335:                        type = addtype(oadd(zp->z_gmtoff, zp->z_stdoff),
        !          1336:                                zp->z_format, zp->z_stdoff != 0,
        !          1337:                                startttisstd);
        !          1338:                        if (usestart)
        !          1339:                                addtt(starttime, type);
        !          1340:                        gmtoff = zp->z_gmtoff;
        !          1341:                        stdoff = zp->z_stdoff;
        !          1342:                } else for (year = min_year; year <= max_year; ++year) {
        !          1343:                        if (useuntil && year > zp->z_untilrule.r_hiyear)
        !          1344:                                break;
        !          1345:                        /*
        !          1346:                        ** Mark which rules to do in the current year.
        !          1347:                        ** For those to do, calculate rpytime(rp, year);
        !          1348:                        */
        !          1349:                        for (j = 0; j < zp->z_nrules; ++j) {
        !          1350:                                rp = &zp->z_rules[j];
        !          1351:                                eats(zp->z_filename, zp->z_linenum,
        !          1352:                                        rp->r_filename, rp->r_linenum);
        !          1353:                                rp->r_todo = year >= rp->r_loyear &&
        !          1354:                                                year <= rp->r_hiyear &&
        !          1355:                                                yearistype(year, rp->r_yrtype);
        !          1356:                                if (rp->r_todo)
        !          1357:                                        rp->r_temp = rpytime(rp, year);
        !          1358:                        }
        !          1359:                        for ( ; ; ) {
        !          1360:                                register int    k;
        !          1361:                                register time_t jtime, ktime;
        !          1362:                                register long   offset;
        !          1363:                                char            buf[BUFSIZ];
        !          1364: 
        !          1365:                                if (useuntil) {
        !          1366:                                        /*
        !          1367:                                        ** Turn untiltime into GMT
        !          1368:                                        ** assuming the current gmtoff and
        !          1369:                                        ** stdoff values.
        !          1370:                                        */
        !          1371:                                        offset = gmtoff;
        !          1372:                                        if (!zp->z_untilrule.r_todisstd)
        !          1373:                                                offset = oadd(offset, stdoff);
        !          1374:                                        untiltime = tadd(zp->z_untiltime,
        !          1375:                                                -offset);
        !          1376:                                }
        !          1377:                                /*
        !          1378:                                ** Find the rule (of those to do, if any)
        !          1379:                                ** that takes effect earliest in the year.
        !          1380:                                */
        !          1381:                                k = -1;
        !          1382: #ifdef lint
        !          1383:                                ktime = 0;
        !          1384: #endif /* defined lint */
        !          1385:                                for (j = 0; j < zp->z_nrules; ++j) {
        !          1386:                                        rp = &zp->z_rules[j];
        !          1387:                                        if (!rp->r_todo)
        !          1388:                                                continue;
        !          1389:                                        eats(zp->z_filename, zp->z_linenum,
        !          1390:                                                rp->r_filename, rp->r_linenum);
        !          1391:                                        offset = gmtoff;
        !          1392:                                        if (!rp->r_todisstd)
        !          1393:                                                offset = oadd(offset, stdoff);
        !          1394:                                        jtime = rp->r_temp;
        !          1395:                                        if (jtime == min_time ||
        !          1396:                                                jtime == max_time)
        !          1397:                                                        continue;
        !          1398:                                        jtime = tadd(jtime, -offset);
        !          1399:                                        if (k < 0 || jtime < ktime) {
        !          1400:                                                k = j;
        !          1401:                                                ktime = jtime;
        !          1402:                                        }
        !          1403:                                }
        !          1404:                                if (k < 0)
        !          1405:                                        break;  /* go on to next year */
        !          1406:                                rp = &zp->z_rules[k];
        !          1407:                                rp->r_todo = FALSE;
        !          1408:                                if (useuntil && ktime >= untiltime)
        !          1409:                                        break;
        !          1410:                                if (usestart) {
        !          1411:                                        if (ktime < starttime) {
        !          1412:                                                stdoff = rp->r_stdoff;
        !          1413:                                                startoff = oadd(zp->z_gmtoff,
        !          1414:                                                        rp->r_stdoff);
        !          1415:                                                (void) sprintf(startbuf,
        !          1416:                                                        zp->z_format,
        !          1417:                                                        rp->r_abbrvar);
        !          1418:                                                startisdst =
        !          1419:                                                        rp->r_stdoff != 0;
        !          1420:                                                continue;
        !          1421:                                        }
        !          1422:                                        if (ktime != starttime &&
        !          1423:                                                startisdst >= 0)
        !          1424: addtt(starttime, addtype(startoff, startbuf, startisdst, startttisstd));
        !          1425:                                        usestart = FALSE;
        !          1426:                                }
        !          1427:                                eats(zp->z_filename, zp->z_linenum,
        !          1428:                                        rp->r_filename, rp->r_linenum);
        !          1429:                                (void) sprintf(buf, zp->z_format,
        !          1430:                                        rp->r_abbrvar);
        !          1431:                                offset = oadd(zp->z_gmtoff, rp->r_stdoff);
        !          1432:                                type = addtype(offset, buf, rp->r_stdoff != 0,
        !          1433:                                        rp->r_todisstd);
        !          1434:                                if (timecnt != 0 || rp->r_stdoff != 0)
        !          1435:                                        addtt(ktime, type);
        !          1436:                                gmtoff = zp->z_gmtoff;
        !          1437:                                stdoff = rp->r_stdoff;
        !          1438:                        }
        !          1439:                }
        !          1440:                /*
        !          1441:                ** Now we may get to set starttime for the next zone line.
        !          1442:                */
        !          1443:                if (useuntil) {
        !          1444:                        starttime = tadd(zp->z_untiltime,
        !          1445:                                -gmtoffs[types[timecnt - 1]]);
        !          1446:                        startttisstd = zp->z_untilrule.r_todisstd;
        !          1447:                }
        !          1448:        }
        !          1449:        writezone(zpfirst->z_name);
        !          1450: }
        !          1451: 
        !          1452: static void
        !          1453: addtt(starttime, type)
        !          1454: const time_t   starttime;
        !          1455: const int      type;
        !          1456: {
        !          1457:        if (timecnt != 0 && type == types[timecnt - 1])
        !          1458:                return; /* easy enough! */
        !          1459:        if (timecnt >= TZ_MAX_TIMES) {
        !          1460:                error("too many transitions?!");
        !          1461:                (void) exit(EXIT_FAILURE);
        !          1462:        }
        !          1463:        ats[timecnt] = starttime;
        !          1464:        types[timecnt] = type;
        !          1465:        ++timecnt;
        !          1466: }
        !          1467: 
        !          1468: static int
        !          1469: addtype(gmtoff, abbr, isdst, ttisstd)
        !          1470: const long             gmtoff;
        !          1471: const char * const     abbr;
        !          1472: const int              isdst;
        !          1473: const int              ttisstd;
        !          1474: {
        !          1475:        register int    i, j;
        !          1476: 
        !          1477:        /*
        !          1478:        ** See if there's already an entry for this zone type.
        !          1479:        ** If so, just return its index.
        !          1480:        */
        !          1481:        for (i = 0; i < typecnt; ++i) {
        !          1482:                if (gmtoff == gmtoffs[i] && isdst == isdsts[i] &&
        !          1483:                        strcmp(abbr, &chars[abbrinds[i]]) == 0 &&
        !          1484:                        ttisstd == ttisstds[i])
        !          1485:                                return i;
        !          1486:        }
        !          1487:        /*
        !          1488:        ** There isn't one; add a new one, unless there are already too
        !          1489:        ** many.
        !          1490:        */
        !          1491:        if (typecnt >= TZ_MAX_TYPES) {
        !          1492:                error("too many local time types");
        !          1493:                (void) exit(EXIT_FAILURE);
        !          1494:        }
        !          1495:        gmtoffs[i] = gmtoff;
        !          1496:        isdsts[i] = isdst;
        !          1497:        ttisstds[i] = ttisstd;
        !          1498: 
        !          1499:        for (j = 0; j < charcnt; ++j)
        !          1500:                if (strcmp(&chars[j], abbr) == 0)
        !          1501:                        break;
        !          1502:        if (j == charcnt)
        !          1503:                newabbr(abbr);
        !          1504:        abbrinds[i] = j;
        !          1505:        ++typecnt;
        !          1506:        return i;
        !          1507: }
        !          1508: 
        !          1509: static void
        !          1510: addleap(t, positive, rolling)
        !          1511: const time_t   t;
        !          1512: const int      positive;
        !          1513: const int      rolling;
        !          1514: {
        !          1515:        register int    i, j;
        !          1516: 
        !          1517:        if (leapcnt >= TZ_MAX_LEAPS) {
        !          1518:                error("too many leap seconds");
        !          1519:                (void) exit(EXIT_FAILURE);
        !          1520:        }
        !          1521:        for (i = 0; i < leapcnt; ++i)
        !          1522:                if (t <= trans[i]) {
        !          1523:                        if (t == trans[i]) {
        !          1524:                                error("repeated leap second moment");
        !          1525:                                (void) exit(EXIT_FAILURE);
        !          1526:                        }
        !          1527:                        break;
        !          1528:                }
        !          1529:        for (j = leapcnt; j > i; --j) {
        !          1530:                trans[j] = trans[j-1];
        !          1531:                corr[j] = corr[j-1];
        !          1532:                roll[j] = roll[j-1];
        !          1533:        }
        !          1534:        trans[i] = t;
        !          1535:        corr[i] = (positive ? 1L : -1L);
        !          1536:        roll[i] = rolling;
        !          1537:        ++leapcnt;
        !          1538: }
        !          1539: 
        !          1540: static void
        !          1541: adjleap()
        !          1542: {
        !          1543:        register int    i;
        !          1544:        register long   last = 0;
        !          1545: 
        !          1546:        /*
        !          1547:        ** propagate leap seconds forward
        !          1548:        */
        !          1549:        for (i = 0; i < leapcnt; ++i) {
        !          1550:                trans[i] = tadd(trans[i], last);
        !          1551:                last = corr[i] += last;
        !          1552:        }
        !          1553: }
        !          1554: 
        !          1555: static int
        !          1556: yearistype(year, type)
        !          1557: const int              year;
        !          1558: const char * const     type;
        !          1559: {
        !          1560:        char    buf[BUFSIZ];
        !          1561:        int     result;
        !          1562: 
        !          1563:        if (type == NULL || *type == '\0')
        !          1564:                return TRUE;
        !          1565:        if (strcmp(type, "uspres") == 0)
        !          1566:                return (year % 4) == 0;
        !          1567:        if (strcmp(type, "nonpres") == 0)
        !          1568:                return (year % 4) != 0;
        !          1569:        (void) sprintf(buf, "yearistype %d %s", year, type);
        !          1570:        result = system(buf);
        !          1571:        if (result == 0)
        !          1572:                return TRUE;
        !          1573:        if (result == (1 << 8))
        !          1574:                return FALSE;
        !          1575:        error("Wild result from command execution");
        !          1576:        (void) fprintf(stderr, "%s: command was '%s', result was %d\n",
        !          1577:                progname, buf, result);
        !          1578:        for ( ; ; )
        !          1579:                (void) exit(EXIT_FAILURE);
        !          1580: }
        !          1581: 
        !          1582: static int
        !          1583: lowerit(a)
        !          1584: const int      a;
        !          1585: {
        !          1586:        return (isascii(a) && isupper(a)) ? tolower(a) : a;
        !          1587: }
        !          1588: 
        !          1589: static int
        !          1590: ciequal(ap, bp)                /* case-insensitive equality */
        !          1591: register const char *  ap;
        !          1592: register const char *  bp;
        !          1593: {
        !          1594:        while (lowerit(*ap) == lowerit(*bp++))
        !          1595:                if (*ap++ == '\0')
        !          1596:                        return TRUE;
        !          1597:        return FALSE;
        !          1598: }
        !          1599: 
        !          1600: static int
        !          1601: itsabbr(abbr, word)
        !          1602: register const char *  abbr;
        !          1603: register const char *  word;
        !          1604: {
        !          1605:        if (lowerit(*abbr) != lowerit(*word))
        !          1606:                return FALSE;
        !          1607:        ++word;
        !          1608:        while (*++abbr != '\0')
        !          1609:                do if (*word == '\0')
        !          1610:                        return FALSE;
        !          1611:                                while (lowerit(*word++) != lowerit(*abbr));
        !          1612:        return TRUE;
        !          1613: }
        !          1614: 
        !          1615: static const struct lookup *
        !          1616: byword(word, table)
        !          1617: register const char * const            word;
        !          1618: register const struct lookup * const   table;
        !          1619: {
        !          1620:        register const struct lookup *  foundlp;
        !          1621:        register const struct lookup *  lp;
        !          1622: 
        !          1623:        if (word == NULL || table == NULL)
        !          1624:                return NULL;
        !          1625:        /*
        !          1626:        ** Look for exact match.
        !          1627:        */
        !          1628:        for (lp = table; lp->l_word != NULL; ++lp)
        !          1629:                if (ciequal(word, lp->l_word))
        !          1630:                        return lp;
        !          1631:        /*
        !          1632:        ** Look for inexact match.
        !          1633:        */
        !          1634:        foundlp = NULL;
        !          1635:        for (lp = table; lp->l_word != NULL; ++lp)
        !          1636:                if (itsabbr(word, lp->l_word))
        !          1637:                        if (foundlp == NULL)
        !          1638:                                foundlp = lp;
        !          1639:                        else    return NULL;    /* multiple inexact matches */
        !          1640:        return foundlp;
        !          1641: }
        !          1642: 
        !          1643: static char **
        !          1644: getfields(cp)
        !          1645: register char *        cp;
        !          1646: {
        !          1647:        register char *         dp;
        !          1648:        register char **        array;
        !          1649:        register int            nsubs;
        !          1650: 
        !          1651:        if (cp == NULL)
        !          1652:                return NULL;
        !          1653:        array = (char **) emalloc((int) ((strlen(cp) + 1) * sizeof *array));
        !          1654:        nsubs = 0;
        !          1655:        for ( ; ; ) {
        !          1656:                while (isascii(*cp) && isspace(*cp))
        !          1657:                        ++cp;
        !          1658:                if (*cp == '\0' || *cp == '#')
        !          1659:                        break;
        !          1660:                array[nsubs++] = dp = cp;
        !          1661:                do {
        !          1662:                        if ((*dp = *cp++) != '"')
        !          1663:                                ++dp;
        !          1664:                        else while ((*dp = *cp++) != '"')
        !          1665:                                if (*dp != '\0')
        !          1666:                                        ++dp;
        !          1667:                                else    error("Odd number of quotation marks");
        !          1668:                } while (*cp != '\0' && *cp != '#' &&
        !          1669:                        (!isascii(*cp) || !isspace(*cp)));
        !          1670:                if (isascii(*cp) && isspace(*cp))
        !          1671:                        ++cp;
        !          1672:                *dp = '\0';
        !          1673:        }
        !          1674:        array[nsubs] = NULL;
        !          1675:        return array;
        !          1676: }
        !          1677: 
        !          1678: static long
        !          1679: oadd(t1, t2)
        !          1680: const long     t1;
        !          1681: const long     t2;
        !          1682: {
        !          1683:        register long   t;
        !          1684: 
        !          1685:        t = t1 + t2;
        !          1686:        if (t2 > 0 && t <= t1 || t2 < 0 && t >= t1) {
        !          1687:                error("time overflow");
        !          1688:                (void) exit(EXIT_FAILURE);
        !          1689:        }
        !          1690:        return t;
        !          1691: }
        !          1692: 
        !          1693: static time_t
        !          1694: tadd(t1, t2)
        !          1695: const time_t   t1;
        !          1696: const long     t2;
        !          1697: {
        !          1698:        register time_t t;
        !          1699: 
        !          1700:        if (t1 == max_time && t2 > 0)
        !          1701:                return max_time;
        !          1702:        if (t1 == min_time && t2 < 0)
        !          1703:                return min_time;
        !          1704:        t = t1 + t2;
        !          1705:        if (t2 > 0 && t <= t1 || t2 < 0 && t >= t1) {
        !          1706:                error("time overflow");
        !          1707:                (void) exit(EXIT_FAILURE);
        !          1708:        }
        !          1709:        return t;
        !          1710: }
        !          1711: 
        !          1712: /*
        !          1713: ** Given a rule, and a year, compute the date - in seconds since January 1,
        !          1714: ** 1970, 00:00 LOCAL time - in that year that the rule refers to.
        !          1715: */
        !          1716: 
        !          1717: static time_t
        !          1718: rpytime(rp, wantedy)
        !          1719: register const struct rule * const     rp;
        !          1720: register const int                     wantedy;
        !          1721: {
        !          1722:        register int    y, m, i;
        !          1723:        register long   dayoff;                 /* with a nod to Margaret O. */
        !          1724:        register time_t t;
        !          1725: 
        !          1726:        dayoff = 0;
        !          1727:        m = TM_JANUARY;
        !          1728:        y = EPOCH_YEAR;
        !          1729:        while (wantedy != y) {
        !          1730:                if (wantedy > y) {
        !          1731:                        i = len_years[isleap(y)];
        !          1732:                        ++y;
        !          1733:                } else {
        !          1734:                        --y;
        !          1735:                        i = -len_years[isleap(y)];
        !          1736:                }
        !          1737:                dayoff = oadd(dayoff, eitol(i));
        !          1738:        }
        !          1739:        while (m != rp->r_month) {
        !          1740:                i = len_months[isleap(y)][m];
        !          1741:                dayoff = oadd(dayoff, eitol(i));
        !          1742:                ++m;
        !          1743:        }
        !          1744:        i = rp->r_dayofmonth;
        !          1745:        if (m == TM_FEBRUARY && i == 29 && !isleap(y)) {
        !          1746:                if (rp->r_dycode == DC_DOWLEQ)
        !          1747:                        --i;
        !          1748:                else {
        !          1749:                        error("use of 2/29 in non leap-year");
        !          1750:                        (void) exit(EXIT_FAILURE);
        !          1751:                }
        !          1752:        }
        !          1753:        --i;
        !          1754:        dayoff = oadd(dayoff, eitol(i));
        !          1755:        if (rp->r_dycode == DC_DOWGEQ || rp->r_dycode == DC_DOWLEQ) {
        !          1756:                register long   wday;
        !          1757: 
        !          1758: #define LDAYSPERWEEK   ((long) DAYSPERWEEK)
        !          1759:                wday = eitol(EPOCH_WDAY);
        !          1760:                /*
        !          1761:                ** Don't trust mod of negative numbers.
        !          1762:                */
        !          1763:                if (dayoff >= 0)
        !          1764:                        wday = (wday + dayoff) % LDAYSPERWEEK;
        !          1765:                else {
        !          1766:                        wday -= ((-dayoff) % LDAYSPERWEEK);
        !          1767:                        if (wday < 0)
        !          1768:                                wday += LDAYSPERWEEK;
        !          1769:                }
        !          1770:                while (wday != eitol(rp->r_wday))
        !          1771:                        if (rp->r_dycode == DC_DOWGEQ) {
        !          1772:                                dayoff = oadd(dayoff, (long) 1);
        !          1773:                                if (++wday >= LDAYSPERWEEK)
        !          1774:                                        wday = 0;
        !          1775:                                ++i;
        !          1776:                        } else {
        !          1777:                                dayoff = oadd(dayoff, (long) -1);
        !          1778:                                if (--wday < 0)
        !          1779:                                        wday = LDAYSPERWEEK;
        !          1780:                                --i;
        !          1781:                        }
        !          1782:                if (i < 0 || i >= len_months[isleap(y)][m]) {
        !          1783:                        error("no day in month matches rule");
        !          1784:                        (void) exit(EXIT_FAILURE);
        !          1785:                }
        !          1786:        }
        !          1787:        if (dayoff < 0 && !tt_signed) {
        !          1788:                if (wantedy == rp->r_loyear)
        !          1789:                        return min_time;
        !          1790:                error("time before zero");
        !          1791:                (void) exit(EXIT_FAILURE);
        !          1792:        }
        !          1793:        t = (time_t) dayoff * SECSPERDAY;
        !          1794:        /*
        !          1795:        ** Cheap overflow check.
        !          1796:        */
        !          1797:        if (t / SECSPERDAY != dayoff) {
        !          1798:                if (wantedy == rp->r_hiyear)
        !          1799:                        return max_time;
        !          1800:                if (wantedy == rp->r_loyear)
        !          1801:                        return min_time;
        !          1802:                error("time overflow");
        !          1803:                (void) exit(EXIT_FAILURE);
        !          1804:        }
        !          1805:        return tadd(t, rp->r_tod);
        !          1806: }
        !          1807: 
        !          1808: static void
        !          1809: newabbr(string)
        !          1810: const char * const     string;
        !          1811: {
        !          1812:        register int    i;
        !          1813: 
        !          1814:        i = strlen(string) + 1;
        !          1815:        if (charcnt + i >= TZ_MAX_CHARS) {
        !          1816:                error("too many, or too long, time zone abbreviations");
        !          1817:                (void) exit(EXIT_FAILURE);
        !          1818:        }
        !          1819:        (void) strcpy(&chars[charcnt], string);
        !          1820:        charcnt += eitol(i);
        !          1821: }
        !          1822: 
        !          1823: static int
        !          1824: mkdirs(name)
        !          1825: char * const   name;
        !          1826: {
        !          1827:        register char * cp;
        !          1828: 
        !          1829:        if ((cp = name) == NULL || *cp == '\0')
        !          1830:                return 0;
        !          1831:        while ((cp = strchr(cp + 1, '/')) != 0) {
        !          1832:                *cp = '\0';
        !          1833: #ifndef unix
        !          1834:                /*
        !          1835:                ** MS-DOS drive specifier?
        !          1836:                */
        !          1837:                if (strlen(name) == 2 && isascii(name[0]) &&
        !          1838:                        isalpha(name[0]) && name[1] == ':') {
        !          1839:                                *cp = '/';
        !          1840:                                continue;
        !          1841:                }
        !          1842: #endif /* !defined unix */
        !          1843:                if (!itsdir(name)) {
        !          1844:                        /*
        !          1845:                        ** It doesn't seem to exist, so we try to create it.
        !          1846:                        */
        !          1847:                        if (emkdir(name, 0755) != 0) {
        !          1848:                                (void) fprintf(stderr,
        !          1849:                                        "%s: Can't create directory ",
        !          1850:                                        progname);
        !          1851:                                (void) perror(name);
        !          1852:                                return -1;
        !          1853:                        }
        !          1854:                }
        !          1855:                *cp = '/';
        !          1856:        }
        !          1857:        return 0;
        !          1858: }
        !          1859: 
        !          1860: static long
        !          1861: eitol(i)
        !          1862: const int      i;
        !          1863: {
        !          1864:        long    l;
        !          1865: 
        !          1866:        l = i;
        !          1867:        if (i < 0 && l >= 0 || i == 0 && l != 0 || i > 0 && l <= 0) {
        !          1868:                (void) fprintf(stderr, "%s: %d did not sign extend correctly\n",
        !          1869:                        progname, i);
        !          1870:                (void) exit(EXIT_FAILURE);
        !          1871:        }
        !          1872:        return l;
        !          1873: }
        !          1874: 
        !          1875: /*
        !          1876: ** UNIX is a registered trademark of AT&T.
        !          1877: */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.