zic.c
来自「一个C源代码分析器」· C语言 代码 · 共 1,940 行 · 第 1/3 页
C
1,940 行
#ifndef lint#ifndef NOIDstatic char elsieid[] = "@(#)zic.c 7.22";#endif /* !defined NOID */#endif /* !defined lint */#include "private.h"#include "tzfile.h"struct rule { const char * r_filename; int r_linenum; const char * r_name; int r_loyear; /* for example, 1986 */ int r_hiyear; /* for example, 1986 */ const char * r_yrtype; int r_month; /* 0..11 */ int r_dycode; /* see below */ int r_dayofmonth; int r_wday; long r_tod; /* time from midnight */ int r_todisstd; /* above is standard time if TRUE */ /* or wall clock time if FALSE */ long r_stdoff; /* offset from standard time */ const char * r_abbrvar; /* variable part of abbreviation */ int r_todo; /* a rule to do (used in outzone) */ time_t r_temp; /* used in outzone */};/*** r_dycode r_dayofmonth r_wday*/#define DC_DOM 0 /* 1..31 */ /* unused */#define DC_DOWGEQ 1 /* 1..31 */ /* 0..6 (Sun..Sat) */#define DC_DOWLEQ 2 /* 1..31 */ /* 0..6 (Sun..Sat) */struct zone { const char * z_filename; int z_linenum; const char * z_name; long z_gmtoff; const char * z_rule; const char * z_format; long z_stdoff; struct rule * z_rules; int z_nrules; struct rule z_untilrule; time_t z_untiltime;};extern int emkdir P((const char * name, int mode));extern int getopt P((int argc, char * argv[], const char * options));extern char * icatalloc P((char * old, const char * new));extern char * icpyalloc P((const char * string));extern void ifree P((char * p));extern char * imalloc P((int n));extern char * irealloc P((char * old, int n));extern int link P((const char * fromname, const char * toname));extern char * optarg;extern int optind;extern char * scheck P((const char * string, const char * format));static void addtt P((time_t starttime, int type));static int addtype P((long gmtoff, const char * abbr, int isdst, int ttisstd));static void leapadd P((time_t t, int positive, int rolling, int count));static void adjleap P((void));static void associate P((void));static int ciequal P((const char * ap, const char * bp));static void convert P((long val, char * buf));static void dolink P((const char * fromfile, const char * tofile));static void eat P((const char * name, int num));static void eats P((const char * name, int num, const char * rname, int rnum));static long eitol P((int i));static void error P((const char * message));static char ** getfields P((char * buf));static long gethms P((const char * string, const char * errstrng, int signable));static void infile P((const char * filename));static void inleap P((char ** fields, int nfields));static void inlink P((char ** fields, int nfields));static void inrule P((char ** fields, int nfields));static int inzcont P((char ** fields, int nfields));static int inzone P((char ** fields, int nfields));static int inzsub P((char ** fields, int nfields, int iscont));static int itsabbr P((const char * abbr, const char * word));static int itsdir P((const char * name));static int lowerit P((int c));static char * memcheck P((char * tocheck));static int mkdirs P((char * filename));static void newabbr P((const char * abbr));static long oadd P((long t1, long t2));static void outzone P((const struct zone * zp, int ntzones));static void puttzcode P((long code, FILE * fp));static int rcomp P((const genericptr_t leftp, const genericptr_t rightp));static time_t rpytime P((const struct rule * rp, int wantedy));static void rulesub P((struct rule * rp, char * loyearp, char * hiyearp, char * typep, char * monthp, char * dayp, char * timep));static void setboundaries P((void));static time_t tadd P((time_t t1, long t2));static void usage P((void));static void writezone P((const char * name));static int yearistype P((int year, const char * type));static int charcnt;static int errors;static const char * filename;static int leapcnt;static int linenum;static int max_int;static time_t max_time;static int max_year;static int min_int;static time_t min_time;static int min_year;static int noise;static const char * rfilename;static int rlinenum;static const char * progname;static int timecnt;static int typecnt;static int tt_signed;/*** Line codes.*/#define LC_RULE 0#define LC_ZONE 1#define LC_LINK 2#define LC_LEAP 3/*** Which fields are which on a Zone line.*/#define ZF_NAME 1#define ZF_GMTOFF 2#define ZF_RULE 3#define ZF_FORMAT 4#define ZF_TILYEAR 5#define ZF_TILMONTH 6#define ZF_TILDAY 7#define ZF_TILTIME 8#define ZONE_MINFIELDS 5#define ZONE_MAXFIELDS 9/*** Which fields are which on a Zone continuation line.*/#define ZFC_GMTOFF 0#define ZFC_RULE 1#define ZFC_FORMAT 2#define ZFC_TILYEAR 3#define ZFC_TILMONTH 4#define ZFC_TILDAY 5#define ZFC_TILTIME 6#define ZONEC_MINFIELDS 3#define ZONEC_MAXFIELDS 7/*** Which files are which on a Rule line.*/#define RF_NAME 1#define RF_LOYEAR 2#define RF_HIYEAR 3#define RF_COMMAND 4#define RF_MONTH 5#define RF_DAY 6#define RF_TOD 7#define RF_STDOFF 8#define RF_ABBRVAR 9#define RULE_FIELDS 10/*** Which fields are which on a Link line.*/#define LF_FROM 1#define LF_TO 2#define LINK_FIELDS 3/*** Which fields are which on a Leap line.*/#define LP_YEAR 1#define LP_MONTH 2#define LP_DAY 3#define LP_TIME 4#define LP_CORR 5#define LP_ROLL 6#define LEAP_FIELDS 7/*** Year synonyms.*/#define YR_MINIMUM 0#define YR_MAXIMUM 1#define YR_ONLY 2static struct rule * rules;static int nrules; /* number of rules */static struct zone * zones;static int nzones; /* number of zones */struct link { const char * l_filename; int l_linenum; const char * l_from; const char * l_to;};static struct link * links;static int nlinks;struct lookup { const char * l_word; const int l_value;};static struct lookup const * byword P((const char * string, const struct lookup * lp));static struct lookup const line_codes[] = { { "Rule", LC_RULE }, { "Zone", LC_ZONE }, { "Link", LC_LINK }, { "Leap", LC_LEAP }, { NULL, 0}};static struct lookup const mon_names[] = { { "January", TM_JANUARY }, { "February", TM_FEBRUARY }, { "March", TM_MARCH }, { "April", TM_APRIL }, { "May", TM_MAY }, { "June", TM_JUNE }, { "July", TM_JULY }, { "August", TM_AUGUST }, { "September", TM_SEPTEMBER }, { "October", TM_OCTOBER }, { "November", TM_NOVEMBER }, { "December", TM_DECEMBER }, { NULL, 0 }};static struct lookup const wday_names[] = { { "Sunday", TM_SUNDAY }, { "Monday", TM_MONDAY }, { "Tuesday", TM_TUESDAY }, { "Wednesday", TM_WEDNESDAY }, { "Thursday", TM_THURSDAY }, { "Friday", TM_FRIDAY }, { "Saturday", TM_SATURDAY }, { NULL, 0 }};static struct lookup const lasts[] = { { "last-Sunday", TM_SUNDAY }, { "last-Monday", TM_MONDAY }, { "last-Tuesday", TM_TUESDAY }, { "last-Wednesday", TM_WEDNESDAY }, { "last-Thursday", TM_THURSDAY }, { "last-Friday", TM_FRIDAY }, { "last-Saturday", TM_SATURDAY }, { NULL, 0 }};static struct lookup const begin_years[] = { { "minimum", YR_MINIMUM }, { "maximum", YR_MAXIMUM }, { NULL, 0 }};static struct lookup const end_years[] = { { "minimum", YR_MINIMUM }, { "maximum", YR_MAXIMUM }, { "only", YR_ONLY }, { NULL, 0 }};static struct lookup const leap_types[] = { { "Rolling", TRUE }, { "Stationary", FALSE }, { NULL, 0 }};static const int len_months[2][MONSPERYEAR] = { { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }};static const int len_years[2] = { DAYSPERNYEAR, DAYSPERLYEAR};static time_t ats[TZ_MAX_TIMES];static unsigned char types[TZ_MAX_TIMES];static long gmtoffs[TZ_MAX_TYPES];static char isdsts[TZ_MAX_TYPES];static unsigned char abbrinds[TZ_MAX_TYPES];static char ttisstds[TZ_MAX_TYPES];static char chars[TZ_MAX_CHARS];static time_t trans[TZ_MAX_LEAPS];static long corr[TZ_MAX_LEAPS];static char roll[TZ_MAX_LEAPS];/*** Memory allocation.*/static char *memcheck(ptr)char * const ptr;{ if (ptr == NULL) { (void) perror(progname); (void) exit(EXIT_FAILURE); } return ptr;}#define emalloc(size) memcheck(imalloc(size))#define erealloc(ptr, size) memcheck(irealloc(ptr, size))#define ecpyalloc(ptr) memcheck(icpyalloc(ptr))#define ecatalloc(oldp, newp) memcheck(icatalloc(oldp, newp))/*** Error handling.*/static voideats(name, num, rname, rnum)const char * const name;const int num;const char * const rname;const int rnum;{ filename = name; linenum = num; rfilename = rname; rlinenum = rnum;}static voideat(name, num)const char * const name;const int num;{ eats(name, num, (char *) NULL, -1);}static voiderror(string)const char * const string;{ /* ** Match the format of "cc" to allow sh users to ** zic ... 2>&1 | error -t "*" -v ** on BSD systems. */ (void) fprintf(stderr, "\"%s\", line %d: %s", filename, linenum, string); if (rfilename != NULL) (void) fprintf(stderr, " (rule from \"%s\", line %d)", rfilename, rlinenum); (void) fprintf(stderr, "\n"); ++errors;}static voidusage(){ (void) fprintf(stderr,"%s: usage is %s [ -s ] [ -v ] [ -l localtime ] [ -p posixrules ] [ -d directory ] \n\\t[ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n", progname, progname); (void) exit(EXIT_FAILURE);}static const char * psxrules;static const char * lcltime;static const char * directory;static const char * leapsec;static const char * yitcommand;static int sflag = FALSE;intmain(argc, argv)int argc;char * argv[];{ register int i, j; register int c;#ifdef unix (void) umask(umask(022) | 022);#endif /* defined unix */ progname = argv[0]; while ((c = getopt(argc, argv, "d:l:p:L:vsy:")) != EOF) switch (c) { default: usage(); case 'd': if (directory == NULL) directory = optarg; else { (void) fprintf(stderr,"%s: More than one -d option specified\n", progname); (void) exit(EXIT_FAILURE); } break; case 'l': if (lcltime == NULL) lcltime = optarg; else { (void) fprintf(stderr,"%s: More than one -l option specified\n", progname); (void) exit(EXIT_FAILURE); } break; case 'p': if (psxrules == NULL) psxrules = optarg; else { (void) fprintf(stderr,"%s: More than one -p option specified\n", progname); (void) exit(EXIT_FAILURE); } break; case 'y': if (yitcommand == NULL) yitcommand = optarg; else { (void) fprintf(stderr,"%s: More than one -y option specified\n", progname); (void) exit(EXIT_FAILURE); } break; case 'L': if (leapsec == NULL) leapsec = optarg; else { (void) fprintf(stderr,"%s: More than one -L option specified\n", progname); (void) exit(EXIT_FAILURE); } break; case 'v': noise = TRUE; break; case 's': sflag = TRUE; break; } if (optind == argc - 1 && strcmp(argv[optind], "=") == 0) usage(); /* usage message by request */ if (directory == NULL) directory = TZDIR; if (yitcommand == NULL) yitcommand = "yearistype"; setboundaries(); if (optind < argc && leapsec != NULL) { infile(leapsec); adjleap(); } zones = (struct zone *) emalloc(0); rules = (struct rule *) emalloc(0); links = (struct link *) emalloc(0); for (i = optind; i < argc; ++i) infile(argv[i]); if (errors) (void) exit(EXIT_FAILURE); associate(); for (i = 0; i < nzones; i = j) { /* ** Find the next non-continuation zone entry. */ for (j = i + 1; j < nzones && zones[j].z_name == NULL; ++j) continue; outzone(&zones[i], j - i); } /* ** Make links. */ for (i = 0; i < nlinks; ++i) dolink(links[i].l_from, links[i].l_to); if (lcltime != NULL) dolink(lcltime, TZDEFAULT); if (psxrules != NULL) dolink(psxrules, TZDEFRULES); return (errors == 0) ? EXIT_SUCCESS : EXIT_FAILURE;}static voiddolink(fromfile, tofile)const char * const fromfile;const char * const tofile;{ register char * fromname; register char * toname; if (fromfile[0] == '/') fromname = fromfile; else { fromname = ecpyalloc(directory); fromname = ecatalloc(fromname, "/"); fromname = ecatalloc(fromname, fromfile); } if (tofile[0] == '/') toname = tofile; else { toname = ecpyalloc(directory); toname = ecatalloc(toname, "/"); toname = ecatalloc(toname, tofile); } /* ** We get to be careful here since ** there's a fair chance of root running us. */ if (!itsdir(toname)) (void) remove(toname); if (link(fromname, toname) != 0) { if (mkdirs(toname) != 0) (void) exit(EXIT_FAILURE); if (link(fromname, toname) != 0) { (void) fprintf(stderr, "%s: Can't link from %s to ", progname, fromname); (void) perror(toname); (void) exit(EXIT_FAILURE); } } if (fromname != fromfile) ifree(fromname); if (toname != tofile) ifree(toname);}static voidsetboundaries(){ register time_t bit; register int bii; for (bit = 1; bit > 0; bit <<= 1) continue; if (bit == 0) { /* time_t is an unsigned type */ tt_signed = FALSE; min_time = 0; max_time = ~(time_t) 0; if (sflag) max_time >>= 1; } else { tt_signed = TRUE; min_time = bit; max_time = bit; ++max_time; max_time = -max_time; if (sflag) min_time = 0; } min_year = TM_YEAR_BASE + gmtime(&min_time)->tm_year; max_year = TM_YEAR_BASE + gmtime(&max_time)->tm_year; for (bii = 1; bii > 0; bii <<= 1) continue; min_int = bii; max_int = -1 - bii;}static intitsdir(name)const char * const name;{ register char * myname; register int accres; myname = ecpyalloc(name); myname = ecatalloc(myname, "/."); accres = access(myname, 0); ifree(myname); return accres == 0;}/*** Associate sets of rules with zones.*//*** Sort by rule name.*/static intrcomp(cp1, cp2)const genericptr_t cp1;const genericptr_t cp2;{ return strcmp(((struct rule *) cp1)->r_name, ((struct rule *) cp2)->r_name);}static voidassociate(){ register struct zone * zp; register struct rule * rp; register int base, out; register int i; if (nrules != 0) (void) qsort((genericptr_t) rules, (qsort_size_t) nrules, (qsort_size_t) sizeof *rules, rcomp); for (i = 0; i < nzones; ++i) { zp = &zones[i]; zp->z_rules = NULL; zp->z_nrules = 0; } for (base = 0; base < nrules; base = out) { rp = &rules[base];
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?