Index: ossp-pkg/tai/tai.ac RCS File: /v/ossp/cvs/ossp-pkg/tai/tai.ac,v rcsdiff -q -kk '-r1.2' '-r1.3' -u '/v/ossp/cvs/ossp-pkg/tai/tai.ac,v' 2>/dev/null --- tai.ac 2002/08/14 13:34:01 1.2 +++ tai.ac 2002/08/14 14:28:27 1.3 @@ -33,8 +33,15 @@ dnl # TAI_CHECK_ALL AC_DEFUN(TAI_CHECK_ALL,[ - # check for system functions + # gmtime_r hack for Solaris (FIXME) CFLAGS="$CFLAGS -D_REENTRANT" + + # check for system functions AC_CHECK_FUNCS(gmtime_r timegm) + + # determine whether "tm_gmtoff" exists in "struct tm" + AC_CHECK_MEMBER(struct tm.tm_gmtoff, + AC_DEFINE(HAVE_TM_GMTOFF, 1, [Define to 1 if "struct tm" has "tm_gmtoff"]),, + [#include ]) ]) Index: ossp-pkg/tai/tai_data.c RCS File: /v/ossp/cvs/ossp-pkg/tai/tai_data.c,v rcsdiff -q -kk '-r1.1' '-r1.2' -u '/v/ossp/cvs/ossp-pkg/tai/tai_data.c,v' 2>/dev/null --- tai_data.c 2002/04/18 09:10:46 1.1 +++ tai_data.c 2002/08/14 14:28:27 1.2 @@ -25,7 +25,9 @@ * SUCH DAMAGE. */ +#if 0 #include +#endif #include #if 0 Index: ossp-pkg/tai/tai_format.c RCS File: /v/ossp/cvs/ossp-pkg/tai/tai_format.c,v co -q -kk -p'1.2' '/v/ossp/cvs/ossp-pkg/tai/tai_format.c,v' | diff -u /dev/null - -L'ossp-pkg/tai/tai_format.c' 2>/dev/null --- ossp-pkg/tai/tai_format.c +++ - 2024-05-08 16:33:36.049028424 +0200 @@ -0,0 +1,458 @@ +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#if 0 +static const char elsieid[] = "@(#)strftime.c 7.38"; +static const char sccsid[] = "@(#)strftime.c 5.4 (Berkeley) 3/14/89"; +__FBSDID("$FreeBSD: src/lib/libc/stdtime/strftime.c,v 1.35 2002/03/22 21:53:13 obrien Exp $"); +#endif + +#include +#include +#include +#include +#include + +#include "tai.h" +#include "tai_p.h" + +#define INT_STRLEN_MAXIMUM(type) \ + ((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + 1 + TYPE_SIGNED(type)) +#define TYPE_BIT(type) (sizeof(type)*8) +#define TYPE_SIGNED(type) (((type) -1) < 0) +#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0)) +#define DAYSPERWEEK 7 +#define DAYSPERNYEAR 365 +#define DAYSPERLYEAR 366 + +static char * _add(const char *, char *, const char *); +static char * _conv(int, const char *, char *, const char *); +static char * _fmt(const char *, const struct tm *, char *, const char *); + +#if 0 /* FIXME */ +extern char * tzname[]; +#endif + +size_t +tai_format_int( + char *const s, + const size_t maxsize, + const char *const format, + const struct tm *const t) +{ + char *p; + +#if 0 /* FIXME */ + tzset(); +#endif + p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize); + if (p == s + maxsize) + return 0; + *p = '\0'; + return p - s; +} + +static char * +_fmt( + const char *format, + const struct tm *const t, + char *pt, + const char *const ptlim) +{ + int Ealternative, Oalternative; + const tai_locale_t *tptr = &tai_locale; + + for ( ; *format; ++format) { + if (*format == '%') { + Ealternative = 0; + Oalternative = 0; +label: + switch (*++format) { + case '\0': + --format; + break; + case 'A': + pt = _add((t->tm_wday < 0 || t->tm_wday > 6) ? + "?" : tptr->weekday[t->tm_wday], + pt, ptlim); + continue; + case 'a': + pt = _add((t->tm_wday < 0 || t->tm_wday > 6) ? + "?" : tptr->wday[t->tm_wday], + pt, ptlim); + continue; + case 'B': + pt = _add((t->tm_mon < 0 || t->tm_mon > 11) ? + "?" : (Oalternative ? tptr->alt_month : + tptr->month)[t->tm_mon], + pt, ptlim); + continue; + case 'b': + case 'h': + pt = _add((t->tm_mon < 0 || t->tm_mon > 11) ? + "?" : tptr->mon[t->tm_mon], + pt, ptlim); + continue; + case 'C': + /* + ** %C used to do a... + ** _fmt("%a %b %e %X %Y", t); + ** ...whereas now POSIX 1003.2 calls for + ** something completely different. + ** (ado, 5/24/93) + */ + pt = _conv((t->tm_year + TM_YEAR_BASE) / 100, + "%02d", pt, ptlim); + continue; + case 'c': + pt = _fmt(tptr->c_fmt, t, pt, ptlim); + continue; + case 'D': + pt = _fmt("%m/%d/%y", t, pt, ptlim); + continue; + case 'd': + pt = _conv(t->tm_mday, "%02d", pt, ptlim); + continue; + case 'E': + if (Ealternative || Oalternative) + break; + Ealternative++; + goto label; + case 'O': + /* + ** POSIX locale extensions, a la + ** Arnold Robbins' strftime version 3.0. + ** The sequences + ** %Ec %EC %Ex %EX %Ey %EY + ** %Od %oe %OH %OI %Om %OM + ** %OS %Ou %OU %OV %Ow %OW %Oy + ** are supposed to provide alternate + ** representations. + ** (ado, 5/24/93) + ** + ** FreeBSD extensions + ** %OB %Ef %EF + */ + if (Ealternative || Oalternative) + break; + Oalternative++; + goto label; + case 'e': + pt = _conv(t->tm_mday, "%2d", pt, ptlim); + continue; + case 'F': + pt = _fmt("%Y-%m-%d", t, pt, ptlim); + continue; + case 'H': + pt = _conv(t->tm_hour, "%02d", pt, ptlim); + continue; + case 'I': + pt = _conv((t->tm_hour % 12) ? + (t->tm_hour % 12) : 12, + "%02d", pt, ptlim); + continue; + case 'j': + pt = _conv(t->tm_yday + 1, "%03d", pt, ptlim); + continue; + case 'k': + /* + ** This used to be... + ** _conv(t->tm_hour % 12 ? + ** t->tm_hour % 12 : 12, 2, ' '); + ** ...and has been changed to the below to + ** match SunOS 4.1.1 and Arnold Robbins' + ** strftime version 3.0. That is, "%k" and + ** "%l" have been swapped. + ** (ado, 5/24/93) + */ + pt = _conv(t->tm_hour, "%2d", pt, ptlim); + continue; +#ifdef KITCHEN_SINK + case 'K': + /* + ** After all this time, still unclaimed! + */ + pt = _add("kitchen sink", pt, ptlim); + continue; +#endif /* defined KITCHEN_SINK */ + case 'l': + /* + ** This used to be... + ** _conv(t->tm_hour, 2, ' '); + ** ...and has been changed to the below to + ** match SunOS 4.1.1 and Arnold Robbin's + ** strftime version 3.0. That is, "%k" and + ** "%l" have been swapped. + ** (ado, 5/24/93) + */ + pt = _conv((t->tm_hour % 12) ? + (t->tm_hour % 12) : 12, + "%2d", pt, ptlim); + continue; + case 'M': + pt = _conv(t->tm_min, "%02d", pt, ptlim); + continue; + case 'm': + pt = _conv(t->tm_mon + 1, "%02d", pt, ptlim); + continue; + case 'n': + pt = _add("\n", pt, ptlim); + continue; + case 'p': + pt = _add((t->tm_hour >= 12) ? + tptr->pm : + tptr->am, + pt, ptlim); + continue; + case 'R': + pt = _fmt("%H:%M", t, pt, ptlim); + continue; + case 'r': + pt = _fmt(tptr->ampm_fmt, t, pt, ptlim); + continue; + case 'S': + pt = _conv(t->tm_sec, "%02d", pt, ptlim); + continue; + case 's': + { + struct tm tm; + char buf[INT_STRLEN_MAXIMUM( + time_t) + 1]; + time_t mkt; + + tm = *t; + mkt = mktime(&tm); + if (TYPE_SIGNED(time_t)) + (void) sprintf(buf, "%ld", + (long) mkt); + else (void) sprintf(buf, "%lu", + (unsigned long) mkt); + pt = _add(buf, pt, ptlim); + } + continue; + case 'T': + pt = _fmt("%H:%M:%S", t, pt, ptlim); + continue; + case 't': + pt = _add("\t", pt, ptlim); + continue; + case 'U': + pt = _conv((t->tm_yday + 7 - t->tm_wday) / 7, + "%02d", pt, ptlim); + continue; + case 'u': + /* + ** From Arnold Robbins' strftime version 3.0: + ** "ISO 8601: Weekday as a decimal number + ** [1 (Monday) - 7]" + ** (ado, 5/24/93) + */ + pt = _conv((t->tm_wday == 0) ? 7 : t->tm_wday, + "%d", pt, ptlim); + continue; + case 'V': /* ISO 8601 week number */ + case 'G': /* ISO 8601 year (four digits) */ + case 'g': /* ISO 8601 year (two digits) */ +/* +** From Arnold Robbins' strftime version 3.0: "the week number of the +** year (the first Monday as the first day of week 1) as a decimal number +** (01-53)." +** (ado, 1993-05-24) +** +** From "http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html" by Markus Kuhn: +** "Week 01 of a year is per definition the first week which has the +** Thursday in this year, which is equivalent to the week which contains +** the fourth day of January. In other words, the first week of a new year +** is the week which has the majority of its days in the new year. Week 01 +** might also contain days from the previous year and the week before week +** 01 of a year is the last week (52 or 53) of the previous year even if +** it contains days from the new year. A week starts with Monday (day 1) +** and ends with Sunday (day 7). For example, the first week of the year +** 1997 lasts from 1996-12-30 to 1997-01-05..." +** (ado, 1996-01-02) +*/ + { + int year; + int yday; + int wday; + int w; + + year = t->tm_year + TM_YEAR_BASE; + yday = t->tm_yday; + wday = t->tm_wday; + for ( ; ; ) { + int len; + int bot; + int top; + + len = isleap(year) ? + DAYSPERLYEAR : + DAYSPERNYEAR; + /* + ** What yday (-3 ... 3) does + ** the ISO year begin on? + */ + bot = ((yday + 11 - wday) % + DAYSPERWEEK) - 3; + /* + ** What yday does the NEXT + ** ISO year begin on? + */ + top = bot - + (len % DAYSPERWEEK); + if (top < -3) + top += DAYSPERWEEK; + top += len; + if (yday >= top) { + ++year; + w = 1; + break; + } + if (yday >= bot) { + w = 1 + ((yday - bot) / + DAYSPERWEEK); + break; + } + --year; + yday += isleap(year) ? + DAYSPERLYEAR : + DAYSPERNYEAR; + } +#ifdef XPG4_1994_04_09 + if ((w == 52 + && t->tm_mon == TM_JANUARY) + || (w == 1 + && t->tm_mon == TM_DECEMBER)) + w = 53; +#endif /* defined XPG4_1994_04_09 */ + if (*format == 'V') + pt = _conv(w, "%02d", + pt, ptlim); + else if (*format == 'g') { + pt = _conv(year % 100, "%02d", + pt, ptlim); + } else pt = _conv(year, "%04d", + pt, ptlim); + } + continue; + case 'v': + /* + ** From Arnold Robbins' strftime version 3.0: + ** "date as dd-bbb-YYYY" + ** (ado, 5/24/93) + */ + pt = _fmt("%e-%b-%Y", t, pt, ptlim); + continue; + case 'W': + pt = _conv((t->tm_yday + 7 - + (t->tm_wday ? + (t->tm_wday - 1) : 6)) / 7, + "%02d", pt, ptlim); + continue; + case 'w': + pt = _conv(t->tm_wday, "%d", pt, ptlim); + continue; + case 'X': + pt = _fmt(tptr->X_fmt, t, pt, ptlim); + continue; + case 'x': + pt = _fmt(tptr->x_fmt, t, pt, ptlim); + continue; + case 'y': + pt = _conv((t->tm_year + TM_YEAR_BASE) % 100, + "%02d", pt, ptlim); + continue; + case 'Y': + pt = _conv(t->tm_year + TM_YEAR_BASE, "%04d", + pt, ptlim); + continue; + case 'Z': +#if 0 /* FIXME */ + if (t->tm_zone != NULL) + pt = _add(t->tm_zone, pt, ptlim); + else + /* FIXME: strftime("%Z") or keep "?" */ + if (t->tm_isdst == 0 || t->tm_isdst == 1) { + pt = _add(tzname[t->tm_isdst], + pt, ptlim); + } else +#endif + pt = _add("?", pt, ptlim); + continue; + case 'z': +#if 0 /* FIXME */ + { + long absoff; + if (t->tm_gmtoff >= 0) { + absoff = t->tm_gmtoff; + pt = _add("+", pt, ptlim); + } else { + absoff = -t->tm_gmtoff; + pt = _add("-", pt, ptlim); + } + pt = _conv(absoff / 3600, "%02d", + pt, ptlim); + pt = _conv((absoff % 3600) / 60, "%02d", + pt, ptlim); + }; +#endif + pt = _add("?", pt, ptlim); + continue; + case '+': + pt = _fmt(tptr->date_fmt, t, pt, ptlim); + continue; + case '%': + /* + * X311J/88-090 (4.12.3.5): if conversion char is + * undefined, behavior is undefined. Print out the + * character itself as printf(3) also does. + */ + default: + break; + } + } + if (pt == ptlim) + break; + *pt++ = *format; + } + return pt; +} + +static char * +_conv(n, format, pt, ptlim) + const int n; + const char *const format; + char *const pt; + const char *const ptlim; +{ + char buf[INT_STRLEN_MAXIMUM(int) + 1]; + + (void) sprintf(buf, format, n); + return _add(buf, pt, ptlim); +} + +static char * +_add(str, pt, ptlim) + const char *str; + char *pt; + const char *const ptlim; +{ + while (pt < ptlim && (*pt = *str++) != '\0') + ++pt; + return pt; +} + Index: ossp-pkg/tai/tai_lib.c RCS File: /v/ossp/cvs/ossp-pkg/tai/tai_lib.c,v rcsdiff -q -kk '-r1.6' '-r1.7' -u '/v/ossp/cvs/ossp-pkg/tai/tai_lib.c,v' 2>/dev/null --- tai_lib.c 2002/08/14 13:34:01 1.6 +++ tai_lib.c 2002/08/14 14:28:27 1.7 @@ -56,12 +56,40 @@ { if (tai == NULL) return TAI_ERR_ARG; - if (tai->tai_zone != NULL) - free(tai->tai_zone); free(tai); return TAI_OK; } +#if 0 +static time_t tai_utcoffset(void) +{ + time_t tL, tU; + struct tm *tmL, *tmU; + time_t offset; + + /* determine local time (UTC based) */ + tL = time(NULL); /* theoretically this could be a constant value, too */ + + /* unpack local time (local time based) */ + tmL = localtime(&tL); + + /* unpack local time (UTC based) */ + tmU = gmtime(&tL); + + /* pack UTC-based local time back into local time */ + tU = mktime(tmU); + + /* local time adjustment for Daylight Saving Time (DST) */ + if (tmL->tm_isdst) + tL += (60*60); + + /* finally calculate the UTC offset */ + offset = (tL - tU); + + return offset; +} +#endif + tai_rc_t tai_import(tai_t *tai, tai_type_t type, ...) { va_list ap; @@ -91,11 +119,11 @@ tai->tai_wday = stm->tm_wday; tai->tai_yday = stm->tm_yday; tai->tai_isdst = stm->tm_isdst; - tai->tai_gmtoff = stm->tm_gmtoff; - if (stm->tm_zone == NULL) - tai->tai_zone = strdup(""); - else - tai->tai_zone = strdup(stm->tm_zone); +#ifdef HAVE_TM_GMTOFF + tai->tai_gmtoff = stm->tm_gmtoff; /* implicitly 0 */ +#else + tai->tai_gmtoff = 0; /* explicitly 0 */ +#endif } else if (type == TAI_TYPE_STRUCTTM) { /* import from struct tm */ @@ -121,11 +149,11 @@ tai->tai_wday = stm->tm_wday; tai->tai_yday = stm->tm_yday; tai->tai_isdst = stm->tm_isdst; +#ifdef HAVE_TM_GMTOFF tai->tai_gmtoff = stm->tm_gmtoff; - if (stm->tm_zone == NULL) - tai->tai_zone = strdup(""); - else - tai->tai_zone = strdup(stm->tm_zone); +#else + tai->tai_gmtoff = 0; +#endif } else if (type == TAI_TYPE_UNIX) { /* import from time(3) FIXME */ @@ -165,8 +193,9 @@ stm->tm_wday = tai->tai_wday; stm->tm_yday = tai->tai_yday; stm->tm_isdst = tai->tai_isdst; +#ifdef HAVE_TM_GMTOFF stm->tm_gmtoff = tai->tai_gmtoff; - stm->tm_zone = tai->tai_zone; +#endif #ifdef HAVE_TIMEGM /* non-standard timegm(3) makes our life easy */ *pt = timegm(stm); @@ -191,8 +220,9 @@ stm->tm_wday = tai->tai_wday; stm->tm_yday = tai->tai_yday; stm->tm_isdst = tai->tai_isdst; +#ifdef HAVE_TM_GMTOFF stm->tm_gmtoff = tai->tai_gmtoff; - stm->tm_zone = strdup(tai->tai_zone); +#endif } else return TAI_ERR_IMP; /* FIXME */ Index: ossp-pkg/tai/tai_p.h RCS File: /v/ossp/cvs/ossp-pkg/tai/tai_p.h,v rcsdiff -q -kk '-r1.3' '-r1.4' -u '/v/ossp/cvs/ossp-pkg/tai/tai_p.h,v' 2>/dev/null --- tai_p.h 2002/05/01 18:48:34 1.3 +++ tai_p.h 2002/08/14 14:28:27 1.4 @@ -49,7 +49,6 @@ int tai_yday; /* days since January 1 [0-365] */ int tai_isdst; /* Daylight Savings Time flag */ long tai_gmtoff; /* offset from CUT in seconds */ - char *tai_zone; /* timezone abbreviation */ }; /* Index: ossp-pkg/tai/tai_parse.c RCS File: /v/ossp/cvs/ossp-pkg/tai/tai_parse.c,v rcsdiff -q -kk '-r1.1' '-r1.2' -u '/v/ossp/cvs/ossp-pkg/tai/tai_parse.c,v' 2>/dev/null --- tai_parse.c 2002/04/18 09:10:45 1.1 +++ tai_parse.c 2002/08/14 14:28:27 1.2 @@ -483,6 +483,7 @@ case 'Z': { +#if 0 /* FIXME */ const char *cp; char *zonestr; @@ -510,6 +511,7 @@ } buf += cp - buf; } +#endif } break; } Index: ossp-pkg/tai/tai_test.c RCS File: /v/ossp/cvs/ossp-pkg/tai/tai_test.c,v rcsdiff -q -kk '-r1.3' '-r1.4' -u '/v/ossp/cvs/ossp-pkg/tai/tai_test.c,v' 2>/dev/null --- tai_test.c 2002/05/29 08:32:53 1.3 +++ tai_test.c 2002/08/14 14:28:27 1.4 @@ -45,7 +45,6 @@ tai_create(&tai); tai_import(tai, TAI_TYPE_UNIX); tai_format(tai, out, sizeof(out), "%a %Y-%m-%d %H:%M:%S %z"); - fprintf(stdout, "\n<%s>\n", out); tai_destroy(tai); } TS_TEST(test_object)