OSSP CVS Repository

ossp - Check-in [3789]
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [Patchset]  [Tagging/Branching

Check-in Number: 3789
Date: 2002-Apr-18 11:10:47 (local)
2002-Apr-18 09:10:47 (UTC)
User:rse
Branch:
Comment: Import first cut for OSSP tai
Tickets:
Inspections:
Files:
ossp-pkg/tai/tai-config.in      1.1 -> 1.1.1.1    
ossp-pkg/tai/tai-config.in      added-> 1.1
ossp-pkg/tai/tai_format.c      1.1 -> 1.1.1.1    
ossp-pkg/tai/tai_format.c      added-> 1.1
ossp-pkg/tai/ts.c      1.1 -> 1.1.1.1    
ossp-pkg/tai/ts.c      added-> 1.1

ossp-pkg/tai/tai-config.in -> 1.1

*** /dev/null    Sat Nov 23 01:13:20 2024
--- -    Sat Nov 23 01:13:32 2024
***************
*** 0 ****
--- 1,145 ----
+ #!/bin/sh
+ ##
+ ##  OSSP tai - Time Handling
+ ##  Copyright (c) 2002 Ralf S. Engelschall <rse@engelschall.com>
+ ##  Copyright (c) 2002 The OSSP Project <http://www.ossp.org/>
+ ##  Copyright (c) 2002 Cable & Wireless Deutschland <http://www.cw.com/de/>
+ ##
+ ##  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-config.in: OSSP tm build utility
+ ##
+ 
+ DIFS='         
+ '
+ 
+ prefix="@prefix@"
+ exec_prefix="@exec_prefix@"
+ 
+ tai_prefix="$prefix"
+ tai_exec_prefix="$exec_prefix"
+ tai_bindir="@bindir@"
+ tai_libdir="@libdir@"
+ tai_includedir="@includedir@"
+ tai_mandir="@mandir@"
+ tai_datadir="@datadir@"
+ tai_acdir="@datadir@/aclocal"
+ tai_cflags="@CFLAGS@"
+ tai_ldflags="@LDFLAGS@"
+ tai_libs="@LIBS@"
+ tai_version="@TM_VERSION_STR@"
+ 
+ help=no
+ version=no
+ 
+ usage="tm-config"
+ usage="$usage [--help] [--version] [--all]"
+ usage="$usage [--prefix] [--exec-prefix] [--bindir] [--libdir] [--includedir] [--mandir] [--datadir] [--acdir]"
+ usage="$usage [--cflags] [--ldflags] [--libs]"
+ if [ $# -eq 0 ]; then
+     echo "tm-config:Error: Invalid option" 1>&2
+     echo "tm-config:Usage: $usage" 1>&2
+     exit 1
+ fi
+ output=''
+ output_extra=''
+ all=no
+ prev=''
+ OIFS="$IFS" IFS="$DIFS"
+ for option
+ do
+     if [ ".$prev" != . ]; then
+         eval "$prev=\$option"
+         prev=''
+         continue
+     fi
+     case "$option" in
+         -*=*) optarg=`echo "$option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+            *) optarg='' ;;
+     esac
+     case "$option" in
+         --help|-h)
+             echo "Usage: $usage"
+             exit 0
+             ;;
+         --version|-v)
+             echo "OSSP tm $tai_version"
+             exit 0
+             ;;
+         --all)
+             all=yes
+             ;;
+         --prefix)
+             output="$output $tai_prefix"
+             ;;
+         --exec-prefix)
+             output="$output $tai_exec_prefix"
+             ;;
+         --bindir)
+             output="$output $tai_bindir"
+             ;;
+         --libdir)
+             output="$output $tai_libdir"
+             ;;
+         --includedir)
+             output="$output $tai_includedir"
+             ;;
+         --mandir)
+             output="$output $tai_mandir"
+             ;;
+         --datadir)
+             output="$output $tai_datadir"
+             ;;
+         --acdir)
+             output="$output $tai_acdir"
+             ;;
+         --cflags)
+             output="$output -I$tai_includedir"
+             output_extra="$output_extra $tai_cflags"
+             ;;
+         --ldflags)
+             output="$output -L$tai_libdir"
+             output_extra="$output_extra $tai_ldflags"
+             ;;
+         --libs)
+             output="$output -ltai"
+             output_extra="$output_extra $tai_libs"
+             ;;
+         * )
+             echo "tai-config:Error: Invalid option" 1>&2
+             echo "tai-config:Usage: $usage" 1>&2
+             exit 1;
+             ;;
+     esac
+ done
+ IFS="$OIFS"
+ if [ ".$prev" != . ]; then
+     echo "tai-config:Error: missing argument to --`echo $prev | sed 's/_/-/g'`" 1>&2
+     exit 1
+ fi
+ if [ ".$output" != . ]; then
+     if [ ".$all" = .yes ]; then
+         output="$output $output_extra"
+     fi
+     echo $output
+ fi
+ 


ossp-pkg/tai/tai-config.in 1.1 -> 1.1.1.1



ossp-pkg/tai/tai_format.c -> 1.1

*** /dev/null    Sat Nov 23 01:13:20 2024
--- -    Sat Nov 23 01:13:32 2024
***************
*** 0 ****
--- 1,454 ----
+ /*
+  * 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 <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <fcntl.h>
+ #include <sys/stat.h>
+ 
+ #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 (t->tm_zone != NULL)
+                                        pt = _add(t->tm_zone, pt, ptlim);
+                                else
+ #if 0 /* 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':
+                                {
+                                        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);
+                                };
+                                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;
+ }
+ 


ossp-pkg/tai/tai_format.c 1.1 -> 1.1.1.1



ossp-pkg/tai/ts.c -> 1.1

*** /dev/null    Sat Nov 23 01:13:20 2024
--- -    Sat Nov 23 01:13:32 2024
***************
*** 0 ****
--- 1,468 ----
+ /*
+ **  TS - OSSP Test Suite Library
+ **  Copyright (c) 2001-2002 Ralf S. Engelschall <rse@engelschall.com>
+ **  Copyright (c) 2001-2002 The OSSP Project <http://www.ossp.org/>
+ **  Copyright (c) 2001-2002 Cable & Wireless Deutschland <http://www.cw.com/de/>
+ **
+ **  This file is part of OSSP TS, a small test suite library which
+ **  can be found at http://www.ossp.org/pkg/ts/.
+ **
+ **  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.
+ **
+ **  ts.c: test suite library
+ */
+ 
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <stdarg.h>
+ 
+ #include "config.h"
+ #if defined(HAVE_DMALLOC_H) && defined(WITH_DMALLOC)
+ #include "dmalloc.h"
+ #endif
+ 
+ #include "ts.h"
+ 
+ /* embedded ring data structure library */
+ #define RING_ENTRY(elem) \
+     struct { elem *next; elem *prev; }
+ #define RING_HEAD(elem) \
+     struct { elem *next; elem *prev; }
+ #define RING_SENTINEL(hp, elem, link) \
+     (elem *)((char *)(hp) - ((size_t)(&((elem *)0)->link)))
+ #define RING_FIRST(hp) \
+     (hp)->next
+ #define RING_LAST(hp) \
+     (hp)->prev
+ #define RING_NEXT(ep, link) \
+     (ep)->link.next
+ #define RING_PREV(ep, link) \
+     (ep)->link.prev
+ #define RING_INIT(hp, elem, link) \
+     do { RING_FIRST((hp)) = RING_SENTINEL((hp), elem, link); \
+          RING_LAST((hp))  = RING_SENTINEL((hp), elem, link); } while (0)
+ #define RING_EMPTY(hp, elem, link) \
+     (RING_FIRST((hp)) == RING_SENTINEL((hp), elem, link))
+ #define RING_ELEM_INIT(ep, link) \
+     do { RING_NEXT((ep), link) = (ep); \
+          RING_PREV((ep), link) = (ep); } while (0)
+ #define RING_SPLICE_BEFORE(lep, ep1, epN, link) \
+     do { RING_NEXT((epN), link) = (lep); \
+          RING_PREV((ep1), link) = RING_PREV((lep), link); \
+          RING_NEXT(RING_PREV((lep), link), link) = (ep1); \
+          RING_PREV((lep), link) = (epN); } while (0)
+ #define RING_SPLICE_TAIL(hp, ep1, epN, elem, link) \
+     RING_SPLICE_BEFORE(RING_SENTINEL((hp), elem, link), (ep1), (epN), link)
+ #define RING_INSERT_TAIL(hp, nep, elem, link) \
+     RING_SPLICE_TAIL((hp), (nep), (nep), elem, link)
+ #define RING_FOREACH(ep, hp, elem, link) \
+     for ((ep)  = RING_FIRST((hp)); \
+          (ep) != RING_SENTINEL((hp), elem, link); \
+          (ep)  = RING_NEXT((ep), link))
+ 
+ /* test suite test log */
+ struct tstl_st;
+ typedef struct tstl_st tstl_t;
+ struct tstl_st {
+     RING_ENTRY(tstl_t) next;
+     char              *text;
+     const char        *file;
+     int                line;
+ };
+ 
+ /* test suite test check */
+ struct tstc_st;
+ typedef struct tstc_st tstc_t;
+ struct tstc_st {
+     RING_ENTRY(tstc_t) next;
+     char              *title;
+     int                failed;
+     const char        *file;
+     int                line;
+     RING_HEAD(tstl_t)  logs;
+ };
+ 
+ /* test suite test */
+ struct ts_test_st {
+     RING_ENTRY(ts_test_t)  next;
+     char              *title;
+     ts_test_cb_t         func;
+     const char        *file;
+     int                line;
+     RING_HEAD(tstc_t)  checks;
+ };
+ 
+ /* test suite */
+ struct ts_suite_st {
+     char              *title;
+     RING_HEAD(ts_test_t)   tests;
+ };
+ 
+ /* minimal output-independent vprintf(3) variant which supports %{c,s,d,%} only */
+ static int ts_suite_mvxprintf(char *buffer, size_t bufsize, const char *format, va_list ap)
+ {
+     /* sufficient integer buffer: <available-bits> x log_10(2) + safety */
+     char ibuf[((sizeof(int)*8)/3)+10]; 
+     char *cp;
+     char c;
+     int d;
+     int n;
+     int bytes;
+ 
+     if (format == NULL || ap == NULL)
+         return -1;
+     bytes = 0;
+     while (*format != '\0') {
+         if (*format == '%') {
+             c = *(format+1);
+             if (c == '%') {
+                 /* expand "%%" */
+                 cp = &c;
+                 n = sizeof(char);
+             }
+             else if (c == 'c') {
+                 /* expand "%c" */
+                 c = (char)va_arg(ap, int);
+                 cp = &c;
+                 n = sizeof(char);
+             }
+             else if (c == 's') {
+                 /* expand "%s" */
+                 if ((cp = (char *)va_arg(ap, char *)) == NULL)
+                     cp = "(null)";
+                 n = strlen(cp);
+             }
+             else if (c == 'd') {
+                 /* expand "%d" */
+                 d = (int)va_arg(ap, int);
+ #ifdef HAVE_SNPRINTF
+                 snprintf(ibuf, sizeof(ibuf), "%d", d); /* explicitly secure */
+ #else
+                 sprintf(ibuf, "%d", d);                /* implicitly secure */
+ #endif
+                 cp = ibuf;
+                 n = strlen(cp);
+             }
+             else {
+                 /* any other "%X" */
+                 cp = (char *)format;
+                 n  = 2;
+             }
+             format += 2;
+         }
+         else {
+             /* plain text */
+             cp = (char *)format;
+             if ((format = strchr(cp, '%')) == NULL)
+                 format = strchr(cp, '\0');
+             n = format - cp;
+         }
+         /* perform output operation */
+         if (buffer != NULL) {
+             if (n > bufsize)
+                 return -1;
+             memcpy(buffer, cp, n);
+             buffer  += n;
+             bufsize -= n;
+         }
+         bytes += n;
+     }
+     /* nul-terminate output */
+     if (buffer != NULL) {
+         if (bufsize == 0)
+             return -1;
+         *buffer = '\0';
+     }
+     return bytes;
+ }
+ 
+ /* minimal vasprintf(3) variant which supports %{c,s,d} only */
+ static char *ts_suite_mvasprintf(const char *format, va_list ap)
+ {
+     char *buffer;
+     int n;
+     va_list ap2;
+ 
+     if (format == NULL || ap == NULL)
+         return NULL;
+     ap2 = ap;
+     if ((n = ts_suite_mvxprintf(NULL, 0, format, ap)) == -1)
+         return NULL;
+     if ((buffer = (char *)malloc(n+1)) == NULL)
+         return NULL;
+     ts_suite_mvxprintf(buffer, n+1, format, ap2);
+     return buffer;
+ }
+ 
+ /* minimal asprintf(3) variant which supports %{c,s,d} only */
+ static char *ts_suite_masprintf(const char *format, ...)
+ {
+     va_list ap;
+     char *cp;
+ 
+     va_start(ap, format);
+     cp = ts_suite_mvasprintf(format, ap);
+     va_end(ap);
+     return cp;
+ }
+ 
+ /* create test suite */
+ ts_suite_t *ts_suite_new(const char *fmt, ...)
+ {
+     ts_suite_t *ts;
+     va_list ap;
+ 
+     if ((ts = (ts_suite_t *)malloc(sizeof(ts_suite_t))) == NULL)
+         return NULL;
+     va_start(ap, fmt);
+     ts->title = ts_suite_mvasprintf(fmt, ap);
+     RING_INIT(&ts->tests, ts_test_t, next);
+     va_end(ap);
+     return ts;
+ }
+ 
+ /* add test case to test suite */
+ void ts_suite_test(ts_suite_t *ts, ts_test_cb_t func, const char *fmt, ...)
+ {
+     ts_test_t *tst;
+     va_list ap;
+ 
+     if (ts == NULL || func == NULL || fmt == NULL)
+         return;
+     if ((tst = (ts_test_t *)malloc(sizeof(ts_test_t))) == NULL)
+         return;
+     RING_ELEM_INIT(tst, next);
+     va_start(ap, fmt);
+     tst->title = ts_suite_mvasprintf(fmt, ap);
+     va_end(ap);
+     tst->func = func;
+     tst->file = NULL;
+     tst->line = 0;
+     RING_INIT(&tst->checks, tstc_t, next);
+     RING_INSERT_TAIL(&ts->tests, tst, ts_test_t, next);
+     return;
+ }
+ 
+ /* run test suite */
+ int ts_suite_run(ts_suite_t *ts)
+ {
+     ts_test_t *tst;
+     tstc_t *tstc;
+     tstl_t *tstl;
+     int total_tests, total_tests_suite_failed;
+     int total_checks, total_checks_failed;
+     int test_checks, test_checks_failed;
+     const char *file;
+     int line;
+     char *cp;
+ 
+     if (ts == NULL)
+         return 0;
+ 
+     /* init total counters */
+     total_tests         = 0;
+     total_tests_suite_failed  = 0;
+     total_checks        = 0;
+     total_checks_failed = 0;
+ 
+     fprintf(stdout, "\n");
+     fprintf(stdout, " Test Suite: %s\n", ts->title);
+     fprintf(stdout, " __________________________________________________________________\n");
+     fprintf(stdout, "\n");
+     fflush(stdout);
+ 
+     /* iterate through all test cases */
+     RING_FOREACH(tst, &ts->tests, ts_test_t, next) {
+         cp = ts_suite_masprintf(" Test: %s ........................................"
+                                 "........................................", tst->title);
+         cp[60] = '\0';
+         fprintf(stdout, "%s", cp);
+         free(cp);
+         fflush(stdout);
+ 
+         /* init test case counters */
+         test_checks        = 0;
+         test_checks_failed = 0;
+ 
+         /* run the test case function */
+         tst->func(tst);
+ 
+         /* iterate through all performed checks to determine status */
+         RING_FOREACH(tstc, &tst->checks, tstc_t, next) {
+             test_checks++;
+             if (tstc->failed)
+                 test_checks_failed++;
+         }
+ 
+         if (test_checks_failed > 0) {
+             /* some checks failed, so do detailed reporting of test case */
+             fprintf(stdout, " FAILED\n");
+             fprintf(stdout, "       Ops, %d/%d checks failed! Detailed report follows:\n",
+                     test_checks_failed, test_checks);
+             RING_FOREACH(tstc, &tst->checks, tstc_t, next) {
+                 file = (tstc->file != NULL ? tstc->file : tst->file);
+                 line = (tstc->line != 0    ? tstc->line : tst->line);
+                 if (file != NULL)
+                     fprintf(stdout, "       Check: %s [%s:%d]\n", tstc->title, file, line);
+                 else
+                     fprintf(stdout, "       Check: %s\n", tstc->title);
+                 RING_FOREACH(tstl, &tstc->logs, tstl_t, next) {
+                     file = (tstl->file != NULL ? tstl->file : file);
+                     line = (tstl->line != 0    ? tstl->line : line);
+                     if (file != NULL)
+                         fprintf(stdout, "              Log: %s [%s:%d]\n", tstl->text, file, line);
+                     else
+                         fprintf(stdout, "              Log: %s\n", tstl->text);
+                 }
+             }
+         }
+         else {
+             /* test case ran successfully */
+             fprintf(stdout, ".... OK\n");
+         }
+         fflush(stdout);
+ 
+         /* accumulate counters */
+         total_checks += test_checks;
+         total_tests++;
+         if (test_checks_failed > 0) {
+             total_checks_failed += test_checks_failed;
+             total_tests_suite_failed++;
+         }
+     }
+ 
+     /* print test suite summary */
+     fprintf(stdout, " __________________________________________________________________\n");
+     fprintf(stdout, "\n");
+     fprintf(stdout, " Test Summary: %d tests (%d ok, %d failed), %d checks (%d ok, %d failed)\n", 
+             total_tests, (total_tests - total_tests_suite_failed), total_tests_suite_failed, 
+             total_checks, (total_checks - total_checks_failed), total_checks_failed); 
+     if (total_tests_suite_failed > 0)
+         fprintf(stdout, " Test Suite: FAILED\n");
+     else
+         fprintf(stdout, " Test Suite: OK\n");
+     fprintf(stdout, "\n");
+     fflush(stdout);
+ 
+     return total_checks_failed;
+ }
+ 
+ /* destroy test suite */
+ void ts_suite_free(ts_suite_t *ts)
+ {
+     ts_test_t *tst;
+     tstc_t *tstc;
+     tstl_t *tstl;
+ 
+     if (ts == NULL)
+         return;
+     RING_FOREACH(tst, &ts->tests, ts_test_t, next) {
+         RING_FOREACH(tstc, &tst->checks, tstc_t, next) {
+             RING_FOREACH(tstl, &tstc->logs, tstl_t, next) {
+                 free(tstl->text);
+             }
+             free(tstc->title);
+             free(tstc);
+         }
+         free(tst->title);
+         free(tst);
+     }
+     free(ts->title);
+     free(ts);
+     return;
+ }
+ 
+ /* annotate test case with file name and line number */
+ ts_test_t *ts_test_ctx(ts_test_t *tst, const char *file, int line)
+ {
+     if (tst != NULL && file != NULL) {
+         tst->file = file;
+         tst->line = line;
+     }
+     return tst;
+ }
+ 
+ /* annotate test case with check */
+ void ts_test_check(ts_test_t *tst, const char *fmt, ...)
+ {
+     tstc_t *tstc;
+     va_list ap;
+ 
+     if (tst == NULL || fmt == NULL)
+         return;
+     if ((tstc = (tstc_t *)malloc(sizeof(tstc_t))) == NULL)
+         return;
+     va_start(ap, fmt);
+     RING_ELEM_INIT(tstc, next);
+     tstc->title = ts_suite_mvasprintf(fmt, ap);
+     tstc->failed = 0;
+     tstc->file = tst->file;
+     tstc->line = tst->line;
+     RING_INIT(&tstc->logs, tstl_t, next);
+     RING_INSERT_TAIL(&tst->checks, tstc, tstc_t, next);
+     va_end(ap);
+     return;
+ }
+ 
+ /* annotate test case with log message and failure */
+ void ts_test_fail(ts_test_t *tst, const char *fmt, ...)
+ {
+     tstc_t *tstc;
+     tstl_t *tstl;
+     va_list ap;
+ 
+     if (tst == NULL || fmt == NULL)
+         return;
+     if ((tstl = (tstl_t *)malloc(sizeof(tstl_t))) == NULL)
+         return;
+     va_start(ap, fmt);
+     tstl->text = ts_suite_mvasprintf(fmt, ap);
+     tstl->file = tst->file;
+     tstl->line = tst->line;
+     RING_ELEM_INIT(tstl, next);
+     tstc = RING_LAST(&tst->checks);
+     RING_INSERT_TAIL(&tstc->logs, tstl, tstl_t, next);
+     tstc->failed = 1;
+     va_end(ap);
+     return;
+ }
+ 
+ /* annotate test case with log message only */
+ void ts_test_log(ts_test_t *tst, const char *fmt, ...)
+ {
+     tstc_t *tstc;
+     tstl_t *tstl;
+     va_list ap;
+ 
+     if (tst == NULL || fmt == NULL)
+         return;
+     if ((tstl = (tstl_t *)malloc(sizeof(tstl_t))) == NULL)
+         return;
+     va_start(ap, fmt);
+     tstl->text = ts_suite_mvasprintf(fmt, ap);
+     tstl->file = tst->file;
+     tstl->line = tst->line;
+     RING_ELEM_INIT(tstl, next);
+     tstc = RING_LAST(&tst->checks);
+     RING_INSERT_TAIL(&tstc->logs, tstl, tstl_t, next);
+     va_end(ap);
+     return;
+ }
+ 


ossp-pkg/tai/ts.c 1.1 -> 1.1.1.1


CVSTrac 2.0.1