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 + -
显示快捷键?