zic.c
来自「一个C源代码分析器」· C语言 代码 · 共 1,940 行 · 第 1/3 页
C
1,940 行
(fwrite_size_t) timecnt, fp); for (i = 0; i < typecnt; ++i) { puttzcode((long) gmtoffs[i], fp); (void) putc(isdsts[i], fp); (void) putc(abbrinds[i], fp); } if (charcnt != 0) (void) fwrite((genericptr_t) chars, (fwrite_size_t) sizeof chars[0], (fwrite_size_t) charcnt, fp); for (i = 0; i < leapcnt; ++i) { if (roll[i]) { if (timecnt == 0 || trans[i] < ats[0]) { j = 0; while (isdsts[j]) if (++j >= typecnt) { j = 0; break; } } else { j = 1; while (j < timecnt && trans[i] >= ats[j]) ++j; j = types[j - 1]; } puttzcode((long) tadd(trans[i], -gmtoffs[j]), fp); } else puttzcode((long) trans[i], fp); puttzcode((long) corr[i], fp); } for (i = 0; i < typecnt; ++i) (void) putc(ttisstds[i], fp); if (ferror(fp) || fclose(fp)) { (void) fprintf(stderr, "%s: Write error on ", progname); (void) perror(fullname); (void) exit(EXIT_FAILURE); }}static voidoutzone(zpfirst, zonecount)const struct zone * const zpfirst;const int zonecount;{ register const struct zone * zp; register struct rule * rp; register int i, j; register int usestart, useuntil; register time_t starttime, untiltime; register long gmtoff; register long stdoff; register int year; register long startoff; register int startisdst; register int startttisstd; register int type; char startbuf[BUFSIZ]; /* ** Now. . .finally. . .generate some useful data! */ timecnt = 0; typecnt = 0; charcnt = 0; /* ** A guess that may well be corrected later. */ stdoff = 0; /* ** Thanks to Earl Chew (earl@dnd.icp.nec.com.au) ** for noting the need to unconditionally initialize startttisstd. */ startttisstd = FALSE;#ifdef lint starttime = 0;#endif /* defined lint */ for (i = 0; i < zonecount; ++i) { zp = &zpfirst[i]; usestart = i > 0 && (zp - 1)->z_untiltime > min_time; useuntil = i < (zonecount - 1); if (useuntil && zp->z_untiltime <= min_time) continue; gmtoff = zp->z_gmtoff; eat(zp->z_filename, zp->z_linenum); startisdst = -1; if (zp->z_nrules == 0) { stdoff = zp->z_stdoff; (void) strcpy(startbuf, zp->z_format); type = addtype(oadd(zp->z_gmtoff, stdoff), startbuf, stdoff != 0, startttisstd); if (usestart) addtt(starttime, type); else if (stdoff != 0) addtt(min_time, type); } else for (year = min_year; year <= max_year; ++year) { if (useuntil && year > zp->z_untilrule.r_hiyear) break; /* ** Mark which rules to do in the current year. ** For those to do, calculate rpytime(rp, year); */ for (j = 0; j < zp->z_nrules; ++j) { rp = &zp->z_rules[j]; eats(zp->z_filename, zp->z_linenum, rp->r_filename, rp->r_linenum); rp->r_todo = year >= rp->r_loyear && year <= rp->r_hiyear && yearistype(year, rp->r_yrtype); if (rp->r_todo) rp->r_temp = rpytime(rp, year); } for ( ; ; ) { register int k; register time_t jtime, ktime; register long offset; char buf[BUFSIZ]; if (useuntil) { /* ** Turn untiltime into GMT ** assuming the current gmtoff and ** stdoff values. */ untiltime = tadd(zp->z_untiltime, -gmtoff); if (!zp->z_untilrule.r_todisstd) untiltime = tadd(untiltime, -stdoff); } /* ** Find the rule (of those to do, if any) ** that takes effect earliest in the year. */ k = -1;#ifdef lint ktime = 0;#endif /* defined lint */ for (j = 0; j < zp->z_nrules; ++j) { rp = &zp->z_rules[j]; if (!rp->r_todo) continue; eats(zp->z_filename, zp->z_linenum, rp->r_filename, rp->r_linenum); offset = gmtoff; if (!rp->r_todisstd) offset = oadd(offset, stdoff); jtime = rp->r_temp; if (jtime == min_time || jtime == max_time) continue; jtime = tadd(jtime, -offset); if (k < 0 || jtime < ktime) { k = j; ktime = jtime; } } if (k < 0) break; /* go on to next year */ rp = &zp->z_rules[k]; rp->r_todo = FALSE; if (useuntil && ktime >= untiltime) break; if (usestart) { if (ktime < starttime) { stdoff = rp->r_stdoff; startoff = oadd(zp->z_gmtoff, rp->r_stdoff); (void) sprintf(startbuf, zp->z_format, rp->r_abbrvar); startisdst = rp->r_stdoff != 0; continue; } usestart = FALSE; if (ktime != starttime) { if (startisdst < 0 && zp->z_gmtoff != (zp - 1)->z_gmtoff) { type = (timecnt == 0) ? 0 : types[timecnt - 1]; startoff = oadd(gmtoffs[type], -(zp - 1)->z_gmtoff); startisdst = startoff != 0; startoff = oadd(startoff, zp->z_gmtoff); (void) strcpy(startbuf, &chars[abbrinds[type]]); } if (startisdst >= 0)addtt(starttime, addtype(startoff, startbuf, startisdst, startttisstd)); } } eats(zp->z_filename, zp->z_linenum, rp->r_filename, rp->r_linenum); (void) sprintf(buf, zp->z_format, rp->r_abbrvar); offset = oadd(zp->z_gmtoff, rp->r_stdoff); type = addtype(offset, buf, rp->r_stdoff != 0, rp->r_todisstd); addtt(ktime, type); stdoff = rp->r_stdoff; } } /* ** Now we may get to set starttime for the next zone line. */ if (useuntil) { starttime = tadd(zp->z_untiltime, -gmtoff); startttisstd = zp->z_untilrule.r_todisstd; if (!startttisstd) starttime = tadd(starttime, -stdoff); } } writezone(zpfirst->z_name);}static voidaddtt(starttime, type)const time_t starttime;const int type;{ if (timecnt != 0 && type == types[timecnt - 1]) return; /* easy enough! */ if (timecnt == 0 && type == 0 && isdsts[0] == 0) return; /* handled by default rule */ if (timecnt >= TZ_MAX_TIMES) { error("too many transitions?!"); (void) exit(EXIT_FAILURE); } ats[timecnt] = starttime; types[timecnt] = type; ++timecnt;}static intaddtype(gmtoff, abbr, isdst, ttisstd)const long gmtoff;const char * const abbr;const int isdst;const int ttisstd;{ register int i, j; /* ** See if there's already an entry for this zone type. ** If so, just return its index. */ for (i = 0; i < typecnt; ++i) { if (gmtoff == gmtoffs[i] && isdst == isdsts[i] && strcmp(abbr, &chars[abbrinds[i]]) == 0 && ttisstd == ttisstds[i]) return i; } /* ** There isn't one; add a new one, unless there are already too ** many. */ if (typecnt >= TZ_MAX_TYPES) { error("too many local time types"); (void) exit(EXIT_FAILURE); } gmtoffs[i] = gmtoff; isdsts[i] = isdst; ttisstds[i] = ttisstd; for (j = 0; j < charcnt; ++j) if (strcmp(&chars[j], abbr) == 0) break; if (j == charcnt) newabbr(abbr); abbrinds[i] = j; ++typecnt; return i;}static voidleapadd(t, positive, rolling, count)const time_t t;const int positive;const int rolling;int count;{ register int i, j; if (leapcnt + (positive ? count : 1) > TZ_MAX_LEAPS) { error("too many leap seconds"); (void) exit(EXIT_FAILURE); } for (i = 0; i < leapcnt; ++i) if (t <= trans[i]) { if (t == trans[i]) { error("repeated leap second moment"); (void) exit(EXIT_FAILURE); } break; } do { for (j = leapcnt; j > i; --j) { trans[j] = trans[j - 1]; corr[j] = corr[j - 1]; roll[j] = roll[j - 1]; } trans[i] = t; corr[i] = positive ? 1L : eitol(-count); roll[i] = rolling; ++leapcnt; } while (positive && --count != 0);}static voidadjleap(){ register int i; register long last = 0; /* ** propagate leap seconds forward */ for (i = 0; i < leapcnt; ++i) { trans[i] = tadd(trans[i], last); last = corr[i] += last; }}static intyearistype(year, type)const int year;const char * const type;{ static char * buf; int result; if (type == NULL || *type == '\0') return TRUE; if (strcmp(type, "uspres") == 0) return (year % 4) == 0; if (strcmp(type, "nonpres") == 0) return (year % 4) != 0; buf = erealloc(buf, 132 + strlen(yitcommand) + strlen(type)); (void) sprintf(buf, "%s %d %s", yitcommand, year, type); result = system(buf); if (result == 0) return TRUE; if (result == (1 << 8)) return FALSE; error("Wild result from command execution"); (void) fprintf(stderr, "%s: command was '%s', result was %d\n", progname, buf, result); for ( ; ; ) (void) exit(EXIT_FAILURE);}static intlowerit(a)const int a;{ return (isascii(a) && isupper(a)) ? tolower(a) : a;}static intciequal(ap, bp) /* case-insensitive equality */register const char * ap;register const char * bp;{ while (lowerit(*ap) == lowerit(*bp++)) if (*ap++ == '\0') return TRUE; return FALSE;}static intitsabbr(abbr, word)register const char * abbr;register const char * word;{ if (lowerit(*abbr) != lowerit(*word)) return FALSE; ++word; while (*++abbr != '\0') do if (*word == '\0') return FALSE; while (lowerit(*word++) != lowerit(*abbr)); return TRUE;}static const struct lookup *byword(word, table)register const char * const word;register const struct lookup * const table;{ register const struct lookup * foundlp; register const struct lookup * lp; if (word == NULL || table == NULL) return NULL; /* ** Look for exact match. */ for (lp = table; lp->l_word != NULL; ++lp) if (ciequal(word, lp->l_word)) return lp; /* ** Look for inexact match. */ foundlp = NULL; for (lp = table; lp->l_word != NULL; ++lp) if (itsabbr(word, lp->l_word)) if (foundlp == NULL) foundlp = lp; else return NULL; /* multiple inexact matches */ return foundlp;}static char **getfields(cp)register char * cp;{ register char * dp; register char ** array; register int nsubs; if (cp == NULL) return NULL; array = (char **) emalloc((int) ((strlen(cp) + 1) * sizeof *array)); nsubs = 0; for ( ; ; ) { while (isascii(*cp) && isspace(*cp)) ++cp; if (*cp == '\0' || *cp == '#') break; array[nsubs++] = dp = cp; do { if ((*dp = *cp++) != '"') ++dp; else while ((*dp = *cp++) != '"') if (*dp != '\0') ++dp; else error("Odd number of quotation marks"); } while (*cp != '\0' && *cp != '#' && (!isascii(*cp) || !isspace(*cp))); if (isascii(*cp) && isspace(*cp)) ++cp; *dp = '\0'; } array[nsubs] = NULL; return array;}static longoadd(t1, t2)const long t1;const long t2;{ register long t; t = t1 + t2; if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) { error("time overflow"); (void) exit(EXIT_FAILURE); } return t;}static time_ttadd(t1, t2)const time_t t1;const long t2;{ register time_t t; if (t1 == max_time && t2 > 0) return max_time; if (t1 == min_time && t2 < 0) return min_time; t = t1 + t2; if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) { error("time overflow"); (void) exit(EXIT_FAILURE); } return t;}/*** Given a rule, and a year, compute the date - in seconds since January 1,** 1970, 00:00 LOCAL time - in that year that the rule refers to.*/static time_trpytime(rp, wantedy)register const struct rule * const rp;register const int wantedy;{ register int y, m, i; register long dayoff; /* with a nod to Margaret O. */ register time_t t; if (wantedy == min_int) return min_time; if (wantedy == max_int) return max_time; dayoff = 0; m = TM_JANUARY; y = EPOCH_YEAR; while (wantedy != y) { if (wantedy > y) { i = len_years[isleap(y)]; ++y; } else { --y; i = -len_years[isleap(y)]; } dayoff = oadd(dayoff, eitol(i)); } while (m != rp->r_month) { i = len_months[isleap(y)][m]; dayoff = oadd(dayoff, eitol(i)); ++m; } i = rp->r_dayofmonth; if (m == TM_FEBRUARY && i == 29 && !isleap(y)) { if (rp->r_dycode == DC_DOWLEQ) --i; else { error("use of 2/29 in non leap-year"); (void) exit(EXIT_FAILURE); } } --i; dayoff = oadd(dayoff, eitol(i)); if (rp->r_dycode == DC_DOWGEQ || rp->r_dycode == DC_DOWLEQ) { register long wday;#define LDAYSPERWEEK ((long) DAYSPERWEEK) wday = eitol(EPOCH_WDAY); /* ** Don't trust mod of negative numbers. */ if (dayoff >= 0) wday = (wday + dayoff) % LDAYSPERWEEK; else { wday -= ((-dayoff) % LDAYSPERWEEK); if (wday < 0) wday += LDAYSPERWEEK; } while (wday != eitol(rp->r_wday)) if (rp->r_dycode == DC_DOWGEQ) { dayoff = oadd(dayoff, (long) 1); if (++wday >= LDAYSPERWEEK) wday = 0; ++i; } else { dayoff = oadd(dayoff, (long) -1); if (--wday < 0) wday = LDAYSPERWEEK - 1; --i; } if (i < 0 || i >= len_months[isleap(y)][m]) { error("no day in month matches rule"); (void) exit(EXIT_FAILURE); } } if (dayoff < 0 && !tt_signed) return min_time; t = (time_t) dayoff * SECSPERDAY; /* ** Cheap overflow check. */ if (t / SECSPERDAY != dayoff) return (dayoff > 0) ? max_time : min_time; return tadd(t, rp->r_tod);}static voidnewabbr(string)const char * const string;{ register int i; i = strlen(string) + 1; if (charcnt + i > TZ_MAX_CHARS) { error("too many, or too long, time zone abbreviations"); (void) exit(EXIT_FAILURE); } (void) strcpy(&chars[charcnt], string); charcnt += eitol(i);}static intmkdirs(argname)char * const argname;{ register char * name; register char * cp; if (argname == NULL || *argname == '\0') return 0; cp = name = ecpyalloc(argname); while ((cp = strchr(cp + 1, '/')) != 0) { *cp = '\0';#ifndef unix /* ** MS-DOS drive specifier? */ if (strlen(name) == 2 && isascii(name[0]) && isalpha(name[0]) && name[1] == ':') { *cp = '/'; continue; }#endif /* !defined unix */ if (!itsdir(name)) { /* ** It doesn't seem to exist, so we try to create it. */ if (emkdir(name, 0755) != 0) { (void) fprintf(stderr, "%s: Can't create directory ", progname); (void) perror(name); ifree(name); return -1; } } *cp = '/'; } ifree(name); return 0;}static longeitol(i)const int i;{ long l; l = i; if ((i < 0 && l >= 0) || (i == 0 && l != 0) || (i > 0 && l <= 0)) { (void) fprintf(stderr, "%s: %d did not sign extend correctly\n", progname, i); (void) exit(EXIT_FAILURE); } return l;}/*** UNIX is a registered trademark of AT&T.*/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?