scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

commit 07a0d5a07e238e5cd637bcfac976b69d698651d9
parent b118ad2f51757c015aec5f72c813b20e8048530a
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Fri, 27 Aug 2021 11:44:57 +0200

libc: Update time to last version

This code is being updated out of the tree of scc and
it is time to synchroniza both copies now.

Diffstat:
Msrc/libc/libc.h | 66+++++++++++++++++++++++++++++++++++-------------------------------
Msrc/libc/objs/common-objs.mk | 2++
Msrc/libc/time/Makefile | 1+
Msrc/libc/time/_daysyear.c | 19-------------------
Asrc/libc/time/_newyear.c | 15+++++++++++++++
Msrc/libc/time/asctime.c | 8+++++++-
Msrc/libc/time/ctime.c | 1+
Msrc/libc/time/difftime.c | 3++-
Msrc/libc/time/gmtime.c | 15++++++++-------
Msrc/libc/time/localtime.c | 8++------
Msrc/libc/time/mktime.c | 75+++++++++++++++++++++++++++++++++------------------------------------------
Msrc/libc/time/strftime.c | 189+++++++++++++++++++++++++++++++++++++++++--------------------------------------
12 files changed, 203 insertions(+), 199 deletions(-)

diff --git a/src/libc/libc.h b/src/libc/libc.h @@ -1,20 +1,25 @@ -#define SUN 0 -#define MON 1 -#define TUE 2 -#define WED 3 -#define THU 4 -#define FRI 5 -#define SAT 6 - -#define JAN 0 -#define FEB 1 -#define DEC 11 +enum { + SUN, + MON, + TUE, + WED, + THU, + FRI, + SAT +}; + +#define JAN 0 +#define FEB 1 +#define DEC 11 -#define EPOCH 1970 #define FEBDAYS(y) ((_daysyear(y) == 366) ? 29 : 28) -#define SECMIN 60 -#define SECHOUR (60 * SECMIN) /* 3600 */ -#define SECDAY (24 * SECHOUR) /* 86400 */ +#define EPOCH 1970 +#define MINYEAR 1900 +#define SECMIN 60 +#define SECHOUR (60 * SECMIN) /* 3600 */ +#define SECDAY (24 * SECHOUR) /* 86400 */ + +struct tm; struct tzone { char *name; @@ -22,28 +27,27 @@ struct tzone { int isdst; }; -struct tm; - -extern void _tzset(void); -extern int _daysyear(int year); -extern int _newyear(int year); extern void *_getheap(void); -extern int _dtoi(char); + +#ifdef stdin +extern int _allocbuf(FILE *); +extern int _flsbuf(FILE *); +extern FILE *_fpopen(const char * restrict, const char *restrict, + FILE *restrict); +#endif #ifdef _TIME_H -extern char *_tzname[2]; extern time_t _tzstdoff, _tzdstoff; extern time_t _tzstart, _tzend; -extern int _tzjulian; -extern struct tzone tzones[]; -#endif -#ifdef stdin -extern int _flsbuf(FILE *fp); -extern int _allocbuf(FILE *fp); -extern FILE *_fpopen(const char * restrict fname, - const char * restrict mode, - FILE * restrict fp); +extern time_t _systime(struct tm *); #endif +extern void _tzset(void); +extern int _daysyear(int); +extern int _newyear(int); + +extern int _tzjulian; extern int _daysmon[12]; +extern char *_tzname[2]; +extern struct tzone tzones[]; diff --git a/src/libc/objs/common-objs.mk b/src/libc/objs/common-objs.mk @@ -98,6 +98,7 @@ COMMON_OBJS =\ string/strtok.$O\ string/strxfrm.$O\ time/_daysyear.$O\ + time/_newyear.$O\ time/asctime.$O\ time/ctime.$O\ time/difftime.$O\ @@ -105,3 +106,4 @@ COMMON_OBJS =\ time/localtime.$O\ time/mktime.$O\ time/strftime.$O\ + time/tz.$O\ diff --git a/src/libc/time/Makefile b/src/libc/time/Makefile @@ -5,6 +5,7 @@ include ../rules.mk OBJS =\ _daysyear.$O\ + _newyear.$O\ asctime.$O\ ctime.$O\ difftime.$O\ diff --git a/src/libc/time/_daysyear.c b/src/libc/time/_daysyear.c @@ -1,6 +1,3 @@ -#include <time.h> -#include "../libc.h" - int _daysmon[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; int @@ -12,19 +9,3 @@ _daysyear(int year) return 365; return 366; } - -/* - * Happy New Year!!!! - */ -int -_newyear(int year) -{ - int day; - - year += 1900 - 1; - day = 1 + year + year/4; - day -= year/100; - day += year/400; - - return day % 7; -} diff --git a/src/libc/time/_newyear.c b/src/libc/time/_newyear.c @@ -0,0 +1,15 @@ +/* + * Happy New Year!!!! + */ +int +_newyear(int year) +{ + int day; + + year += 1900 - 1; + day = 1 + year + year/4; + day -= year/100; + day += year/400; + + return day % 7; +} diff --git a/src/libc/time/asctime.c b/src/libc/time/asctime.c @@ -1,11 +1,17 @@ #include <time.h> + #undef asctime char * asctime(const struct tm *tm) { - static char buf[30]; + static char buf[26]; + /* + * buf has space for a text like "Sun Sep 16 01:03:52 1973\n\0" + * and for this reason strftime cannot fail as the buffer is + * long enough + */ strftime(buf, sizeof(buf), "%c\n", tm); return buf; } diff --git a/src/libc/time/ctime.c b/src/libc/time/ctime.c @@ -1,4 +1,5 @@ #include <time.h> + #undef ctime char * diff --git a/src/libc/time/difftime.c b/src/libc/time/difftime.c @@ -1,8 +1,9 @@ #include <time.h> + #undef difftime double difftime(time_t t1, time_t t2) { - return (double) (t1 - t2); + return t2 - t1; } diff --git a/src/libc/time/gmtime.c b/src/libc/time/gmtime.c @@ -1,27 +1,28 @@ #include <time.h> #include "../libc.h" + #undef gmtime struct tm * -gmtime(const time_t *t) +gmtime(const time_t *tim) { - static struct tm tm; - time_t sec, min, hour, year, day; + static struct tm tm; + time_t day; int i; - tm.tm_sec = *t % SECDAY; + tm.tm_sec = *tim % SECDAY; tm.tm_min = tm.tm_sec / 60; tm.tm_sec %= 60; tm.tm_hour = tm.tm_min / 60; tm.tm_min %= 60; - day = *t / SECDAY; + day = *tim / SECDAY; tm.tm_wday = (day + THU) % 7; /* 1/1/1970 was Thursday */ for (i = EPOCH; day >= _daysyear(i); ++i) day -= _daysyear(i); - tm.tm_year = i - 1900; + tm.tm_year = i - 1900; tm.tm_yday = day; _daysmon[FEB] = FEBDAYS(tm.tm_year); @@ -32,5 +33,5 @@ gmtime(const time_t *t) tm.tm_isdst = 0; - return &tm; + return &tm; } diff --git a/src/libc/time/localtime.c b/src/libc/time/localtime.c @@ -38,14 +38,10 @@ localtime(const time_t *timep) tm->tm_zone = _tzname[0]; tm->tm_isdst = 0; - if (_tzjulian && - ((yday + 1) < 60) || - (FEBDAYS(tm->tm_year) < 29)) + if (_tzjulian && yday+1 < 60 || FEBDAYS(tm->tm_year) < 29) yday++; - if (yday >= _tzstart && - yday <= _tzend && - tm->tm_hour >= 2) { + if (yday >= _tzstart && yday <= _tzend && tm->tm_hour >= 2) { tm->tm_gmtoff = _tzdstoff; tm->tm_zone = _tzname[1]; tm->tm_isdst = 1; diff --git a/src/libc/time/mktime.c b/src/libc/time/mktime.c @@ -2,23 +2,24 @@ #include <time.h> #include "../libc.h" + #undef mktime static int -norm(int *val, int *next, int qty) +norm(int *val, int *next, int max) { int v = *val, n = *next, d; if (v < 0) { - d = -v / qty + 1; - v += d * qty; + d = -v / max + 1; + v += d * max; if (n > INT_MAX - d) return 0; n -= d; } - if (v >= qty) { - d = v / qty; - v -= d * qty; + if (v >= max) { + d = v / max; + v -= d * max; if (n < INT_MIN + d) return 0; n += d; @@ -33,29 +34,41 @@ static int normalize(struct tm *tm) { int mon, day, year, yday; - struct tm aux = *tm; - if (!norm(&tm->tm_sec, &tm->tm_min, 60) || - !norm(&tm->tm_min, &tm->tm_hour, 60) || - !norm(&tm->tm_hour, &tm->tm_mday, 24) || - !norm(&tm->tm_mon, &tm->tm_year, 12)) { + /* + * Normalize sec so that it doesn't over/underflow min + * Normalize min so that it doesn't over/underflow hour + * Normalize hour so that it doesn't over/underflow mday + * Normalize month so that it doesn't over/underflow year + */ + if (!norm(&tm->tm_sec, &tm->tm_min, 60) + || !norm(&tm->tm_min, &tm->tm_hour, 60) + || !norm(&tm->tm_hour, &tm->tm_mday, 24) + || !norm(&tm->tm_mon, &tm->tm_year, 12)) return 0; - } if (tm->tm_year < 0) return 0; day = tm->tm_mday; yday = 0; - year = 1900 + tm->tm_year; + year = MINYEAR + tm->tm_year; + + if (year > _MAXYEAR) + return 0; + _daysmon[FEB] = FEBDAYS(year); + /* + * Normalize mday so that it doesn't over/underflow month + * Normalize month so that it doesn't over/underflow year + */ for (mon = tm->tm_mon; day < 1; --mon) { if (mon == JAN) { - if (year == 1900) + if (year == MINYEAR) return 0; year--; - _daysmon[FEB] = FEBDAYS(year); + _daysmon[FEB] = _febdays(year); mon = DEC+1; } day += _daysmon[mon-1]; @@ -67,49 +80,27 @@ normalize(struct tm *tm) if (year == _MAXYEAR) return 0; year++; - _daysmon[FEB] = FEBDAYS(year); + _daysmon[FEB] = _febdays(year); mon = JAN-1; } } - for (int i = 0; i < mon; i++) + for (int i = 0; i < mon; ++i) yday += _daysmon[i]; tm->tm_mon = mon; - tm->tm_year = year - 1900; + tm->tm_year = year - MINYEAR; tm->tm_mday = day; tm->tm_yday = yday + day - 1; tm->tm_wday = (_newyear(tm->tm_year) + tm->tm_yday) % 7; - + tm->tm_isdst = 0; return 1; } time_t mktime(struct tm *tm) { - int i, year, dst; - time_t t; - struct tm *aux; - if (!normalize(tm)) return -1; - - t = 0; - year = tm->tm_year + 1900; - for (i = EPOCH; i < year; i++) - t += _daysyear(i) * SECDAY; - - for (i = 0; i < tm->tm_mon; i++) - t += _daysmon[i] * SECDAY; - - t += tm->tm_sec; - t += tm->tm_min * SECMIN; - t += tm->tm_hour * SECHOUR; - t += (tm->tm_mday-1) * SECDAY; - - aux = localtime(&t); - - t += aux->tm_gmtoff; - - return t; + return _systime(tm); } diff --git a/src/libc/time/strftime.c b/src/libc/time/strftime.c @@ -1,7 +1,8 @@ -#include <time.h> #include <string.h> +#include <time.h> #include "../libc.h" + #undef strftime static char *days[] = { @@ -30,9 +31,8 @@ first(int day, int year) return day - ny; } - static int -weeknum(struct tm* tm, int day) +weeknum(struct tm *tm, int day) { int fday, val; @@ -48,7 +48,7 @@ weeknum(struct tm* tm, int day) } static int -isoyear(struct tm* tm) +isoyear(struct tm *tm) { int monday; @@ -65,24 +65,31 @@ isoyear(struct tm* tm) } static int -isoweek(struct tm* tm) +isoweek(struct tm *tm) { int year, monday, yday, val; year = isoyear(tm); monday = first(THU, year) - 3; yday = tm->tm_yday; - if (year > tm->tm_year) { + if (year > tm->tm_year) yday = tm->tm_mday - 31 + monday; - } else if (year < tm->tm_year) { + else if (year < tm->tm_year) yday = _daysyear(year) + yday; - } val = yday - monday; val /= 7; val++; return val; } +static int +isoday(struct tm *tm) +{ + if (tm->tm_wday == 0) + return 7; + return tm->tm_wday; +} + static size_t sval(char *s, size_t siz, char **strs, int abrev, int idx, int max) { @@ -134,10 +141,10 @@ timezone(char *s, size_t prec, const struct tm * restrict tm) { long off = tm->tm_gmtoff; - if (prec < 5) { - *s = '?'; - return 1; - } + if (prec < 5) { + *s = '?'; + return 1; + } if (off >= 0) { *s++ = '+'; @@ -153,15 +160,14 @@ timezone(char *s, size_t prec, const struct tm * restrict tm) } size_t -strftime(char * restrict s, size_t siz, - const char * restrict fmt, - const struct tm * restrict tm) +strftime(char *restrict s, size_t maxsize, + const char *restrict format, const struct tm *restrict timeptr) { int ch, abrev, val, fill, width; size_t n, inc; char *tfmt; - for (n = siz-1; (ch = *fmt++) && n > 0; s += inc, n -= inc) { + for (n = --maxsize; (ch = *format++) && n > 0; s += inc, n -= inc) { if (ch != '%') { *s = ch; inc = 1; @@ -172,93 +178,53 @@ strftime(char * restrict s, size_t siz, fill = '0'; width = 2; - if (*fmt == 'E' || *fmt == 'O') { - fmt++; - } + if (*format == 'E' || *format == 'O') + format++; - switch (*fmt++) { - case 'Z': - if (!tm->tm_zone) - break; - inc = sval(s, n, &tm->tm_zone, 0, 0, 1); - break; + switch (*format++) { case 'a': abrev = 1; case 'A': - inc = sval(s, n, days, abrev, tm->tm_wday, 7); + inc = sval(s, n, days, abrev, timeptr->tm_wday, 7); break; case 'h': case 'b': abrev = 1; case 'B': - inc = sval(s, n, months, abrev, tm->tm_mon, 12); - break; - case 'p': - inc = sval(s, n, am_pm, 0, tm->tm_hour > 12, 2); + inc = sval(s, n, months, abrev, timeptr->tm_mon, 12); break; case 'c': tfmt = "%a %b %e %T %Y"; goto recursive; + case 'C': + val = (timeptr->tm_year + 1900) / 100; + goto number; + case 'd': + val = timeptr->tm_mday; + goto number; case 'D': tfmt = "%m/%d/%y"; goto recursive; - case 'F': - tfmt = "%Y-%m-%d"; - goto recursive; - case 'R': - tfmt = "%H:%M"; - goto recursive; - case 'X': - case 'T': - tfmt = "%H:%M:%S"; - goto recursive; - case 'r': - tfmt = "%I:%M:%S %p"; - goto recursive; - case 'x': - tfmt = "%m/%d/%y"; - goto recursive; - recursive: - inc = strftime(s, n+1, tfmt, tm) - 1; - break; - case 'n': - val = '\n'; - goto character; - case 't': - val = '\t'; - goto character; - case '%': - val = '%'; - character: - *s = val; - inc = 1; - break; case 'e': fill = ' '; - val = tm->tm_mday; - goto number; - case 'd': - val = tm->tm_mday; - goto number; - case 'V': - val = isoweek(tm); + val = timeptr->tm_mday; goto number; + case 'F': + tfmt = "%Y-%m-%d"; + goto recursive; case 'g': - val = isoyear(tm); + val = isoyear(timeptr); goto number; case 'G': - val = isoyear(tm); + val = isoyear(timeptr); val += 1900; width = 4; goto number; - case 'C': - val = (tm->tm_year + 1900) / 100; - goto number; case 'H': - val = tm->tm_hour; + val = timeptr->tm_hour; goto number; case 'I': - val = tm->tm_hour; + val = timeptr->tm_hour; if (val == 0) val = 12; if (val > 12) @@ -266,50 +232,89 @@ strftime(char * restrict s, size_t siz, goto number; case 'j': width = 3; - val = tm->tm_yday+1; + val = timeptr->tm_yday+1; goto number; case 'm': - val = tm->tm_mon+1; + val = timeptr->tm_mon+1; goto number; case 'M': - val = tm->tm_min; + val = timeptr->tm_min; goto number; + case 'n': + val = '\n'; + goto character; + case 'p': + inc = sval(s, n, am_pm, 0, timeptr->tm_hour > 12, 2); + break; + case 'r': + tfmt = "%I:%M:%S %p"; + goto recursive; + case 'R': + tfmt = "%H:%M"; + goto recursive; case 'S': - val = tm->tm_sec; + val = timeptr->tm_sec; goto number; + case 't': + val = '\t'; + goto character; case 'u': width = 1; - val = tm->tm_wday+1; + val = isoday(timeptr); goto number; case 'U': - val = weeknum(tm, SUN); + val = weeknum(timeptr, SUN); goto number; - case 'W': - val = weeknum(tm, MON); + case 'V': + val = isoweek(timeptr); goto number; case 'w': width = 1; - val = tm->tm_wday; + val = timeptr->tm_wday; goto number; + case 'W': + val = weeknum(timeptr, MON); + goto number; + case 'X': + case 'T': + tfmt = "%H:%M:%S"; + goto recursive; + case 'x': + tfmt = "%m/%d/%y"; + goto recursive; case 'y': - val = tm->tm_year%100; + val = timeptr->tm_year%100; goto number; case 'Y': width = 4; - val = 1900 + tm->tm_year; - number: - inc = dval(s, n, width, fill, val); - break; + val = 1900 + timeptr->tm_year; + goto number; case 'z': - inc = timezone(s, n, tm); + inc = timezone(s, n, timeptr); + break; + case 'Z': + memcpy(s, timeptr->tm_zone, 3); + inc = 3; break; case '\0': inc = 0; - --fmt; + --format; + break; + case '%': + val = '%'; + character: + *s = val; + inc = 1; + break; + number: + inc = dval(s, n, width, fill, val); + break; + recursive: + inc = strftime(s, n+1, tfmt, timeptr); break; } } *s = '\0'; - return siz - n; + return maxsize - n; }