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

📄 localtime.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
#if !defined(lint) && defined(SCCSIDS)static	char sccsid[] = "@(#)localtime.c 1.1 92/07/30 SMI"; /* from Arthur Olson's 6.1 */#endif/*LINTLIBRARY*/#include <tzfile.h>#include <time.h>#include <string.h>#include <ctype.h>#include <stdio.h>	/* for NULL */#include <fcntl.h>#include <sys/param.h>	/* for MAXPATHLEN */#define FILENAME_MAX	MAXPATHLEN#ifdef __STDC__#define P(s)		s#else /* !defined __STDC__ *//*** Memory management functions*/extern char *	calloc();extern char *	malloc();/*** Communication with the environment*/extern char *	getenv();#define ASTERISK	*#define P(s)		(/ASTERISK s ASTERISK/)#define const#endif /* !defined __STDC__ */#ifndef TRUE#define TRUE		1#define FALSE		0#endif /* !defined TRUE */#define ACCESS_MODE	O_RDONLY#define OPEN_MODE	O_RDONLY/*** Someone might make incorrect use of a time zone abbreviation:**	1.	They might reference tzname[0] before calling tzset (explicitly**	 	or implicitly).**	2.	They might reference tzname[1] before calling tzset (explicitly**	 	or implicitly).**	3.	They might reference tzname[1] after setting to a time zone**		in which Daylight Saving Time is never observed.**	4.	They might reference tzname[0] after setting to a time zone**		in which Standard Time is never observed.**	5.	They might reference tm.TM_ZONE after calling offtime.** What's best to do in the above cases is open to debate;** for now, we just set things up so that in any of the five cases** WILDABBR is used.  Another possibility:  initialize tzname[0] to the** string "tzname[0] used before set", and similarly for the other cases.** And another:  initialize tzname[0] to "ERA", with an explanation in the** manual page of what this "time zone abbreviation" means (doing this so** that tzname[0] has the "normal" length of three characters).*/static const char *WILDABBR = "   ";static const char *GMT = "GMT";struct ttinfo {				/* time type information */	long		tt_gmtoff;	/* GMT offset in seconds */	int		tt_isdst;	/* used to set tm_isdst */	int		tt_abbrind;	/* abbreviation list index */	int		tt_ttisstd;	/* TRUE if transition is std time */};struct state {	int		timecnt;	int		typecnt;	int		charcnt;	time_t		*ats;	unsigned char	*types;	struct ttinfo	*ttis;	char		*chars;};struct rule {	int		r_type;		/* type of rule--see below */	int		r_day;		/* day number of rule */	int		r_week;		/* week number of rule */	int		r_mon;		/* month number of rule */	long		r_time;		/* transition time of rule */};#define	JULIAN_DAY		0	/* Jn - Julian day */#define	DAY_OF_YEAR		1	/* n - day of year */#define	MONTH_NTH_DAY_OF_WEEK	2	/* Mm.n.d - month, week, day of week *//*** Prototypes for static functions.*/static int		allocall P((register struct state * sp));static long		detzcode P((const char * codep));static void		freeall P((register struct state * sp));static const char *	getzname P((const char * strp));static const char *	getnum P((const char * strp, int * nump, int min,				int max));static const char *	getsecs P((const char * strp, long * secsp));static const char *	getoffset P((const char * strp, long * offsetp));static const char *	getrule P((const char * strp, struct rule * rulep));static void		gmtload P((struct state * sp));static void		gmtsub P((const time_t * timep, long offset,				struct tm * tmp));static void		localsub P((const time_t * timep, long offset,				struct tm * tmp));static void		normalize P((int * tensptr, int * unitsptr, int base));static void		settzname P((void));static time_t		time1 P((struct tm * tmp, void (* funcp)(),				long offset));static time_t		time2 P((struct tm *tmp, void (* funcp)(),				long offset, int * okayp));static void		timesub P((const time_t * timep, long offset,				struct tm * tmp));static int		tmcomp P((const struct tm * atmp,				const struct tm * btmp));static time_t		transtime P((time_t janfirst, int year,				const struct rule * rulep, long offset));static int		tzload P((const char * name, struct state * sp));static int		tzparse P((const char * name, struct state * sp,				int lastditch));static struct state *	lclptr;static struct state *	gmtptr;static int		lcl_is_set;static int		gmt_is_set;#ifdef S5EMULchar *			tzname[2] = {	"GMT",	"   ",};time_t			timezone = 0;time_t			altzone = 0;int			daylight = 0;#endif /* defined S5EMUL */static longdetzcode(codep)const char * const	codep;{	register long	result;	register int	i;	result = 0;	for (i = 0; i < 4; ++i)		result = (result << 8) | (codep[i] & 0xff);	return result;}/*** Free up existing items pointed to by the specified "state" structure,** and allocate new ones of sizes specified by that "state" structure.** Return 0 on success; return -1 and free all previously-allocated items** on failure.*/static intallocall(sp)register struct state * const	sp;{	freeall(sp);	if (sp->timecnt != 0) {		sp->ats = (time_t *)calloc((unsigned)sp->timecnt,		   (unsigned)sizeof (time_t));		if (sp->ats == NULL)			return -1;		sp->types =		   (unsigned char *)calloc((unsigned)sp->timecnt,		   (unsigned)sizeof (unsigned char));		if (sp->types == NULL) {			freeall(sp);			return -1;		}	}	sp->ttis =	  (struct ttinfo *)calloc((unsigned)sp->typecnt,	  (unsigned)sizeof (struct ttinfo));	if (sp->ttis == NULL) {		freeall(sp);		return -1;	}	sp->chars = (char *)calloc((unsigned)sp->charcnt + 1,	  (unsigned)sizeof (char));	if (sp->chars == NULL) {		freeall(sp);		return -1;	}	return 0;}/*** Free all the items pointed to by the specified "state" structure (except for** "chars", which might have other references to it), and zero out all the** pointers to those items.*/static voidfreeall(sp)register struct state * const	sp;{	if (sp->ttis) {		free((char *)sp->ttis);		sp->ttis = 0;	}	if (sp->types) {		free((char *)sp->types);		sp->types = 0;	}	if (sp->ats) {		free((char *)sp->ats);		sp->ats = 0;	}}#ifdef S5EMULstatic voidsettzname(){	register const struct state * const	sp = lclptr;	register int				i;	tzname[0] = GMT;	tzname[1] = WILDABBR;	daylight = 0;	timezone = 0;	altzone = 0;	if (sp == NULL)		return;	for (i = 0; i < sp->typecnt; ++i) {		register const struct ttinfo * const	ttisp = &sp->ttis[i];		tzname[ttisp->tt_isdst] =			(char *) &sp->chars[ttisp->tt_abbrind];		if (ttisp->tt_isdst)			daylight = 1;		if (i == 0 || !ttisp->tt_isdst)			timezone = -(ttisp->tt_gmtoff);		if (i == 0 || ttisp->tt_isdst)			altzone = -(ttisp->tt_gmtoff);	}	/*	** And to get the latest zone names into tzname. . .	*/	for (i = 0; i < sp->timecnt; ++i) {		register const struct ttinfo * const	ttisp =							&sp->ttis[sp->types[i]];		tzname[ttisp->tt_isdst] =			(char *) &sp->chars[ttisp->tt_abbrind];	}}#endif/*** Maximum size of a time zone file.*/#define	MAX_TZFILESZ	(sizeof (struct tzhead) + \			TZ_MAX_TIMES * (4 + sizeof (char)) + \			TZ_MAX_TYPES * (4 + 2 * sizeof (char)) + \			TZ_MAX_CHARS * sizeof (char) + \			TZ_MAX_LEAPS * 2 * 4 + \			TZ_MAX_TYPES * sizeof (char))static inttzload(name, sp)register const char *	name;register struct state * const	sp;{	register const char *	p;	register int		i;	register int		fid;	if (name == NULL && (name = TZDEFAULT) == NULL)		return -1;	{		register int 	doaccess;		char		fullname[FILENAME_MAX + 1];		if (name[0] == ':')			++name;		doaccess = name[0] == '/';		if (!doaccess) {			if ((p = TZDIR) == NULL)				return -1;			if ((strlen(p) + strlen(name) + 1) >= sizeof fullname)				return -1;			(void) strcpy(fullname, p);			(void) strcat(fullname, "/");			(void) strcat(fullname, name);			/*			** Set doaccess if '.' (as in "../") shows up in name.			*/			if (strchr(name, '.') != NULL)				doaccess = TRUE;			name = fullname;		}		if (doaccess && access(name, ACCESS_MODE) != 0)			return -1;		if ((fid = open(name, OPEN_MODE)) == -1)			return -1;	}	{		register const struct tzhead *	tzhp;		char				buf[MAX_TZFILESZ];		int				leapcnt;		int				ttisstdcnt;		i = read(fid, buf, sizeof buf);		if (close(fid) != 0 || i < sizeof *tzhp)			return -1;		tzhp = (struct tzhead *) buf;		ttisstdcnt = (int) detzcode(tzhp->tzh_ttisstdcnt);		leapcnt = (int) detzcode(tzhp->tzh_leapcnt);		sp->timecnt = (int) detzcode(tzhp->tzh_timecnt);		sp->typecnt = (int) detzcode(tzhp->tzh_typecnt);		sp->charcnt = (int) detzcode(tzhp->tzh_charcnt);		if (leapcnt < 0 || leapcnt > TZ_MAX_LEAPS ||			sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||			sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||			sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||			(ttisstdcnt != sp->typecnt && ttisstdcnt != 0))				return -1;		if (i < sizeof *tzhp +			sp->timecnt * (4 + sizeof (char)) +			sp->typecnt * (4 + 2 * sizeof (char)) +			sp->charcnt * sizeof (char) +			leapcnt * 2 * 4 +			ttisstdcnt * sizeof (char))				return -1;		if (allocall(sp) < 0)			return -1;		p = buf + sizeof *tzhp;		for (i = 0; i < sp->timecnt; ++i) {			sp->ats[i] = detzcode(p);			p += 4;		}		for (i = 0; i < sp->timecnt; ++i) {			sp->types[i] = (unsigned char) *p++;			if (sp->types[i] >= sp->typecnt)				return -1;		}		for (i = 0; i < sp->typecnt; ++i) {			register struct ttinfo *	ttisp;			ttisp = &sp->ttis[i];			ttisp->tt_gmtoff = detzcode(p);			p += 4;			ttisp->tt_isdst = (unsigned char) *p++;			if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)				return -1;			ttisp->tt_abbrind = (unsigned char) *p++;			if (ttisp->tt_abbrind < 0 ||				ttisp->tt_abbrind > sp->charcnt)					return -1;		}		for (i = 0; i < sp->charcnt; ++i)			sp->chars[i] = *p++;		sp->chars[i] = '\0';	/* ensure '\0' at end */		p += (4 + 4) * leapcnt;	/* skip leap seconds list */		for (i = 0; i < sp->typecnt; ++i) {			register struct ttinfo *	ttisp;			ttisp = &sp->ttis[i];			if (ttisstdcnt == 0)				ttisp->tt_ttisstd = FALSE;			else {				ttisp->tt_ttisstd = *p++;				if (ttisp->tt_ttisstd != TRUE &&					ttisp->tt_ttisstd != FALSE)						return -1;			}		}	}	return 0;}static const int	mon_lengths[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	year_lengths[2] = {	DAYSPERNYEAR, DAYSPERLYEAR};/*** Given a pointer into a time zone string, scan until a character that is not** a valid character in a zone name is found.  Return a pointer to that** character.*/static const char *getzname(strp)register const char *	strp;{	register char	c;	while ((c = *strp) != '\0' && !isdigit(c) && c != ',' && c != '-' &&		c != '+')			++strp;	return strp;}/*** Given a pointer into a time zone string, extract a number from that string.** Check that the number is within a specified range; if it is not, return** NULL.** Otherwise, return a pointer to the first character not part of the number.*/static const char *getnum(strp, nump, min, max)register const char *	strp;int * const		nump;const int		min;const int		max;{	register char	c;	register int	num;	if (strp == NULL || !isdigit(*strp))		return NULL;	num = 0;	while ((c = *strp) != '\0' && isdigit(c)) {		num = num * 10 + (c - '0');		if (num > max)			return NULL;	/* illegal value */		++strp;	}	if (num < min)		return NULL;		/* illegal value */

⌨️ 快捷键说明

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