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

📄 time.c

📁 Axis 221 camera embedded programing interface
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Copyright (C) 2002-2004   Manuel Novoa III    <mjn3@codepoet.org> * * GNU Library General Public License (LGPL) version 2 or later. * * Dedicated to Toni.  See uClibc/DEDICATION.mjn3 for details. *//* June 15, 2002     Initial Notes: * * Note: It is assumed throught that time_t is either long or unsigned long. *       Similarly, clock_t is assumed to be long int. * * Warning: Assumptions are made about the layout of struct tm!  It is *    assumed that the initial fields of struct tm are (in order): *    tm_sec, tm_min, tm_hour, tm_mday, tm_mon, tm_year, tm_wday, tm_yday * * Reached the inital goal of supporting the ANSI/ISO C99 time functions * as well as SUSv3's strptime.  All timezone info is obtained from the * TZ env variable. * * Differences from glibc worth noting: * * Leap seconds are not considered here. * * glibc stores additional timezone info the struct tm, whereas we don't. * * Alternate digits and era handling are not currently implemented. * The modifiers are accepted, and tested for validity with the following * specifier, but are ignored otherwise. * * strftime does not implement glibc extension modifiers or widths for *     conversion specifiers.  However it does implement the glibc *     extension specifiers %l, %k, and %s.  It also recognizes %P, but *     treats it as a synonym for %p; i.e. doesn't convert to lower case. * * strptime implements the glibc extension specifiers.  However, it follows *     SUSv3 in requiring at least one non-alphanumeric char between *     conversion specifiers.  Also, strptime only sets struct tm fields *     for which format specifiers appear and does not try to infer other *     fields (such as wday) as glibc's version does. * * TODO - Since glibc's %l and %k can space-pad their output in strftime, *     it might be reasonable to eat whitespace first for those specifiers. *     This could be done by pushing " %I" and " %H" respectively so that *     leading whitespace is consumed.  This is really only an issue if %l *     or %k occurs at the start of the format string. * * TODO - Implement getdate? tzfile? struct tm extensions? * * TODO - Rework _time_mktime to remove the dependency on long long. *//* Oct 28, 2002 * * Fixed allowed char check for std and dst TZ fields. * * Added several options concerned with timezone support.  The names will * probably change once Erik gets the new config system in place. * * Defining __TIME_TZ_FILE causes tzset() to attempt to read the TZ value * from the file /etc/TZ if the TZ env variable isn't set.  The file contents * must be the intended value of TZ, followed by a newline.  No other chars, * spacing, etc is allowed.  As an example, an easy way for me to init * /etc/TZ appropriately would be:    echo CST6CDT > /etc/TZ * * Defining __TIME_TZ_FILE_ONCE will cause all further accesses of /etc/TZ * to be skipped once a legal value has been read. * * Defining __TIME_TZ_OPT_SPEED will cause a tzset() to keep a copy of the * last TZ setting string and do a "fast out" if the current string is the * same. * * Nov 21, 2002   Fix an error return case in _time_mktime. * * Nov 26, 2002   Fix bug in setting daylight and timezone when no (valid) TZ. *   Bug reported by Arne Bernin <arne@alamut.de> in regards to freeswan. * * July 27, 2003  Adjust the struct tm extension field support. *   Change __tm_zone back to a ptr and add the __tm_tzname[] buffer for *   __tm_zone to point to.  This gets around complaints from g++. *  Who knows... it might even fix the PPC timezone init problem. * * July 29, 2003  Fix a bug in mktime behavior when tm_isdst was -1. *   Bug reported by "Sid Wade" <sid@vivato.net> in regards to busybox. * *   NOTE: uClibc mktime behavior is different than glibc's when *   the struct tm has tm_isdst == -1 and also had fields outside of *   the normal ranges. *  *   Apparently, glibc examines (at least) tm_sec and guesses the app's *   intention of assuming increasing or decreasing time when entering an *   ambiguous time period at the dst<->st boundaries. * *   The uClibc behavior is to always normalize the struct tm and then *   try to determing the dst setting. * *   As long as tm_isdst != -1 or the time specifiec by struct tm is *   unambiguous (not falling in the dst<->st transition region) both *   uClibc and glibc should produce the same result for mktime. * * Oct 31, 2003 Kill the seperate __tm_zone and __tm_tzname[] and which *   doesn't work if you want the memcpy the struct.  Sigh... I didn't *   think about that.  So now, when the extensions are enabled, we *   malloc space when necessary and keep the timezone names in a linked *   list. * *   Fix a dst-related bug which resulted in use of uninitialized data. * * Nov 15, 2003 I forgot to update the thread locking in the last dst fix. * * Dec 14, 2003 Fix some dst issues in _time_mktime(). *   Normalize the tm_isdst value to -1, 0, or 1. *   If no dst for this timezone, then reset tm_isdst to 0. * * May 7, 2004 *   Change clock() to allow wrapping. *   Add timegm() function. *   Make lookup_tzname() static (as it should have been). *   Have strftime() get timezone information from the passed struct *     for the %z and %Z conversions when using struct tm extensions. */#define _GNU_SOURCE#include <stdio.h>#include <stdlib.h>#include <stddef.h>#include <string.h>#include <time.h>#include <limits.h>#include <assert.h>#include <errno.h>#include <ctype.h>#include <langinfo.h>#include <locale.h>#include <bits/uClibc_uintmaxtostr.h>#ifdef __UCLIBC_HAS_XLOCALE__#include <xlocale.h>#endif#ifndef __isleap#define __isleap(y) ( !((y) % 4) && ( ((y) % 100) || !((y) % 400) ) )#endif#ifndef TZNAME_MAX#define TZNAME_MAX _POSIX_TZNAME_MAX#endif/**********************************************************************//* The era code is currently unfinished. *//*  #define ENABLE_ERA_CODE */#define TZ_BUFLEN		(2*TZNAME_MAX + 56)#ifdef __UCLIBC_HAS_TZ_FILE__#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include "paths.h"/* ":<tzname>+hh:mm:ss<tzname>+hh:mm:ss,Mmm.w.d/hh:mm:ss,Mmm.w.d/hh:mm:ss" + nul *//* 1 + 2*(1+TZNAME_MAX+1 + 9 + 7 + 9) + 1 = 2*TZNAME_MAX + 56 */#else  /* __UCLIBC_HAS_TZ_FILE__ *//* Probably no longer needed. */#undef __UCLIBC_HAS_TZ_FILE_READ_MANY__#endif /* __UCLIBC_HAS_TZ_FILE__ *//**********************************************************************/extern struct tm __time_tm;typedef struct {	long gmt_offset;	long dst_offset;	short day;					/* for J or normal */	short week;	short month;	short rule_type;			/* J, M, \0 */	char tzname[TZNAME_MAX+1];} rule_struct;#ifdef __UCLIBC_HAS_THREADS__#include <pthread.h>extern pthread_mutex_t _time_tzlock;#define TZLOCK		__pthread_mutex_lock(&_time_tzlock)#define TZUNLOCK	__pthread_mutex_unlock(&_time_tzlock)#else#define TZLOCK		((void) 0)#define TZUNLOCK	((void) 0)#endifextern rule_struct _time_tzinfo[2];extern struct tm *_time_t2tm(const time_t *__restrict timer,							 int offset, struct tm *__restrict result);extern time_t _time_mktime(struct tm *timeptr, int store_on_success);extern struct tm *__time_localtime_tzi(const time_t *__restrict timer,									   struct tm *__restrict result,									   rule_struct *tzi);extern time_t _time_mktime_tzi(struct tm *timeptr, int store_on_success,							   rule_struct *tzi);/**********************************************************************/#ifdef L_asctimestatic char __time_str[26];char *asctime(const struct tm *__restrict ptm){	return asctime_r(ptm, __time_str);}#endif/**********************************************************************/#ifdef L_asctime_r/* Strictly speaking, this implementation isn't correct.  ANSI/ISO specifies * that the implementation of asctime() be equivalent to * *   char *asctime(const struct tm *timeptr) *   { *       static char wday_name[7][3] = { *           "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" *       }; *       static char mon_name[12][3] = { *           "Jan", "Feb", "Mar", "Apr", "May", "Jun", *           "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"  *       }; *       static char result[26]; *    *       sprintf(result, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n", *           wday_name[timeptr->tm_wday],                    *           mon_name[timeptr->tm_mon], *           timeptr->tm_mday, timeptr->tm_hour, *           timeptr->tm_min, timeptr->tm_sec,   *           1900 + timeptr->tm_year);         *       return result; *   } * * but the above is either inherently unsafe, or carries with it the implicit * assumption that all fields of timeptr fall within their usual ranges, and * that the tm_year value falls in the range [-2899,8099] to avoid overflowing * the static buffer. * * If we take the implicit assumption as given, then the implementation below * is still incorrect for tm_year values < -900, as there will be either * 0-padding and/or a missing negative sign for the year conversion .  But given * the ususal use of asctime(), I think it isn't unreasonable to restrict correct * operation to the domain of years between 1000 and 9999. *//* This is generally a good thing, but if you're _sure_ any data passed will be * in range, you can #undef this. */#define SAFE_ASCTIME_R		1static const unsigned char at_data[] = {	'S', 'u', 'n', 'M', 'o', 'n', 'T', 'u', 'e', 'W', 'e', 'd',	'T', 'h', 'u', 'F', 'r', 'i', 'S', 'a', 't',	'J', 'a', 'n', 'F', 'e', 'b', 'M', 'a', 'r', 'A', 'p', 'r',	'M', 'a', 'y', 'J', 'u', 'n', 'J', 'u', 'l', 'A', 'u', 'g',	'S', 'e', 'p', 'O', 'c', 't', 'N', 'o', 'v', 'D', 'e', 'c', #ifdef SAFE_ASCTIME_R	'?', '?', '?', #endif	' ', '?', '?', '?',	' ', '0',	offsetof(struct tm, tm_mday),	' ', '0',	offsetof(struct tm, tm_hour),	':', '0',	offsetof(struct tm, tm_min),	':', '0',	offsetof(struct tm, tm_sec),	' ', '?', '?', '?', '?', '\n', 0};char *asctime_r(register const struct tm *__restrict ptm,				register char *__restrict buffer){	int tmp;	assert(ptm);	assert(buffer);#ifdef SAFE_ASCTIME_R	memcpy(buffer, at_data + 3*(7 + 12), sizeof(at_data) - 3*(7 + 12));	if (((unsigned int)(ptm->tm_wday)) <= 6) {		memcpy(buffer, at_data + 3 * ptm->tm_wday, 3);	}	if (((unsigned int)(ptm->tm_mon)) <= 11) {		memcpy(buffer + 4, at_data + 3*7 + 3 * ptm->tm_mon, 3);	}#else	assert(((unsigned int)(ptm->tm_wday)) <= 6);	assert(((unsigned int)(ptm->tm_mon)) <= 11);	memcpy(buffer, at_data + 3*(7 + 12) - 3, sizeof(at_data) + 3 - 3*(7 + 12));	memcpy(buffer, at_data + 3 * ptm->tm_wday, 3);	memcpy(buffer + 4, at_data + 3*7 + 3 * ptm->tm_mon, 3);#endif#ifdef SAFE_ASCTIME_R	buffer += 19;	tmp = ptm->tm_year + 1900;	if (((unsigned int) tmp) < 10000) {		buffer += 4;		do {			*buffer = '0' + (tmp % 10);			tmp /= 10;		} while (*--buffer == '?');	}#else  /* SAFE_ASCTIME_R */	buffer += 23;	tmp = ptm->tm_year + 1900;	assert( ((unsigned int) tmp) < 10000 );	do {		*buffer = '0' + (tmp % 10);		tmp /= 10;	} while (*--buffer == '?');#endif /* SAFE_ASCTIME_R */	do {		--buffer;		tmp = *((int *)(((const char *) ptm) + (int) *buffer));#ifdef SAFE_ASCTIME_R		if (((unsigned int) tmp) >= 100) { /* Just check 2 digit non-neg. */			buffer[-1] = *buffer = '?';		} else#else  /* SAFE_ASCTIME_R */		assert(((unsigned int) tmp) < 100); /* Just check 2 digit non-neg. */#endif /* SAFE_ASCTIME_R */		{			*buffer = '0' + (tmp % 10);#ifdef __BCC__			buffer[-1] = '0' + (tmp/10);#else  /* __BCC__ */			buffer[-1] += (tmp/10);#endif /* __BCC__ */		}	} while ((buffer -= 2)[-2] == '0');	if (*++buffer == '0') {		/* Space-pad day of month. */		*buffer = ' ';	}	return buffer - 8;}#endif/**********************************************************************/#ifdef L_clock#include <sys/times.h>#ifndef __BCC__#if CLOCKS_PER_SEC != 1000000L#error unexpected value for CLOCKS_PER_SEC!#endif#endif#ifdef __UCLIBC_CLK_TCK_CONST# if __UCLIBC_CLK_TCK_CONST > CLOCKS_PER_SEC#  error __UCLIBC_CLK_TCK_CONST > CLOCKS_PER_SEC!# elif __UCLIBC_CLK_TCK_CONST < 1#  error __UCLIBC_CLK_TCK_CONST < 1!# endif#endif/* Note: SUSv3 notes * *   On XSI-conformant systems, CLOCKS_PER_SEC is defined to be one million. * *   The value returned by clock() may wrap around on some implementations. *   For example, on a machine with 32-bit values for clock_t, it wraps *   after 2147 seconds. * * This implies that we should bitwise and with LONG_MAX. */clock_t clock(void){	struct tms xtms;	unsigned long t;	times(&xtms);	t = ((unsigned long) xtms.tms_utime) + xtms.tms_stime;#ifndef __UCLIBC_CLK_TCK_CONST# error __UCLIBC_CLK_TCK_CONST not defined!#elif ((CLOCKS_PER_SEC % __UCLIBC_CLK_TCK_CONST) == 0)	/* CLOCKS_PER_SEC == k * __UCLIBC_CLK_TCK_CONST for some integer k >= 1. */	return ((t * (CLOCKS_PER_SEC/__UCLIBC_CLK_TCK_CONST)) & LONG_MAX);#else	/* Unlike the previous case, the scaling factor is not an integer.	 * So when tms_utime, tms_stime, or their sum wraps, some of the	 * "visible" bits in the return value are affected.  Nothing we	 * can really do about this though other than handle tms_utime and	 * tms_stime seperately and then sum.  But since that doesn't really	 * buy us much, we don't bother. */	return ((((t / __UCLIBC_CLK_TCK_CONST) * CLOCKS_PER_SEC)			 + ((((t % __UCLIBC_CLK_TCK_CONST) * CLOCKS_PER_SEC)				 / __UCLIBC_CLK_TCK_CONST))			 ) & LONG_MAX);#endif}#endif/**********************************************************************/#ifdef L_ctimechar *ctime(const time_t *clock){	/* ANSI/ISO/SUSv3 say that ctime is equivalent to the following. */	return asctime(localtime(clock));}#endif/**********************************************************************/#ifdef L_ctime_rchar *ctime_r(const time_t *clock, char *buf){	struct tm xtm;	return asctime_r(localtime_r(clock, &xtm), buf);}#endif/**********************************************************************/#ifdef L_difftime#include <float.h>#if FLT_RADIX != 2#error difftime implementation assumptions violated for you arch!#endifdouble difftime(time_t time1, time_t time0){#if (LONG_MAX >> DBL_MANT_DIG) == 0	/* time_t fits in the mantissa of a double. */	return ((double) time1) - time0;#elif ((LONG_MAX >> DBL_MANT_DIG) >> DBL_MANT_DIG) == 0	/* time_t can overflow the mantissa of a double. */	time_t t1, t0, d;	d = ((time_t) 1) << DBL_MANT_DIG;	t1 = time1 / d;	time1 -= (t1 * d);	t0 = time0 / d;	time0 -= (t0*d);	/* Since FLT_RADIX==2 and d is a power of 2, the only possible	 * rounding error in the expression below would occur from the	 * addition. */	return (((double) t1) - t0) * d + (((double) time1) - time0);#else#error difftime needs special implementation on your arch.#endif}#endif/**********************************************************************/#ifdef L_gmtimestruct tm *gmtime(const time_t *timer){	register struct tm *ptm = &__time_tm;	_time_t2tm(timer, 0, ptm); /* Can return NULL... */	return ptm;}#endif/**********************************************************************/#ifdef L_gmtime_rstruct tm *gmtime_r(const time_t *__restrict timer,					struct tm *__restrict result){	return _time_t2tm(timer, 0, result);}#endif/**********************************************************************/#ifdef L_localtimestruct tm *localtime(const time_t *timer){	register struct tm *ptm = &__time_tm;	/* In this implementation, tzset() is called by localtime_r().  */	localtime_r(timer, ptm);	/* Can return NULL... */	return ptm;}#endif/**********************************************************************/#ifdef L_localtime_rstruct tm *localtime_r(register const time_t *__restrict timer,					   register struct tm *__restrict result){	TZLOCK;	tzset();	__time_localtime_tzi(timer, result, _time_tzinfo);	TZUNLOCK;	return result;}#endif/**********************************************************************/#ifdef L__time_localtime_tzi#ifdef __UCLIBC_HAS_TM_EXTENSIONS__struct ll_tzname_item;typedef struct ll_tzname_item {	struct ll_tzname_item *next;	char tzname[TZNAME_MAX+1];} ll_tzname_item_t;static ll_tzname_item_t ll_tzname[] = {	{ ll_tzname + 1, "UTC" },	/* Always 1st. */	{ NULL, "???" }		  /* Always 2nd. (invalid or out-of-memory) */};static const char *lookup_tzname(const char *key){	ll_tzname_item_t *p;	for (p=ll_tzname ; p ; p=p->next) {		if (!strcmp(p->tzname, key)) {			return p->tzname;		}	}	/* Hmm... a new name. */	if (strnlen(key, TZNAME_MAX+1) < TZNAME_MAX+1) { /* Verify legal length */		if ((p = malloc(sizeof(ll_tzname_item_t))) != NULL) {			/* Insert as 3rd item in the list. */			p->next = ll_tzname[1].next;			ll_tzname[1].next = p;

⌨️ 快捷键说明

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