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

📄 ctime.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
字号:
/* * Copyright (c) 1987 Regents of the University of California. * All rights reserved.  The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */#ifndef lintstatic	char	*sccsid = "@(#)ctime.c	4.1	(ULTRIX)	7/3/90";#endif lint/************************************************************************ *									* *			Copyright (c) 1989 by				* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************//************************************************************************ *			Modification History * * 004	Jon Reeves, 20-Nov-1989 *	Added _last_tz_set logic: effectively do tzset every time, not *	just first, since environment may have changed.  Still leaves a *	little acceleration in place.  Believe user's tm_isdst for *	mktime. * * 003	Ken Lesniak, 31-Aug-1989 *	Modified mktime to correctly handle all times not representable * * 002	Ken Lesniak, 17-Jul-1989 *	Moved tz_is_set flag to tzset.c and actually set flag in tzset() * * 001	Ken Lesniak, 20-Mar-1989 *	Added support for POSIX 1003.1 compliancy. *	Added mktime and difftime routines for ANSI X3J11. *	Moved tzset* routines to tzset.c. * *	Based on Berkeley ctime.c 1.2 ************************************************************************/#include <sys/time.h>#include <tzfile.h>#include <limits.h>#include <stdlib.h>#include <string.h>#include "tzs.h"char *ctime(t)time_t *t;{	return(asctime(localtime(t)));}static char *itoa2(cp, n)register char *cp;int	n;{	if (n >= 10)		*cp++ = (n / 10) % 10 + '0';	else		*cp++ = ' ';	*cp++ = n % 10 + '0';	return cp;}char *asctime(t)register struct tm *	t;{	static char	wday_name[DAYS_PER_WEEK][3] = {		"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"	};	static char	mon_name[MONS_PER_YEAR][3] = {		"Jan", "Feb", "Mar", "Apr", "May", "Jun",		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"	};	static char	result[26];	register char	*cp;	register char	*ncp;	register int	year;	cp = result;	ncp = wday_name[t->tm_wday];	*cp++ = *ncp++;	*cp++ = *ncp++;	*cp++ = *ncp++;	*cp++ = ' ';	ncp = mon_name[t->tm_mon];	*cp++ = *ncp++;	*cp++ = *ncp++;	*cp++ = *ncp++;	*cp++ = ' ';	cp = itoa2(cp, t->tm_mday);	*cp++ = ' ';	cp = itoa2(cp, t->tm_hour + 100);	*cp++ = ':';	cp = itoa2(cp, t->tm_min + 100);	*cp++ = ':';	cp = itoa2(cp, t->tm_sec + 100);	*cp++ = ' ';	year = TM_YEAR_BASE + t->tm_year;	cp = itoa2(cp, year / 100);	cp = itoa2(cp, year);	*cp++ = '\n';	*cp++ = '\0';	return result;}struct tm *		offtime();extern struct state	_tzs;extern int		_tz_is_set;extern char 		_last_tz_set[LAST_TZ_LEN];struct tm *localtime(timep)time_t *	timep;{	register struct ttinfo *	ttisp;	register struct tm *		tmp;	register int			i;	time_t				t;	char *				tz;	if (!_tz_is_set || (tz=getenv("TZ")) && strcmp(tz, _last_tz_set))		(void) tzset();	t = *timep;	if (_tzs.timecnt == 0 || t < _tzs.ats[0]) {		i = 0;		while (_tzs.ttis[i].tt_isdst)			if (++i >= _tzs.timecnt) {				i = 0;				break;			}	} else {		for (i = 1; i < _tzs.timecnt; ++i)			if (t < _tzs.ats[i])				break;		i = _tzs.types[i - 1];	}	ttisp = &_tzs.ttis[i];	/*	** To get (wrong) behavior that's compatible with System V Release 2.0	** you'd replace the statement below with	**	tmp = offtime((time_t) (t + ttisp->tt_gmtoff), 0L);	*/	tmp = offtime(&t, ttisp->tt_gmtoff);	tmp->tm_isdst = ttisp->tt_isdst;	tzname[tmp->tm_isdst] = &_tzs.chars[ttisp->tt_abbrind];	tmp->tm_zone = &_tzs.chars[ttisp->tt_abbrind];	return tmp;}struct tm *gmtime(clock)time_t *	clock;{	register struct tm *	tmp;	tmp = offtime(clock, 0L);	tzname[0] = "GMT";	tmp->tm_zone = "GMT";		/* UCT ? */	return tmp;}static int	mon_lengths[2][MONS_PER_YEAR] = {	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 int	year_lengths[2] = {	DAYS_PER_NYEAR, DAYS_PER_LYEAR};struct tm *offtime(clock, offset)time_t *	clock;long		offset;{	register struct tm *	tmp;	register long		days;	register long		rem;	register int		y;	register int		yleap;	register int *		ip;	static struct tm	tm;	tmp = &tm;	days = *clock / SECS_PER_DAY;	rem = *clock % SECS_PER_DAY;	rem += offset;	while (rem < 0) {		rem += SECS_PER_DAY;		--days;	}	while (rem >= SECS_PER_DAY) {		rem -= SECS_PER_DAY;		++days;	}	tmp->tm_hour = (int) (rem / SECS_PER_HOUR);	rem = rem % SECS_PER_HOUR;	tmp->tm_min = (int) (rem / SECS_PER_MIN);	tmp->tm_sec = (int) (rem % SECS_PER_MIN);	tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYS_PER_WEEK);	if (tmp->tm_wday < 0)		tmp->tm_wday += DAYS_PER_WEEK;	y = EPOCH_YEAR;	if (days >= 0)		for ( ; ; ) {			yleap = isleap(y);			if (days < (long) year_lengths[yleap])				break;			++y;			days -= (long) year_lengths[yleap];		}	else do {		--y;		yleap = isleap(y);		days += (long) year_lengths[yleap];	} while (days < 0);	tmp->tm_year = y - TM_YEAR_BASE;	tmp->tm_yday = (int) days;	ip = mon_lengths[yleap];	for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon))		days -= (long) ip[tmp->tm_mon];	tmp->tm_mday = (int) (days + 1);	tmp->tm_isdst = 0;	tmp->tm_zone = "";	tmp->tm_gmtoff = offset;	return tmp;}double difftime(time1, time0)	time_t		time1;	time_t		time0;    {	return (double)time1 - (double)time0;    }/* * The following types and routines are provided so that mktime() can * use quadword math as it combines the broken-down time into * a time_t value. mktime() does not impose any bounds on the broken-down * time components, without the quadword math, all sorts of overflows * are possible. * * The routines are not general purpose quadword routines. The types * of the operands are restricted, to allow shortcuts in the algorthims. * * I know this is ugly, I can't think of any other way to allow mktime * to handle all broken-down times that can represent a valid time_t. */typedef union {	unsigned long	lw[2];	unsigned short	w[4];    } quadword;typedef union {	unsigned long	lw;	unsigned short	w[2];    } longword;#define ULONG unsigned long/* quadword(qw) = quadword(qw) + long(op) */void qadd(qw, op)	register quadword *qw;	long		op;    {	longword	ac;	longword	sext;	longword	lw_op;	sext.lw = 0;	if (op < 0)	    sext.lw = (unsigned long)-1;	lw_op.lw = (ULONG)op;	qw->w[0] = (ac.lw = (ULONG)qw->w[0] + lw_op.w[0]);	qw->w[1] = (ac.lw = (ULONG)qw->w[1] + lw_op.w[1] + (ULONG)ac.w[1]);	qw->w[2] = (ac.lw = (ULONG)qw->w[2] + (ULONG)sext.w[0] + (ULONG)ac.w[1]);	qw->w[3] += (ULONG)sext.w[1] + (ULONG)ac.w[1];    };/* quadword(qw) = (quadword(qw) * unsigned short(mop)) + long(aop) */void qmuladd(qw, mop, aop)	register quadword *qw;	unsigned short	mop;	long		aop;    {	longword	ac;	qw->w[0] = (ac.lw = (ULONG)qw->w[0] * (ULONG)mop);	qw->w[1] = (ac.lw = ((ULONG)qw->w[1] * (ULONG)mop) + ac.w[1]);	qw->w[2] = (ac.lw = ((ULONG)qw->w[2] * (ULONG)mop) + ac.w[1]);	qw->w[3] = (qw->w[3] * mop) + ac.w[1];	qadd(qw, aop);    }time_t mktime(tp)	register struct tm *tp;    {	time_t		t;	quadword	tq;	int		y;	int		m;	int		ly;	int		isdst;	int		i;	struct ttinfo	*ttis;	char		*tz;#define mktime_max_year (INT_MAX + (INT_MIN / MONS_PER_YEAR) + \	(INT_MIN / DAYS_PER_NYEAR) + \	(INT_MIN / (HOURS_PER_DAY * DAYS_PER_NYEAR)) + \	(INT_MIN / (MINS_PER_HOUR * HOURS_PER_DAY * DAYS_PER_NYEAR)) + \	(INT_MIN / (SECS_PER_MIN * MINS_PER_HOUR * HOURS_PER_DAY * DAYS_PER_NYEAR)) + \	TM_YEAR_BASE)#define mktime_min_year (INT_MIN + (INT_MAX / MONS_PER_YEAR) + \	(INT_MAX / DAYS_PER_NYEAR) + \	(INT_MAX / (HOURS_PER_DAY * DAYS_PER_NYEAR)) + \	(INT_MAX / (MINS_PER_HOUR * HOURS_PER_DAY * DAYS_PER_NYEAR)) + \	(INT_MAX / (SECS_PER_MIN * MINS_PER_HOUR * HOURS_PER_DAY * DAYS_PER_NYEAR)) + \	TM_YEAR_BASE)	/* Make sure the year is in bounds to avoid overflowing the */	/* month-year normalization */	if (tp->tm_year < mktime_min_year || tp->tm_year > mktime_max_year)	    return (time_t)-1;	/* Get normalized month and year */	y = tp->tm_year + TM_YEAR_BASE + (tp->tm_mon / MONS_PER_YEAR);	if ((m = tp->tm_mon % MONS_PER_YEAR) < 0) {	    m += MONS_PER_YEAR;	    y--;	};	ly = isleap(y);	/* Determine the number of days since the epoch */	tq.lw[0] = tq.lw[1] = -1;	qadd(&tq, tp->tm_mday);	while (m != 0)	    qadd(&tq, mon_lengths[ly][--m]);	if (y >= EPOCH_YEAR) {	    while (y != EPOCH_YEAR) {		y--;		qadd(&tq, year_lengths[isleap(y)]);	    };	} else {	    do {		qadd(&tq, -year_lengths[isleap(y)]);		y++;	    } while (y != EPOCH_YEAR);	};		/* Now convert everything to seconds */	qmuladd(&tq, HOURS_PER_DAY, tp->tm_hour);	qmuladd(&tq, MINS_PER_HOUR, tp->tm_min);	qmuladd(&tq, SECS_PER_MIN, tp->tm_sec);	/* Make sure the resulting time can be represented by a time_t */	if (tq.lw[1] != 0 && tq.lw[1] != (unsigned long)-1)	    return (time_t)-1;	t = (time_t)tq.lw[0];	/* Determine the GMT offset for the time */	if (!_tz_is_set || (tz=getenv("TZ")) && strcmp(tz, _last_tz_set))	    (void)tzset();	ttis = &_tzs.ttis[0];	if (tp->tm_isdst < 0) {	    if (_tzs.timecnt != 0 && t >= _tzs.ats[0] + ttis->tt_gmtoff) {		for (i = 1; i < _tzs.timecnt; i++) {		    ttis = &_tzs.ttis[_tzs.types[i - 1]];		    if (t < _tzs.ats[i - 1] + ttis->tt_gmtoff)			return (time_t)-1;		    if (t < _tzs.ats[i] + ttis->tt_gmtoff)			break;		};	    };	} else {	    /* User specified DST, normalize to 0 or 1 (yes, '=' is right) */	    if (isdst = tp->tm_isdst)		isdst = 1;	    /* Search for an appropriate DST setting; fall out if no DST */	    for (i = 0; i < _tzs.timecnt; i++) {		ttis = &_tzs.ttis[_tzs.types[i]];		if (ttis->tt_isdst == isdst)		    break;	    }	    /* Asked for DST (or standard), but none defined */	    if (ttis->tt_isdst != isdst)		return (time_t)-1;	}	/* Adjust for time zone and daylight savings time */	t -= ttis->tt_gmtoff;	/* Normalize the broken down time and fill in the unspecified fields */	(void)memcpy(tp, localtime(&t), sizeof(struct tm));	/* Return the time */	return t;    }

⌨️ 快捷键说明

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