📄 zic.c
字号:
(void) perror(fullname); (void) exit(EXIT_FAILURE); } } convert(eitol(typecnt), tzh.tzh_ttisstdcnt); convert(eitol(leapcnt), tzh.tzh_leapcnt); convert(eitol(timecnt), tzh.tzh_timecnt); convert(eitol(typecnt), tzh.tzh_typecnt); convert(eitol(charcnt), tzh.tzh_charcnt); (void) fwrite((void *) &tzh, (size_t) sizeof tzh, (size_t) 1, fp); for (i = 0; i < timecnt; ++i) { j = leapcnt; while (--j >= 0) if (ats[i] >= trans[j]) { ats[i] = tadd(ats[i], corr[j]); break; } puttzcode((long) ats[i], fp); } if (timecnt > 0) (void) fwrite((void *) types, (size_t) sizeof types[0], (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((void *) chars, (size_t) sizeof chars[0], (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; /* ** Two guesses. . .the second may well be corrected later. */ gmtoff = zpfirst->z_gmtoff; stdoff = 0; starttime = 0; startttisstd = FALSE; for (i = 0; i < zonecount; ++i) { usestart = i > 0; useuntil = i < (zonecount - 1); zp = &zpfirst[i]; eat(zp->z_filename, zp->z_linenum); startisdst = -1; if (zp->z_nrules == 0) { type = addtype(oadd(zp->z_gmtoff, zp->z_stdoff), zp->z_format, zp->z_stdoff != 0, startttisstd); if (usestart) addtt(starttime, type); gmtoff = zp->z_gmtoff; stdoff = zp->z_stdoff; } 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. */ offset = gmtoff; if (!zp->z_untilrule.r_todisstd) offset = oadd(offset, stdoff); untiltime = tadd(zp->z_untiltime, -offset); } /* ** 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; } if (ktime != starttime && startisdst >= 0)addtt(starttime, addtype(startoff, startbuf, startisdst, startttisstd)); usestart = FALSE; } 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); if (timecnt != 0 || rp->r_stdoff != 0) addtt(ktime, type); gmtoff = zp->z_gmtoff; stdoff = rp->r_stdoff; } } /* ** Now we may get to set starttime for the next zone line. */ if (useuntil) { starttime = tadd(zp->z_untiltime, -gmtoffs[types[timecnt - 1]]); startttisstd = zp->z_untilrule.r_todisstd; } } 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 >= 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 voidaddleap(t, positive, rolling)const time_t t;const int positive;const int rolling;{ register int i, j; if (leapcnt >= 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; } 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 : -1L); roll[i] = rolling; ++leapcnt;}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;{ char buf[BUFSIZ]; 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; (void) sprintf(buf, "yearistype %d %s", 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; 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) { if (wantedy == rp->r_loyear) return min_time; error("time before zero"); (void) exit(EXIT_FAILURE); } t = (time_t) dayoff * SECSPERDAY; /* ** Cheap overflow check. */ if (t / SECSPERDAY != dayoff) { if (wantedy == rp->r_hiyear) return max_time; if (wantedy == rp->r_loyear) return min_time; error("time overflow"); (void) exit(EXIT_FAILURE); } 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(name)char * const name;{ register char * cp; if ((cp = name) == NULL || *cp == '\0') return 0; while ((cp = strchr(cp + 1, '/')) != 0) { *cp = '\0'; if (!itsdir(name)) { /* ** It doesn't seem to exist, so we try to create it. */ if (mkdir(name, 0755) != 0) { (void) fprintf(stderr, "%s: Can't create directory ", progname); (void) perror(name); return -1; } } *cp = '/'; } 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 + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -