Index: ossp-pkg/tai/ChangeLog RCS File: /v/ossp/cvs/ossp-pkg/tai/ChangeLog,v co -q -kk -p'1.1' '/v/ossp/cvs/ossp-pkg/tai/ChangeLog,v' | diff -u /dev/null - -L'ossp-pkg/tai/ChangeLog' 2>/dev/null --- ossp-pkg/tai/ChangeLog +++ - 2024-05-16 23:08:50.459195892 +0200 @@ -0,0 +1,4 @@ + + o Taken FreeBSD-CURRENT's strftime.c/strptime.c as of 17-Apr-2002 and created + tai_format.c out of strftime.c and tai_parse.c out of strptime.c + Index: ossp-pkg/tai/ChangeLog RCS File: /v/ossp/cvs/ossp-pkg/tai/ChangeLog,v rcsdiff -q -kk '-r1.1' '-r1.1.1.1' -u '/v/ossp/cvs/ossp-pkg/tai/ChangeLog,v' 2>/dev/null Index: ossp-pkg/tai/Makefile.in RCS File: /v/ossp/cvs/ossp-pkg/tai/Makefile.in,v co -q -kk -p'1.1.1.1' '/v/ossp/cvs/ossp-pkg/tai/Makefile.in,v' | diff -u /dev/null - -L'ossp-pkg/tai/Makefile.in' 2>/dev/null --- ossp-pkg/tai/Makefile.in +++ - 2024-05-16 23:08:50.465757978 +0200 @@ -0,0 +1,112 @@ +## +## OSSP tai - Time Handling +## Copyright (c) 2002 Ralf S. Engelschall +## Copyright (c) 2002 The OSSP Project +## Copyright (c) 2002 Cable & Wireless Deutschland +## +## This file is part of OSSP tai, a time handling library +## which can be found at http://www.ossp.org/pkg/lib/tai/. +## +## Permission to use, copy, modify, and distribute this software for +## any purpose with or without fee is hereby granted, provided that +## the above copyright notice and this permission notice appear in all +## copies. +## +## THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR +## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +## SUCH DAMAGE. +## +## Makefile.in: make(1) build procedure +## + +@SET_MAKE@ + +DESTDIR = +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +libdir = @libdir@ +includedir = @includedir@ +mandir = @mandir@ + +CC = @CC@ +CPPFLAGS = @CPPFLAGS@ +CFLAGS = @DEFS@ @CFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +RM = rm -f +RMDIR = rmdir +SHTOOL = ./shtool +LIBTOOL = ./libtool +TRUE = true + +LIB_NAME = libtai.la +LIB_OBJS = tai_lib.lo tai_format.lo tai_parse.lo tai_data.lo + +TST_NAME = tai_test +TST_OBJS = tai_test.o ts.o + +.SUFFIXES: +.SUFFIXES: .c .o .lo + +all: $(LIB_NAME) $(TST_NAME) + +.c.o: + $(CC) $(CPPFLAGS) $(CFLAGS) -c $< + +.c.lo: + @$(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(CFLAGS) -c $< + +$(LIB_NAME): $(LIB_OBJS) + @$(LIBTOOL) --mode=link $(CC) -o $(LIB_NAME) $(LIB_OBJS) -rpath $(libdir) \ + -version-info `$(SHTOOL) version -l txt -d libtool VERSION` + +$(TST_NAME): $(TST_OBJS) $(LIB_NAME) + @$(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $(TST_NAME) $(TST_OBJS) $(LIB_NAME) $(LIBS) + +check: $(TST_NAME) + @$(LIBTOOL) --mode=execute ./$(TST_NAME) + +install: + $(SHTOOL) mkdir -f -p -m 755 $(DESTDIR)$(prefix) + $(SHTOOL) mkdir -f -p -m 755 $(DESTDIR)$(bindir) + $(SHTOOL) mkdir -f -p -m 755 $(DESTDIR)$(includedir) + $(SHTOOL) mkdir -f -p -m 755 $(DESTDIR)$(libdir) + $(SHTOOL) install -c -m 755 tai-config $(DESTDIR)$(bindir)/ + $(SHTOOL) install -c -m 644 tai.h $(DESTDIR)$(includedir)/ + @$(LIBTOOL) --mode=install $(SHTOOL) install -c -m 644 libtai.la $(DESTDIR)$(libdir)/ + +uninstall: + @$(LIBTOOL) --mode=uninstall $(RM) $(DESTDIR)$(libdir)/libtai.la + -$(RM) $(DESTDIR)$(includedir)/tai.h + -$(RM) $(DESTDIR)$(bindir)/tai-config + -$(RMDIR) $(DESTDIR)$(libdir) >/dev/null 2>&1 || $(TRUE) + -$(RMDIR) $(DESTDIR)$(includedir) >/dev/null 2>&1 || $(TRUE) + -$(RMDIR) $(DESTDIR)$(bindir) >/dev/null 2>&1 || $(TRUE) + -$(RMDIR) $(DESTDIR)$(prefix) >/dev/null 2>&1 || $(TRUE) + +clean: + -$(RM) $(LIB_NAME) $(LIB_OBJS) + -$(RM) $(TST_NAME) $(TST_OBJS) + -$(RM) -r .libs >/dev/null 2>&1 || $(TRUE) + -$(RM) *.o *.lo + +distclean: clean + -$(RM) config.log config.status config.cache + -$(RM) Makefile config.h tai-config + -$(RM) libtool + +realclean: distclean + -$(RM) configure config.h.in + -$(RM) shtool + -$(RM) ltmain.sh libtool.m4 config.guess config.sub + Index: ossp-pkg/tai/tai.pod RCS File: /v/ossp/cvs/ossp-pkg/tai/tai.pod,v co -q -kk -p'1.1' '/v/ossp/cvs/ossp-pkg/tai/tai.pod,v' | diff -u /dev/null - -L'ossp-pkg/tai/tai.pod' 2>/dev/null --- ossp-pkg/tai/tai.pod +++ - 2024-05-16 23:08:50.468410301 +0200 @@ -0,0 +1,26 @@ + +=pod + +=head1 NAME + +B - Time Handling + +=head1 SYNOPSIS + +#include "tai.h" + +=head1 DESCRIPTION + +... + +=head1 SEE ALSO + +... + +=head1 AUTHORS + +The B library was implemented in April 2002 by +I for use in the OSSP project. + +=cut + Index: ossp-pkg/tai/tai.pod RCS File: /v/ossp/cvs/ossp-pkg/tai/tai.pod,v rcsdiff -q -kk '-r1.1' '-r1.1.1.1' -u '/v/ossp/cvs/ossp-pkg/tai/tai.pod,v' 2>/dev/null Index: ossp-pkg/tai/tai_lib.c RCS File: /v/ossp/cvs/ossp-pkg/tai/tai_lib.c,v co -q -kk -p'1.1.1.1' '/v/ossp/cvs/ossp-pkg/tai/tai_lib.c,v' | diff -u /dev/null - -L'ossp-pkg/tai/tai_lib.c' 2>/dev/null --- ossp-pkg/tai/tai_lib.c +++ - 2024-05-16 23:08:50.474775744 +0200 @@ -0,0 +1,252 @@ +/* +** OSSP tai - Time Handling +** Copyright (c) 2002 Ralf S. Engelschall +** Copyright (c) 2002 The OSSP Project +** Copyright (c) 2002 Cable & Wireless Deutschland +** +** This file is part of OSSP tai, a time handling library +** which can be found at http://www.ossp.org/pkg/lib/tai/. +** +** Permission to use, copy, modify, and distribute this software for +** any purpose with or without fee is hereby granted, provided that +** the above copyright notice and this permission notice appear in all +** copies. +** +** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR +** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. +** +** tm.c: API implementation +*/ + +#include +#include +#include +#include +#include + +#include "tai.h" +#include "tai_p.h" + +struct tai_st { + int tai_sec; /* seconds after the minute [0-61] */ + int tai_min; /* minutes after the hour [0-59] */ + int tai_hour; /* hours since midnight [0-23] */ + int tai_mday; /* day of the month [1-31] */ + int tai_mon; /* months since January [0-11] */ + int tai_year; /* years since 1900 */ + int tai_wday; /* days since Sunday [0-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 */ +#if 0 + int sign; + unsigned long long sec; + unsigned long nsec; + unsigned long asec; +#endif +}; + +tai_rc_t tai_create(tai_t **ptai) +{ + tai_t *tai; + tai_rc_t rv; + + if ((tai = (tai_t *)malloc(sizeof(tai_t))) == NULL) + return TAI_ERR_SYS; + if ((rv = tai_import(tai, TAI_TYPE_TIMET, 0)) != TAI_OK) { + free(tai); + return rv; + } + *ptai = tai; + return TAI_OK; +} + +tai_rc_t tai_destroy(tai_t *tai) +{ + if (tai == NULL) + return TAI_ERR_ARG; + if (tai->tai_zone != NULL) + free(tai->tai_zone); + free(tai); + return TAI_OK; +} + +tai_rc_t tai_import(tai_t *tai, tai_type_t type, ...) +{ + va_list ap; + + if (tai == NULL) + return TAI_ERR_ARG; + va_start(ap, type); + if (type == TAI_TYPE_TIMET) { + /* import from time_t */ +#ifdef HAVE_GMTIME_R + struct tm stmbuf; +#endif + struct tm *stm; + time_t t; + t = (time_t)va_arg(ap, long); +#ifdef HAVE_GMTIME_R + stm = gmtime_r(&t, &stmbuf); +#else + stm = gmtime(&t); +#endif + tai->tai_sec = stm->tm_sec; + tai->tai_min = stm->tm_min; + tai->tai_hour = stm->tm_hour; + tai->tai_mday = stm->tm_mday; + tai->tai_mon = stm->tm_mon; + tai->tai_year = stm->tm_year; + 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); + } + else if (type == TAI_TYPE_STRUCTTM) { + /* import from struct tm */ + struct tm *stm; + stm = (struct tm *)va_arg(ap, void *); +#define TM_ISRANGE(var,field,min,max) \ + (var->tm_##field >= (min) && var->tm_##field <= (max)) + if (!TM_ISRANGE(stm,sec,0,61) || + !TM_ISRANGE(stm,min,0,59) || + !TM_ISRANGE(stm,hour,0,23) || + !TM_ISRANGE(stm,mday,1,31) || + !TM_ISRANGE(stm,mon,0,11) || + !TM_ISRANGE(stm,wday,0,6) || + !TM_ISRANGE(stm,yday,0,365) || + !TM_ISRANGE(stm,isdst,0,1)) + return TAI_ERR_ARG; + tai->tai_sec = stm->tm_sec; + tai->tai_min = stm->tm_min; + tai->tai_hour = stm->tm_hour; + tai->tai_mday = stm->tm_mday; + tai->tai_mon = stm->tm_mon; + tai->tai_year = stm->tm_year; + 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); + } + else + return TAI_ERR_IMP; /* FIXME */ + va_end(ap); + return TAI_OK; +} + +tai_rc_t tai_export(tai_t *tai, tai_type_t type, ...) +{ + va_list ap; + + if (tai == NULL) + return TAI_ERR_ARG; + va_start(ap, type); + if (type == TAI_TYPE_TIMET) { + time_t *pt; + struct tm stmbuf; + struct tm *stm; +#ifndef HAVE_TIMEGM + time_t t; +#endif + pt = (time_t *)va_arg(ap, void *); + stm = &stmbuf; + stm->tm_sec = tai->tai_sec; + stm->tm_min = tai->tai_min; + stm->tm_hour = tai->tai_hour; + stm->tm_mday = tai->tai_mday; + stm->tm_mon = tai->tai_mon; + stm->tm_year = tai->tai_year; + stm->tm_wday = tai->tai_wday; + stm->tm_yday = tai->tai_yday; + stm->tm_isdst = tai->tai_isdst; + stm->tm_gmtoff = tai->tai_gmtoff; + stm->tm_zone = tai->tai_zone; +#ifdef HAVE_TIMEGM + /* non-standard timegm(3) makes our life easy */ + *pt = timegm(stm); +#else + /* standard mktime(3) calculated relative to local timezone, + so we have to post-adjust result */ + *pt = mktime(stm); + t = 12*60*60*2; /* max offset of 12 hours plus safety */ + *pt += (mktime(localtime(&t)) - mktime(gmtime(&t))); +#endif + } + else if (type == TAI_TYPE_STRUCTTM) { + struct tm *stm; + + stm = (struct tm *)va_arg(ap, void *); + stm->tm_sec = tai->tai_sec; + stm->tm_min = tai->tai_min; + stm->tm_hour = tai->tai_hour; + stm->tm_mday = tai->tai_mday; + stm->tm_mon = tai->tai_mon; + stm->tm_year = tai->tai_year; + stm->tm_wday = tai->tai_wday; + stm->tm_yday = tai->tai_yday; + stm->tm_isdst = tai->tai_isdst; + stm->tm_gmtoff = tai->tai_gmtoff; + stm->tm_zone = strdup(tai->tai_zone); + } + else + return TAI_ERR_IMP; /* FIXME */ + va_end(ap); + return TAI_OK; +} + +tai_rc_t tai_format(tai_t *tai, char *buf_ptr, size_t buf_len, const char *fmt) +{ + struct tm stm; + tai_rc_t rv; + + if (tai == NULL || buf_ptr == NULL || buf_len == 0 || fmt == NULL) + return TAI_ERR_ARG; + if ((rv = tai_export(tai, TAI_TYPE_STRUCTTM, &stm)) != TAI_OK) + return rv; + if (tai_format_int(buf_ptr, buf_len, fmt, &stm) == 0) + return TAI_ERR_FMT; + return TAI_OK; +} + +tai_rc_t tai_parse(tai_t *tai, const char *buf_ptr, size_t buf_len, const char *fmt) +{ + struct tm stm; + char *cp; + char *cp2; + tai_rc_t rv; + + if (tai == NULL || buf_ptr == NULL || buf_len == 0 || fmt == NULL) + return TAI_ERR_ARG; + if ((cp = malloc(buf_len+1)) == NULL) + return TAI_ERR_SYS; + memmove(cp, buf_ptr, buf_len); + cp[buf_len] = '\0'; + memset(&stm, 0, sizeof(struct tm)); + cp2 = tai_parse_int(cp, fmt, &stm); + free(cp); + if (cp2 == NULL) + return TAI_ERR_PRS; + if ((rv = tai_import(tai, TAI_TYPE_STRUCTTM, &stm)) != TAI_OK) + return rv; + return TAI_OK; +} + Index: ossp-pkg/tai/tai_p.h RCS File: /v/ossp/cvs/ossp-pkg/tai/tai_p.h,v co -q -kk -p'1.1.1.1' '/v/ossp/cvs/ossp-pkg/tai/tai_p.h,v' | diff -u /dev/null - -L'ossp-pkg/tai/tai_p.h' 2>/dev/null --- ossp-pkg/tai/tai_p.h +++ - 2024-05-16 23:08:50.477492113 +0200 @@ -0,0 +1,63 @@ +/*- + * Copyright (c) 1997-2002 FreeBSD Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libc/stdtime/timelocal.h,v 1.11 2002/01/24 15:07:44 phantom Exp $ + */ + +#ifndef _TIMELOCAL_H_ +#define _TIMELOCAL_H_ + +#include + +#include "config.h" + +/* + * Private header file for the strftime and strptime localization + * stuff. + */ +typedef struct { + const char *mon[12]; + const char *month[12]; + const char *wday[7]; + const char *weekday[7]; + const char *X_fmt; + const char *x_fmt; + const char *c_fmt; + const char *am; + const char *pm; + const char *date_fmt; + const char *alt_month[12]; + const char *md_order; + const char *ampm_fmt; +} tai_locale_t; + +extern const tai_locale_t tai_locale; + +#define TM_YEAR_BASE 1900 + +size_t tai_format_int(char *const s, const size_t maxsize, const char *const format, const struct tm *const t); +char *tai_parse_int (const char *buf, const char *fmt, struct tm *tm); + +#endif /* !_TIMELOCAL_H_ */ Index: ossp-pkg/tai/tai_parse.c RCS File: /v/ossp/cvs/ossp-pkg/tai/tai_parse.c,v co -q -kk -p'1.1' '/v/ossp/cvs/ossp-pkg/tai/tai_parse.c,v' | diff -u /dev/null - -L'ossp-pkg/tai/tai_parse.c' 2>/dev/null --- ossp-pkg/tai/tai_parse.c +++ - 2024-05-16 23:08:50.480120563 +0200 @@ -0,0 +1,543 @@ +/* + * Powerdog Industries kindly requests feedback from anyone modifying + * this function: + * + * Date: Thu, 05 Jun 1997 23:17:17 -0400 + * From: Kevin Ruddy + * To: James FitzGibbon + * Subject: Re: Use of your strptime(3) code (fwd) + * + * The reason for the "no mod" clause was so that modifications would + * come back and we could integrate them and reissue so that a wider + * audience could use it (thereby spreading the wealth). This has + * made it possible to get strptime to work on many operating systems. + * I'm not sure why that's "plain unacceptable" to the FreeBSD team. + * + * Anyway, you can change it to "with or without modification" as + * you see fit. Enjoy. + * + * Kevin Ruddy + * Powerdog Industries, Inc. + */ +/* + * Copyright (c) 1994 Powerdog Industries. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgement: + * This product includes software developed by Powerdog Industries. + * 4. The name of Powerdog Industries may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY POWERDOG INDUSTRIES ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE POWERDOG INDUSTRIES BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if 0 +"@(#) Copyright (c) 1994 Powerdog Industries. All rights reserved."; +static char sccsid[] = "@(#)strptime.c 0.1 (Powerdog) 94/03/27"; +__FBSDID("$FreeBSD: src/lib/libc/stdtime/strptime.c,v 1.27 2002/03/22 21:53:13 obrien Exp $"); +#endif + +#include +#include +#include +#include +#include + +#include "tai.h" +#include "tai_p.h" + +#if 0 /* FIXME */ +static pthread_mutex_t gotgmt_mutex = PTHREAD_MUTEX_INITIALIZER; +static int got_GMT; +#endif + +#define asizeof(a) (sizeof (a) / sizeof ((a)[0])) + +char * +tai_parse_int(const char *buf, const char *fmt, struct tm *tm) +{ + char c; + const char *ptr; + int i, len = 0; + int Ealternative, Oalternative; + const tai_locale_t *tptr = &tai_locale; + + ptr = fmt; + while (*ptr != 0) { + if (*buf == 0) + break; + + c = *ptr++; + + if (c != '%') { + if (isspace((unsigned char)c)) + while (*buf != 0 && isspace((unsigned char)*buf)) + buf++; + else if (c != *buf++) + return 0; + continue; + } + + Ealternative = 0; + Oalternative = 0; +label: + c = *ptr++; + switch (c) { + case 0: + case '%': + if (*buf++ != '%') + return 0; + break; + + case '+': + buf = tai_parse_int(buf, tptr->date_fmt, tm); + if (buf == 0) + return 0; + break; + + case 'C': + if (!isdigit((unsigned char)*buf)) + return 0; + + /* XXX This will break for 3-digit centuries. */ + len = 2; + for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + i *= 10; + i += *buf - '0'; + len--; + } + if (i < 19) + return 0; + + tm->tm_year = i * 100 - 1900; + break; + + case 'c': + buf = tai_parse_int(buf, tptr->c_fmt, tm); + if (buf == 0) + return 0; + break; + + case 'D': + buf = tai_parse_int(buf, "%m/%d/%y", tm); + if (buf == 0) + return 0; + break; + + case 'E': + if (Ealternative || Oalternative) + break; + Ealternative++; + goto label; + + case 'O': + if (Ealternative || Oalternative) + break; + Oalternative++; + goto label; + + case 'F': + buf = tai_parse_int(buf, "%Y-%m-%d", tm); + if (buf == 0) + return 0; + break; + + case 'R': + buf = tai_parse_int(buf, "%H:%M", tm); + if (buf == 0) + return 0; + break; + + case 'r': + buf = tai_parse_int(buf, tptr->ampm_fmt, tm); + if (buf == 0) + return 0; + break; + + case 'T': + buf = tai_parse_int(buf, "%H:%M:%S", tm); + if (buf == 0) + return 0; + break; + + case 'X': + buf = tai_parse_int(buf, tptr->X_fmt, tm); + if (buf == 0) + return 0; + break; + + case 'x': + buf = tai_parse_int(buf, tptr->x_fmt, tm); + if (buf == 0) + return 0; + break; + + case 'j': + if (!isdigit((unsigned char)*buf)) + return 0; + + len = 3; + for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + i *= 10; + i += *buf - '0'; + len--; + } + if (i < 1 || i > 366) + return 0; + + tm->tm_yday = i - 1; + break; + + case 'M': + case 'S': + if (*buf == 0 || isspace((unsigned char)*buf)) + break; + + if (!isdigit((unsigned char)*buf)) + return 0; + + len = 2; + for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + i *= 10; + i += *buf - '0'; + len--; + } + + if (c == 'M') { + if (i > 59) + return 0; + tm->tm_min = i; + } else { + if (i > 60) + return 0; + tm->tm_sec = i; + } + + if (*buf != 0 && isspace((unsigned char)*buf)) + while (*ptr != 0 && !isspace((unsigned char)*ptr)) + ptr++; + break; + + case 'H': + case 'I': + case 'k': + case 'l': + /* + * Of these, %l is the only specifier explicitly + * documented as not being zero-padded. However, + * there is no harm in allowing zero-padding. + * + * XXX The %l specifier may gobble one too many + * digits if used incorrectly. + */ + if (!isdigit((unsigned char)*buf)) + return 0; + + len = 2; + for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + i *= 10; + i += *buf - '0'; + len--; + } + if (c == 'H' || c == 'k') { + if (i > 23) + return 0; + } else if (i > 12) + return 0; + + tm->tm_hour = i; + + if (*buf != 0 && isspace((unsigned char)*buf)) + while (*ptr != 0 && !isspace((unsigned char)*ptr)) + ptr++; + break; + + case 'p': + /* + * XXX This is bogus if parsed before hour-related + * specifiers. + */ + len = strlen(tptr->am); + if (strncasecmp(buf, tptr->am, len) == 0) { + if (tm->tm_hour > 12) + return 0; + if (tm->tm_hour == 12) + tm->tm_hour = 0; + buf += len; + break; + } + + len = strlen(tptr->pm); + if (strncasecmp(buf, tptr->pm, len) == 0) { + if (tm->tm_hour > 12) + return 0; + if (tm->tm_hour != 12) + tm->tm_hour += 12; + buf += len; + break; + } + + return 0; + + case 'A': + case 'a': + for (i = 0; i < asizeof(tptr->weekday); i++) { + len = strlen(tptr->weekday[i]); + if (strncasecmp(buf, tptr->weekday[i], + len) == 0) + break; + len = strlen(tptr->wday[i]); + if (strncasecmp(buf, tptr->wday[i], + len) == 0) + break; + } + if (i == asizeof(tptr->weekday)) + return 0; + + tm->tm_wday = i; + buf += len; + break; + + case 'U': + case 'W': + /* + * XXX This is bogus, as we can not assume any valid + * information present in the tm structure at this + * point to calculate a real value, so just check the + * range for now. + */ + if (!isdigit((unsigned char)*buf)) + return 0; + + len = 2; + for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + i *= 10; + i += *buf - '0'; + len--; + } + if (i > 53) + return 0; + + if (*buf != 0 && isspace((unsigned char)*buf)) + while (*ptr != 0 && !isspace((unsigned char)*ptr)) + ptr++; + break; + + case 'w': + if (!isdigit((unsigned char)*buf)) + return 0; + + i = *buf - '0'; + if (i > 6) + return 0; + + tm->tm_wday = i; + + if (*buf != 0 && isspace((unsigned char)*buf)) + while (*ptr != 0 && !isspace((unsigned char)*ptr)) + ptr++; + break; + + case 'd': + case 'e': + /* + * The %e specifier is explicitly documented as not + * being zero-padded but there is no harm in allowing + * such padding. + * + * XXX The %e specifier may gobble one too many + * digits if used incorrectly. + */ + if (!isdigit((unsigned char)*buf)) + return 0; + + len = 2; + for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + i *= 10; + i += *buf - '0'; + len--; + } + if (i > 31) + return 0; + + tm->tm_mday = i; + + if (*buf != 0 && isspace((unsigned char)*buf)) + while (*ptr != 0 && !isspace((unsigned char)*ptr)) + ptr++; + break; + + case 'B': + case 'b': + case 'h': + for (i = 0; i < asizeof(tptr->month); i++) { + if (Oalternative) { + if (c == 'B') { + len = strlen(tptr->alt_month[i]); + if (strncasecmp(buf, + tptr->alt_month[i], + len) == 0) + break; + } + } else { + len = strlen(tptr->month[i]); + if (strncasecmp(buf, tptr->month[i], + len) == 0) + break; + len = strlen(tptr->mon[i]); + if (strncasecmp(buf, tptr->mon[i], + len) == 0) + break; + } + } + if (i == asizeof(tptr->month)) + return 0; + + tm->tm_mon = i; + buf += len; + break; + + case 'm': + if (!isdigit((unsigned char)*buf)) + return 0; + + len = 2; + for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + i *= 10; + i += *buf - '0'; + len--; + } + if (i < 1 || i > 12) + return 0; + + tm->tm_mon = i - 1; + + if (*buf != 0 && isspace((unsigned char)*buf)) + while (*ptr != 0 && !isspace((unsigned char)*ptr)) + ptr++; + break; + + case 's': + { + char *cp; + time_t t; + + t = strtol(buf, &cp, 10); + if (t == LONG_MAX) + return 0; + buf = cp; +#if 0 /* FIXME */ + gmtime_r(&t, tm); + got_GMT = 1; +#endif + } + break; + + case 'Y': + case 'y': + if (*buf == 0 || isspace((unsigned char)*buf)) + break; + + if (!isdigit((unsigned char)*buf)) + return 0; + + len = (c == 'Y') ? 4 : 2; + for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + i *= 10; + i += *buf - '0'; + len--; + } + if (c == 'Y') + i -= 1900; + if (c == 'y' && i < 69) + i += 100; + if (i < 0) + return 0; + + tm->tm_year = i; + + if (*buf != 0 && isspace((unsigned char)*buf)) + while (*ptr != 0 && !isspace((unsigned char)*ptr)) + ptr++; + break; + + case 'Z': + { + const char *cp; + char *zonestr; + + for (cp = buf; *cp && isupper((unsigned char)*cp); ++cp) {/*empty*/} + if (cp - buf) { + zonestr = alloca(cp - buf + 1); + strncpy(zonestr, buf, cp - buf); + zonestr[cp - buf] = '\0'; +#if 0 /* FIXME */ + tzset(); +#endif + if (0 == strcmp(zonestr, "GMT")) { +#if 0 /* FIXME */ + got_GMT = 1 +#endif + ; +#if 0 /* FIXME */ + } else if (0 == strcmp(zonestr, tzname[0])) { + tm->tm_isdst = 0; + } else if (0 == strcmp(zonestr, tzname[1])) { + tm->tm_isdst = 1; +#endif + } else { + return 0; + } + buf += cp - buf; + } + } + break; + } + } + return (char *)buf; +} + +#if 0 /* FIXME remove? */ +char * +strptime(const char *buf, const char *fmt, struct tm *tm) +{ + char *ret; + + if (__isthreaded) + _pthread_mutex_lock(&gotgmt_mutex); + + got_GMT = 0; + ret = _strptime(buf, fmt, tm); + if (ret && got_GMT) { + time_t t = timegm(tm); + localtime_r(&t, tm); + got_GMT = 0; + } + + if (__isthreaded) + _pthread_mutex_unlock(&gotgmt_mutex); + + return ret; +} +#endif + 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.1.1.1' -u '/v/ossp/cvs/ossp-pkg/tai/tai_parse.c,v' 2>/dev/null Index: ossp-pkg/tai/tai_test.c RCS File: /v/ossp/cvs/ossp-pkg/tai/tai_test.c,v co -q -kk -p'1.1.1.1' '/v/ossp/cvs/ossp-pkg/tai/tai_test.c,v' | diff -u /dev/null - -L'ossp-pkg/tai/tai_test.c' 2>/dev/null --- ossp-pkg/tai/tai_test.c +++ - 2024-05-16 23:08:50.487146534 +0200 @@ -0,0 +1,138 @@ +/* +** OSSP tai - Time Handling +** Copyright (c) 2002 Ralf S. Engelschall +** Copyright (c) 2002 The OSSP Project +** Copyright (c) 2002 Cable & Wireless Deutschland +** +** This file is part of OSSP tai, a time handling library +** which can be found at http://www.ossp.org/pkg/lib/tai/. +** +** Permission to use, copy, modify, and distribute this software for +** any purpose with or without fee is hereby granted, provided that +** the above copyright notice and this permission notice appear in all +** copies. +** +** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR +** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. +** +** tai_test.c: test suite +*/ + +#include +#include +#include +#include + +#include "ts.h" +#include "tai.h" + +TS_TEST(test_object) +{ + tai_t *tm; + tai_rc_t rv; + + ts_test_check(TS_CTX, "object creation"); + if ((rv = tai_create(&tm)) != TAI_OK) { + ts_test_fail(TS_CTX, "tai_create: rv=%d", rv); + return; + } + + ts_test_check(TS_CTX, "object destruction"); + if ((rv = tai_destroy(tm)) != TAI_OK) + ts_test_fail(TS_CTX, "tai_destroy: rv=%d", rv); +} + +TS_TEST(test_importexport) +{ + tai_t *tm; + tai_rc_t rv; + time_t t; + time_t t2; + + ts_test_check(TS_CTX, "time import"); + tai_create(&tm); + if ((rv = tai_import(tm, TAI_TYPE_TIMET, 0)) != TAI_OK) + ts_test_fail(TS_CTX, "tai_import: rv=%d", rv); + if ((rv = tai_export(tm, TAI_TYPE_TIMET, &t)) != TAI_OK) + ts_test_fail(TS_CTX, "tai_export: rv=%d", rv); + if (t != 0) + ts_test_fail(TS_CTX, "unexpected time %d (!= 0)", t); + t = time(NULL); + if ((rv = tai_import(tm, TAI_TYPE_TIMET, t)) != TAI_OK) + ts_test_fail(TS_CTX, "tai_import: rv=%d", rv); + if ((rv = tai_export(tm, TAI_TYPE_TIMET, &t2)) != TAI_OK) + ts_test_fail(TS_CTX, "tai_export: rv=%d", rv); + if (t != t2) + ts_test_fail(TS_CTX, "unexpected time %d (!= %d)", t2, t); + tai_destroy(tm); +} + +TS_TEST(test_parsing) +{ + tai_t *tm; + tai_rc_t rv; + char out[32]; + int i; + struct { + char *date; + char *fmt; + } table[] = { + { "2000-02-22", "%Y-%m-%d" }, + { "22-02-2000", "%d-%m-%Y" }, + { "22-Feb-2000", "%d-%b-%Y" }, + { "29-Feb-2000", "%d-%b-%Y" }, + { "31-Feb-2000", "%d-%b-%Y" }, + { NULL, NULL } + }; + + ts_test_check(TS_CTX, "time parsing"); + tai_create(&tm); + for (i = 0; table[i].date != NULL; i++) { + ts_test_log(TS_CTX, "date=%s, fmt=%s", table[i].date, table[i].fmt); + if ((rv = tai_parse(tm, table[i].date, strlen(table[i].date), table[i].fmt)) != TAI_OK) + ts_test_fail(TS_CTX, "#%d: tai_parse(\"%s\"): rv=%d", i, table[i].date, rv); + else { + if ((rv = tai_format(tm, out, sizeof(out), table[i].fmt)) != TAI_OK) + ts_test_fail(TS_CTX, "#%d: tai_format(\"%s\"): rv=%d", i, table[i].date, rv); + if (strcmp(table[i].date, out) != 0) + ts_test_fail(TS_CTX, "#%d: output \"%s\", expected \"%s\" (input)", i, out, table[i].date); + } + } + tai_destroy(tm); +} + +TS_TEST(test_formatting) +{ + tai_t *tm; + + ts_test_check(TS_CTX, "time formatting"); + tai_create(&tm); + /* FIXME */ + tai_destroy(tm); +} + +int main(int argc, char *argv[]) +{ + ts_suite_t *ts; + int n; + + ts = ts_suite_new("OSSP tai (Time Handling)"); + ts_suite_test(ts, test_object, "object handling"); + ts_suite_test(ts, test_importexport, "time import/export"); + ts_suite_test(ts, test_parsing, "time parsing"); + ts_suite_test(ts, test_formatting, "time formatting"); + n = ts_suite_run(ts); + ts_suite_free(ts); + return n; +} +