⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zic.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
}static voidassociate(){	register struct zone *	zp;	register struct rule *	rp;	register int		base, out;	register int		i;	if (nrules != 0)		(void) qsort((void *) rules, (size_t) nrules,		     (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];		for (out = base + 1; out < nrules; ++out)			if (strcmp(rp->r_name, rules[out].r_name) != 0)				break;		for (i = 0; i < nzones; ++i) {			zp = &zones[i];			if (strcmp(zp->z_rule, rp->r_name) != 0)				continue;			zp->z_rules = rp;			zp->z_nrules = out - base;		}	}	for (i = 0; i < nzones; ++i) {		zp = &zones[i];		if (zp->z_nrules == 0) {			/*			** Maybe we have a local standard time offset.			*/			eat(zp->z_filename, zp->z_linenum);			zp->z_stdoff =			    gethms((char *)zp->z_rule, "unruly zone", TRUE);			/*			** Note, though, that if there's no rule,			** a '%s' in the format is a bad thing.			*/			if (strchr(zp->z_format, '%') != 0)				error("%s in ruleless zone");		}	}	if (errors)		(void) exit(EXIT_FAILURE);}static voidinfile(name)const char *	name;{	register FILE *			fp;	register char **		fields;	register char *			cp;	register const struct lookup *	lp;	register int			nfields;	register int			wantcont;	register int			num;	char				buf[BUFSIZ];	if (strcmp(name, "-") == 0) {		name = "standard input";		fp = stdin;	} else if ((fp = fopen(name, "r")) == NULL) {		(void) fprintf(stderr, "%s: Can't open ", progname);		(void) perror(name);		(void) exit(EXIT_FAILURE);	}	wantcont = FALSE;	for (num = 1; ; ++num) {		eat(name, num);		if (fgets(buf, (int) sizeof buf, fp) != buf)			break;		cp = strchr(buf, '\n');		if (cp == NULL) {			error("line too long");			(void) exit(EXIT_FAILURE);		}		*cp = '\0';		fields = getfields(buf);		nfields = 0;		while (fields[nfields] != NULL) {			if (ciequal(fields[nfields], "-"))				fields[nfields] = "";			++nfields;		}		if (nfields == 0) {			/* nothing to do */		} else if (wantcont) {			wantcont = inzcont(fields, nfields);		} else {			lp = byword(fields[0], line_codes);			if (lp == NULL)				error("input line of unknown type");			else switch ((int) (lp->l_value)) {				case LC_RULE:					inrule(fields, nfields);					wantcont = FALSE;					break;				case LC_ZONE:					wantcont = inzone(fields, nfields);					break;				case LC_LINK:					inlink(fields, nfields);					wantcont = FALSE;					break;				case LC_LEAP:					if (name != leapsec)						(void) fprintf(stderr,"%s: Leap line in non leap seconds file %s\n",							progname, name);					else	inleap(fields, nfields);					wantcont = FALSE;					break;				default:	/* "cannot happen" */					(void) fprintf(stderr,"%s: panic: Invalid l_value %d\n",						progname, lp->l_value);					(void) exit(EXIT_FAILURE);			}		}		ifree((char *) fields);	}	if (ferror(fp)) {		(void) fprintf(stderr, "%s: Error reading ", progname);		(void) perror(filename);		(void) exit(EXIT_FAILURE);	}	if (fp != stdin && fclose(fp)) {		(void) fprintf(stderr, "%s: Error closing ", progname);		(void) perror(filename);		(void) exit(EXIT_FAILURE);	}	if (wantcont)		error("expected continuation line not found");}/*** Convert a string of one of the forms**	h	-h 	hh:mm	-hh:mm	hh:mm:ss	-hh:mm:ss** into a number of seconds.** A null string maps to zero.** Call error with errstring and return zero on errors.*/static longgethms(string, errstring, signable)char *		string;const char * const	errstring;const int		signable;{	int	hh, mm, ss, sign;	if (string == NULL || *string == '\0')		return 0;	if (!signable)		sign = 1;	else if (*string == '-') {		sign = -1;		++string;	} else	sign = 1;	if (sscanf(string, scheck(string, "%d"), &hh) == 1)		mm = ss = 0;	else if (sscanf(string, scheck(string, "%d:%d"), &hh, &mm) == 2)		ss = 0;	else if (sscanf(string, scheck(string, "%d:%d:%d"),		&hh, &mm, &ss) != 3) {			error(errstring);			return 0;	}	if (hh < 0 || hh >= HOURSPERDAY ||		mm < 0 || mm >= MINSPERHOUR ||		ss < 0 || ss > SECSPERMIN) {			error(errstring);			return 0;	}	return eitol(sign) *		(eitol(hh * MINSPERHOUR + mm) *		eitol(SECSPERMIN) + eitol(ss));}static voidinrule(fields, nfields)register char ** const	fields;const int		nfields;{	static struct rule	r;	if (nfields != RULE_FIELDS) {		error("wrong number of fields on Rule line");		return;	}	if (*fields[RF_NAME] == '\0') {		error("nameless rule");		return;	}	r.r_filename = filename;	r.r_linenum = linenum;	r.r_stdoff = gethms(fields[RF_STDOFF], "invalid saved time", TRUE);	rulesub(&r, fields[RF_LOYEAR], fields[RF_HIYEAR], fields[RF_COMMAND],		fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]);	r.r_name = ecpyalloc(fields[RF_NAME]);	r.r_abbrvar = ecpyalloc(fields[RF_ABBRVAR]);	rules = (struct rule *) erealloc((char *) rules,		(int) ((nrules + 1) * sizeof *rules));	rules[nrules++] = r;}static intinzone(fields, nfields)register char ** const	fields;const int		nfields;{	register int	i;	char		buf[132];	if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS) {		error("wrong number of fields on Zone line");		return FALSE;	}	if (strcmp(fields[ZF_NAME], TZDEFAULT) == 0 && lcltime != NULL) {		(void) sprintf(buf,			"\"Zone %s\" line and -l option are mutually exclusive",			TZDEFAULT);		error(buf);		return FALSE;	}	if (strcmp(fields[ZF_NAME], TZDEFRULES) == 0 && psxrules != NULL) {		(void) sprintf(buf,			"\"Zone %s\" line and -p option are mutually exclusive",			TZDEFRULES);		error(buf);		return FALSE;	}	for (i = 0; i < nzones; ++i)		if (zones[i].z_name != NULL &&			strcmp(zones[i].z_name, fields[ZF_NAME]) == 0) {				(void) sprintf(buf,"duplicate zone name %s (file \"%s\", line %d)",					fields[ZF_NAME],					zones[i].z_filename,					zones[i].z_linenum);				error(buf);				return FALSE;		}	return inzsub(fields, nfields, FALSE);}static intinzcont(fields, nfields)register char ** const	fields;const int		nfields;{	if (nfields < ZONEC_MINFIELDS || nfields > ZONEC_MAXFIELDS) {		error("wrong number of fields on Zone continuation line");		return FALSE;	}	return inzsub(fields, nfields, TRUE);}static intinzsub(fields, nfields, iscont)register char ** const	fields;const int		nfields;const int		iscont;{	register char *		cp;	static struct zone	z;	register int		i_gmtoff, i_rule, i_format;	register int		i_untilyear, i_untilmonth;	register int		i_untilday, i_untiltime;	register int		hasuntil;	if (iscont) {		i_gmtoff = ZFC_GMTOFF;		i_rule = ZFC_RULE;		i_format = ZFC_FORMAT;		i_untilyear = ZFC_TILYEAR;		i_untilmonth = ZFC_TILMONTH;		i_untilday = ZFC_TILDAY;		i_untiltime = ZFC_TILTIME;		z.z_name = NULL;	} else {		i_gmtoff = ZF_GMTOFF;		i_rule = ZF_RULE;		i_format = ZF_FORMAT;		i_untilyear = ZF_TILYEAR;		i_untilmonth = ZF_TILMONTH;		i_untilday = ZF_TILDAY;		i_untiltime = ZF_TILTIME;		z.z_name = ecpyalloc(fields[ZF_NAME]);	}	z.z_filename = filename;	z.z_linenum = linenum;	z.z_gmtoff = gethms(fields[i_gmtoff], "invalid GMT offset", TRUE);	if ((cp = strchr(fields[i_format], '%')) != 0) {		if (*++cp != 's' || strchr(cp, '%') != 0) {			error("invalid abbreviation format");			return FALSE;		}	}	z.z_rule = ecpyalloc(fields[i_rule]);	z.z_format = ecpyalloc(fields[i_format]);	hasuntil = nfields > i_untilyear;	if (hasuntil) {		z.z_untilrule.r_filename = filename;		z.z_untilrule.r_linenum = linenum;		rulesub(&z.z_untilrule,			fields[i_untilyear],			"only",			"",			(nfields > i_untilmonth) ? fields[i_untilmonth] : "Jan",			(nfields > i_untilday) ? fields[i_untilday] : "1",			(nfields > i_untiltime) ? fields[i_untiltime] : "0");		z.z_untiltime = rpytime(&z.z_untilrule, z.z_untilrule.r_loyear);		if (iscont && nzones > 0 && z.z_untiltime < max_time &&			z.z_untiltime > min_time &&			zones[nzones - 1].z_untiltime >= z.z_untiltime) {error("Zone continuation line end time is not after end time of previous line");			return FALSE;		}	}	zones = (struct zone *) erealloc((char *) zones,		(int) ((nzones + 1) * sizeof *zones));	zones[nzones++] = z;	/*	** If there was an UNTIL field on this line,	** there's more information about the zone on the next line.	*/	return hasuntil;}static voidinleap(fields, nfields)register char ** const	fields;const int		nfields;{	register const char *		cp;	register const struct lookup *	lp;	register int			i, j;	int				year, month, day;	long				dayoff, tod;	time_t				t;	if (nfields != LEAP_FIELDS) {		error("wrong number of fields on Leap line");		return;	}	dayoff = 0;	cp = fields[LP_YEAR];	if (sscanf((char *)cp, scheck(cp, "%d"), &year) != 1 ||		year < min_year || year > max_year) {			/*			 * Leapin' Lizards!			 */			error("invalid leaping year");			return;	}	j = EPOCH_YEAR;	while (j != year) {		if (year > j) {			i = len_years[isleap(j)];			++j;		} else {			--j;			i = -len_years[isleap(j)];		}		dayoff = oadd(dayoff, eitol(i));	}	if ((lp = byword(fields[LP_MONTH], mon_names)) == NULL) {		error("invalid month name");		return;	}	month = lp->l_value;	j = TM_JANUARY;	while (j != month) {		i = len_months[isleap(year)][j];		dayoff = oadd(dayoff, eitol(i));		++j;	}	cp = fields[LP_DAY];	if (sscanf((char *)cp, scheck(cp, "%d"), &day) != 1 ||		day <= 0 || day > len_months[isleap(year)][month]) {			error("invalid day of month");			return;	}	dayoff = oadd(dayoff, eitol(day - 1));	if (dayoff < 0 && !tt_signed) {		error("time before zero");		return;	}	t = (time_t) dayoff * SECSPERDAY;	/*	** Cheap overflow check.	*/	if (t / SECSPERDAY != dayoff) {		error("time overflow");		return;	}	tod = gethms(fields[LP_TIME], "invalid time of day", FALSE);	cp = fields[LP_CORR];	if (strcmp(cp, "+") != 0 && strcmp(cp, "") != 0) {		/* infile() turned "-" into "" */		error("illegal CORRECTION field on Leap line");		return;	}	if ((lp = byword(fields[LP_ROLL], leap_types)) == NULL) {		error("illegal Rolling/Stationary field on Leap line");		return;	}	addleap(tadd(t, tod), *cp == '+', lp->l_value);}static voidinlink(fields, nfields)register char ** const	fields;const int		nfields;{	struct link	l;	if (nfields != LINK_FIELDS) {		error("wrong number of fields on Link line");		return;	}	if (*fields[LF_FROM] == '\0') {		error("blank FROM field on Link line");		return;	}	if (*fields[LF_TO] == '\0') {		error("blank TO field on Link line");		return;	}	l.l_filename = filename;	l.l_linenum = linenum;	l.l_from = ecpyalloc(fields[LF_FROM]);	l.l_to = ecpyalloc(fields[LF_TO]);	links = (struct link *) erealloc((char *) links,		(int) ((nlinks + 1) * sizeof *links));	links[nlinks++] = l;}static voidrulesub(rp, loyearp, hiyearp, typep, monthp, dayp, timep)register struct rule * const	rp;char * const			loyearp;char * const			hiyearp;char * const			typep;char * const			monthp;char * const			dayp;char * const			timep;{	register struct lookup const *	lp;	register char *			cp;	if ((lp = byword(monthp, mon_names)) == NULL) {		error("invalid month name");		return;	}	rp->r_month = lp->l_value;	rp->r_todisstd = FALSE;	cp = timep;	if (*cp != '\0') {		cp += strlen(cp) - 1;		switch (lowerit(*cp)) {			case 's':				rp->r_todisstd = TRUE;				*cp = '\0';				break;			case 'w':				rp->r_todisstd = FALSE;				*cp = '\0';				break;		}	}	rp->r_tod = gethms(timep, "invalid time of day", FALSE);	/*	** Year work.	*/	cp = loyearp;	if ((lp = byword(cp, begin_years)) != NULL) switch ((int) lp->l_value) {		case YR_MINIMUM:			rp->r_loyear = min_year;			break;		case YR_MAXIMUM:			rp->r_loyear = max_year;			break;		default:	/* "cannot happen" */			(void) fprintf(stderr,				"%s: panic: Invalid l_value %d\n",				progname, lp->l_value);			(void) exit(EXIT_FAILURE);	} else if (sscanf(cp, scheck(cp, "%d"), &rp->r_loyear) != 1 ||		rp->r_loyear < min_year || rp->r_loyear > max_year) {			if (noise)				error("invalid starting year");			if (rp->r_loyear > max_year)				return;	}	cp = hiyearp;	if ((lp = byword(cp, end_years)) != NULL) switch ((int) lp->l_value) {		case YR_MINIMUM:			rp->r_hiyear = min_year;			break;		case YR_MAXIMUM:			rp->r_hiyear = max_year;			break;		case YR_ONLY:			rp->r_hiyear = rp->r_loyear;			break;		default:	/* "cannot happen" */			(void) fprintf(stderr,				"%s: panic: Invalid l_value %d\n",				progname, lp->l_value);			(void) exit(EXIT_FAILURE);	} else if (sscanf(cp, scheck(cp, "%d"), &rp->r_hiyear) != 1 ||		rp->r_hiyear < min_year || rp->r_hiyear > max_year) {			if (noise)				error("invalid ending year");			if (rp->r_hiyear < min_year)				return;	}	if (rp->r_hiyear < min_year) 		return; 	if (rp->r_loyear < min_year) 		rp->r_loyear = min_year; 	if (rp->r_hiyear > max_year) 		rp->r_hiyear = max_year;	if (rp->r_loyear > rp->r_hiyear) {		error("starting year greater than ending year");		return;	}	if (*typep == '\0')		rp->r_yrtype = NULL;	else {		if (rp->r_loyear == rp->r_hiyear) {			error("typed single year");			return;		}		rp->r_yrtype = ecpyalloc(typep);	}	/*	** Day work.	** Accept things such as:	**	1	**	last-Sunday	**	Sun<=20	**	Sun>=7	*/	if ((lp = byword(dayp, lasts)) != NULL) {		rp->r_dycode = DC_DOWLEQ;		rp->r_wday = lp->l_value;		rp->r_dayofmonth = len_months[1][rp->r_month];	} else {		if ((cp = strchr(dayp, '<')) != 0)			rp->r_dycode = DC_DOWLEQ;		else if ((cp = strchr(dayp, '>')) != 0)			rp->r_dycode = DC_DOWGEQ;		else {			cp = dayp;			rp->r_dycode = DC_DOM;		}		if (rp->r_dycode != DC_DOM) {			*cp++ = 0;			if (*cp++ != '=') {				error("invalid day of month");				return;			}			if ((lp = byword(dayp, wday_names)) == NULL) {				error("invalid weekday name");				return;			}			rp->r_wday = lp->l_value;		}		if (sscanf(cp, scheck(cp, "%d"), &rp->r_dayofmonth) != 1 ||			rp->r_dayofmonth <= 0 ||			(rp->r_dayofmonth > len_months[1][rp->r_month])) {				error("invalid day of month");				return;		}	}}static voidconvert(val, buf)const long	val;char * const	buf;{	register int	i;	register long	shift;	for (i = 0, shift = 24; i < 4; ++i, shift -= 8)		buf[i] = val >> shift;}static voidputtzcode(val, fp)const long	val;FILE * const	fp;{	char	buf[4];	convert(val, buf);	(void) fwrite((void *) buf, (size_t) sizeof buf, (size_t) 1, fp);}static voidwritezone(name)const char * const	name;{	register FILE *		fp;	register int		i, j;	char			fullname[BUFSIZ];	static struct tzhead	tzh;	if (strlen(directory) + 1 + strlen(name) >= sizeof fullname) {		(void) fprintf(stderr,			"%s: File name %s/%s too long\n", progname,			directory, name);		(void) exit(EXIT_FAILURE);	}	(void) sprintf(fullname, "%s/%s", directory, name);	if ((fp = fopen(fullname, "wb")) == NULL) {		if (mkdirs(fullname) != 0)			(void) exit(EXIT_FAILURE);		if ((fp = fopen(fullname, "wb")) == NULL) {			(void) fprintf(stderr, "%s: Can't create ", progname);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -