278 lines
9.2 KiB
C
278 lines
9.2 KiB
C
|
/*
|
||
|
********************************************************************************
|
||
|
**
|
||
|
** \file ./boot/startup/src/tzset.c
|
||
|
**
|
||
|
** \version $Id: tzset.c 6304 2016-03-18 03:39:06Z chenke $
|
||
|
**
|
||
|
** \brief ARM1176 RealView libc function retargeting.
|
||
|
**
|
||
|
** This files retargets the time zone specific function tzset().
|
||
|
**
|
||
|
** \attention THIS SAMPLE CODE IS PROVIDED AS IS. FUJITSU MICROELECTRONICS
|
||
|
** ACCEPTS NO RESPONSIBILITY OR LIABILITY FOR ANY ERRORS OR
|
||
|
** OMMISSIONS.
|
||
|
**
|
||
|
** (C) Copyright 2006-2010 by Fujitsu Microelectronics Europe GmbH
|
||
|
** (C) Copyright 2010 by Fujitsu Semiconductor Europe GmbH
|
||
|
**
|
||
|
********************************************************************************
|
||
|
**
|
||
|
** \note The following LINT statements have been suppressed:
|
||
|
**
|
||
|
**
|
||
|
*****************************************************************************
|
||
|
*/
|
||
|
|
||
|
//**************************************************************************
|
||
|
//**************************************************************************
|
||
|
//** Standard includes
|
||
|
//**************************************************************************
|
||
|
//**************************************************************************
|
||
|
|
||
|
//#include <stdchar.h>
|
||
|
#include <stdint.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
//#include <time_ext.h>
|
||
|
#include <time.h>
|
||
|
#include "internal.h"
|
||
|
|
||
|
//**************************************************************************
|
||
|
//**************************************************************************
|
||
|
//** FAPI includes
|
||
|
//**************************************************************************
|
||
|
//**************************************************************************
|
||
|
|
||
|
|
||
|
//**************************************************************************
|
||
|
//**************************************************************************
|
||
|
//** Defines and Macros
|
||
|
//**************************************************************************
|
||
|
//**************************************************************************
|
||
|
#ifndef TZNAME_MAX
|
||
|
#define TZNAME_MAX 16
|
||
|
#endif
|
||
|
|
||
|
#define TZ_DEFAULT "GMT0"
|
||
|
#define TZ_INIT_STD_OFFSET 0L // in seconds
|
||
|
#define TZ_INIT_STD_NAME "GMT"
|
||
|
#define TZ_INIT_DST_OFFSET 0 // in seconds
|
||
|
#define TZ_INIT_DST_NAME ""
|
||
|
#define TZ_DEFAULT_DST_OFFSET -3600 // in seconds
|
||
|
|
||
|
|
||
|
//**************************************************************************
|
||
|
//**************************************************************************
|
||
|
//** Global Data
|
||
|
//**************************************************************************
|
||
|
//**************************************************************************
|
||
|
static char _stdname[TZNAME_MAX] = TZ_INIT_STD_NAME;
|
||
|
static char _dstname[TZNAME_MAX] = TZ_INIT_DST_NAME;
|
||
|
char * _tzname[2] = { _stdname, _dstname };
|
||
|
long _timezone = TZ_INIT_STD_OFFSET;
|
||
|
int _daylight = TZ_INIT_DST_OFFSET;
|
||
|
|
||
|
//******************************************************************************
|
||
|
//******************************************************************************
|
||
|
//** Local Functions Declaration
|
||
|
//******************************************************************************
|
||
|
//******************************************************************************
|
||
|
static size_t scanTzString(char_t **tz, char_t *name);
|
||
|
static int8_t scanTzOffset(char_t **tz, int32_t *offset);
|
||
|
|
||
|
//******************************************************************************
|
||
|
//******************************************************************************
|
||
|
//** API Functions
|
||
|
//******************************************************************************
|
||
|
//******************************************************************************
|
||
|
|
||
|
/*
|
||
|
********************************************************************************
|
||
|
** \brief Retarget implementation of the stdc library function.
|
||
|
**
|
||
|
** This is the standard C library tzset() function from time.h.
|
||
|
**
|
||
|
** The tzset() function shall use the value of the environment variable TZ to
|
||
|
** set time conversion information used by ctime(), localtime(), mktime() and
|
||
|
** strftime().
|
||
|
** The tzset() function also shall set the external variable daylight to 0
|
||
|
** if daylight savings time (DST) conversions should never be applied for the
|
||
|
** timezone in use; otherwise, non-zero. The external variable timezone shall be
|
||
|
** set to the difference, in seconds, between coordinated universal time (UTC)
|
||
|
** and local standard time.
|
||
|
********************************************************************************
|
||
|
*/
|
||
|
void tzset( void )
|
||
|
{
|
||
|
char_t *tzdefault = TZ_DEFAULT;
|
||
|
char_t std_name[TZNAME_MAX];
|
||
|
char_t dst_name[TZNAME_MAX];
|
||
|
int32_t std_offset = TZ_INIT_STD_OFFSET;
|
||
|
int32_t dst_offset = TZ_INIT_DST_OFFSET;
|
||
|
char_t *tz = getenv("TZ"); /* get the environment time zone setting */
|
||
|
uint32_t cpu_flags;
|
||
|
|
||
|
/* check, if tz string is valid */
|
||
|
if (tz == NULL) {
|
||
|
tz = tzdefault; /* if environment doesn't exist, use default */
|
||
|
}
|
||
|
|
||
|
/* extract std timzone name */
|
||
|
if (scanTzString(&tz, std_name) == 0) {
|
||
|
strcpy(std_name, TZ_INIT_STD_NAME);
|
||
|
}
|
||
|
|
||
|
/* extract std timzone offset (in s) */
|
||
|
if (scanTzOffset(&tz, &std_offset) == 0) {
|
||
|
std_offset = TZ_INIT_STD_OFFSET;
|
||
|
}
|
||
|
|
||
|
/* extract dst timzone name */
|
||
|
if (scanTzString(&tz, dst_name) == 0) {
|
||
|
strcpy(dst_name, TZ_INIT_DST_NAME);
|
||
|
dst_offset = TZ_INIT_DST_OFFSET;
|
||
|
}
|
||
|
/* extract dst timzone offset (in s) relative to std */
|
||
|
else if (scanTzOffset(&tz, &dst_offset) == 0) {
|
||
|
dst_offset = TZ_DEFAULT_DST_OFFSET;
|
||
|
}
|
||
|
else {
|
||
|
dst_offset -= std_offset;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////
|
||
|
cpu_flags = st_enter_crit_func();
|
||
|
//////////////////////////////////
|
||
|
|
||
|
/* assign global values */
|
||
|
_daylight = (strcmp(dst_name, "") != 0) ? dst_offset : 0;
|
||
|
_timezone = std_offset;
|
||
|
strcpy(tzname[0], std_name);
|
||
|
strcpy(tzname[1], dst_name);
|
||
|
|
||
|
//////////////////////////////
|
||
|
st_exit_crit_func(cpu_flags);
|
||
|
//////////////////////////////
|
||
|
|
||
|
}
|
||
|
|
||
|
//******************************************************************************
|
||
|
//******************************************************************************
|
||
|
//** Local Functions
|
||
|
//******************************************************************************
|
||
|
//******************************************************************************
|
||
|
|
||
|
/*
|
||
|
********************************************************************************
|
||
|
** \brief Extracts (next) timezone (resp. DST) name from timezone string.
|
||
|
**
|
||
|
** This function extracts the next occurrence of a timezone name (either std
|
||
|
** or dst) in the given timezone string.
|
||
|
**
|
||
|
** \note A leading colon, which POSIX allows as an implementation-
|
||
|
** specific extension, is not supported.
|
||
|
**
|
||
|
** \param tz (part of a) time zone string
|
||
|
** \param name extracted time zone (std resp. dst) name from first part of tz
|
||
|
**
|
||
|
** \return length of extracted time zone name string
|
||
|
********************************************************************************
|
||
|
*/
|
||
|
static size_t scanTzString(char_t **tz, char_t *name) {
|
||
|
char_t *p = *tz;
|
||
|
size_t i = 0;
|
||
|
|
||
|
/* leading colon for implementation-specific extension is not supported */
|
||
|
if (*p != ':') {
|
||
|
while ((strchr("0123456789-+,", *p) == NULL) && (i < TZNAME_MAX)) {
|
||
|
name[i++] = *p++;
|
||
|
}
|
||
|
/* finalize string */
|
||
|
if (i == TZNAME_MAX) {
|
||
|
--i;
|
||
|
}
|
||
|
name[i] = '\0';
|
||
|
}
|
||
|
|
||
|
*tz = p;
|
||
|
return (i);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
********************************************************************************
|
||
|
** \brief Extracts (next) timezone (resp. DST) offset from timezone string.
|
||
|
**
|
||
|
** This function extracts the next occurrence of a timezone offset (either std
|
||
|
** or dst) in the given timezone string.
|
||
|
**
|
||
|
** \note A leading colon, which POSIX allows as an implementation-
|
||
|
** specific extension, is not supported.
|
||
|
**
|
||
|
** \param tz (part of a) time zone string
|
||
|
** \param offset extracted time zone (std resp. dst) offset (in seconds) from
|
||
|
** first part of tz
|
||
|
**
|
||
|
** \return
|
||
|
** - 1, if time zone value was successfully extracted and is valid,
|
||
|
** - 0, in error case
|
||
|
********************************************************************************
|
||
|
*/
|
||
|
static int8_t scanTzOffset(char_t **tz, int32_t *offset) {
|
||
|
int8_t sign;
|
||
|
char_t *p;
|
||
|
char_t *endp = 0;
|
||
|
int32_t secs;
|
||
|
int32_t v;
|
||
|
|
||
|
/* check parameter valitidy */
|
||
|
if ((offset == 0) || (tz == 0) || (*tz == 0)) {
|
||
|
return (0);
|
||
|
}
|
||
|
|
||
|
/* extract hours value */
|
||
|
v = strtol(*tz, &endp, 10);
|
||
|
|
||
|
/* no offset value found */
|
||
|
if (*tz == endp ) {
|
||
|
return (0);
|
||
|
}
|
||
|
|
||
|
/* extract sign for correct calculation and latter assignment */
|
||
|
sign = (v < 0) ? -1 : 1;
|
||
|
v = v * sign;
|
||
|
|
||
|
/* convert to seconds */
|
||
|
secs = v * 3600L;
|
||
|
|
||
|
/* extract minutes value */
|
||
|
p = endp;
|
||
|
if ( *p == ':' ) {
|
||
|
p++;
|
||
|
v = strtol(p, &endp, 10);
|
||
|
if (p != endp) {
|
||
|
secs += v * 60L;
|
||
|
}
|
||
|
|
||
|
/* extract seconds value */
|
||
|
p = endp;
|
||
|
if ( *p == ':' ) {
|
||
|
p++;
|
||
|
v = strtol(p, &endp, 10);
|
||
|
if (p != endp) {
|
||
|
secs += v;
|
||
|
}
|
||
|
p = endp;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* re-apply sign value */
|
||
|
*offset = sign * secs;
|
||
|
|
||
|
/* move timezone pointer to the residual string */
|
||
|
*tz = p;
|
||
|
|
||
|
return(1);
|
||
|
}
|
||
|
|