🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: netcom.programmers
Article #1

Re: wanted: public domain strptime(3)

#1
From: D. Jason Penney
Date: Tue, 17 May 1994 16:45
1296 lines
41113 bytes
Eric De Mund <ead@netcom.com> writes:

>Good People,

>Can anyone point me towards a public domain strptime(3), a la SunOS's
>strptime(3)? [1]

>Thanks,
>Eric De Mund <ead@netcom.com>


The date/time parsing used by RCS is not perfect, but a pretty decent
hack for most of us.  I include my mangled version.

--j


----[cut here]

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  partime.c global.ht partime.hf
# Wrapped by jason@denim on Tue May 17 09:53:04 1994
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'partime.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'partime.c'\"
else
echo shar: Extracting \"'partime.c'\" \(34282 characters\)
sed "s/^X//" >'partime.c' <<'END_OF_FILE'
X#define PARTIME_C TRUE
X/*========================================================================
X * Name - partime.c (stolen from RCS 5.5 sources)
X *
X * $Id: partime.c,v 35.7 1994/04/30 08:52:01 darrel Exp $
X *
X * $Log: partime.c,v $
X *
X *	(ARPANET: KLH @ SRI)
X */
X
X/* Hacknotes:
X *	If parsing changed so that no backup needed, could perhaps modify
X *		to use a FILE input stream.  Need terminator, though.
X *	Perhaps should return 0 on success, else a non-zero error val?
X */
X
X/* 
X *
X * Revision 5.4  1990/10/04  06:30:15  eggert
X * Remove date vs time heuristics that fail between 2000 and 2400.
X * Check for overflow when lexing an integer.
X * Parse 'Jan 10 LT' as 'Jan 10, LT', not 'Jan, 10 LT'.
X *
X * Revision 5.3  1990/09/24  18:56:31  eggert
X * Update timezones.
X *
X * Revision 5.2  1990/09/04  08:02:16  eggert
X * Don't parse two-digit years, because it won't work after 1999/12/31.
X * Don't permit 'Aug Aug'.
X *
X * Revision 5.1  1990/08/29  07:13:49  eggert
X * Be able to parse our own date format.  Don't assume year<10000.
X *
X * Revision 5.0  1990/08/22  08:12:40  eggert
X * Switch to GMT and fix the bugs exposed thereby.  Update timezones.
X * Ansify and Posixate.  Fix peekahead and int-size bugs.
X *
X * Revision 1.4  89/05/01  14:48:46  narten
X * fixed #ifdef DEBUG construct
X * 
X * Revision 1.3  88/08/28  14:53:40  eggert
X * Remove unportable "#endif XXX"s.
X * 
X * Revision 1.2  87/03/27  14:21:53  jenkins
X * Port to suns
X * 
X * Revision 1.1  82/05/06  11:38:26  wft
X * Initial revision
X * 
X */
X
X#include "global.ht"
X
X#include "partime.hf"
X
X/* no more includes. KEEP THIS LINE */
X
X#define TZ_OFFSET (24*60) /* PARTIME_TMNULL  <  zone_offset - TZ_OFFSET */
X
Xstruct tmwent {
X  const char *went;
X  short wval;
X  char wflgs;
X  char wtype;
X  };
X
X/* wflgs */
X#define TWTIME 02	/* Word is a time value (absence implies date) */
X#define TWDST  04	/* Word is a DST-type timezone */
X	/* wtype */
X#define TM_MON	1	/* month name */
X#define TM_WDAY	2	/* weekday name */
X#define TM_ZON	3	/* time zone name */
X#define TM_LT	4	/* local time */
X#define TM_DST	5	/* daylight savings time */
X#define TM_12	6	/* AM, PM, NOON, or MIDNIGHT */
X	/* wval (for wtype==TM_12) */
X#define T12_AM 1
X#define T12_PM 2
X#define T12_NOON 12
X#define T12_MIDNIGHT 0
X
Xstatic const struct tmwent tmwords [] = {
X    {"january",      0, 0, TM_MON},
X    {"february",     1, 0, TM_MON},
X    {"march",        2, 0, TM_MON},
X    {"april",        3, 0, TM_MON},
X    {"may",          4, 0, TM_MON},
X    {"june",         5, 0, TM_MON},
X    {"july",         6, 0, TM_MON},
X    {"august",       7, 0, TM_MON},
X    {"september",    8, 0, TM_MON},
X    {"october",      9, 0, TM_MON},
X    {"november",     10, 0, TM_MON},
X    {"december",     11, 0, TM_MON},
X
X    {"sunday",       0, 0, TM_WDAY},
X    {"monday",       1, 0, TM_WDAY},
X    {"tuesday",      2, 0, TM_WDAY},
X    {"wednesday",    3, 0, TM_WDAY},
X    {"thursday",     4, 0, TM_WDAY},
X    {"friday",       5, 0, TM_WDAY},
X    {"saturday",     6, 0, TM_WDAY},
X
X    {"gmt",          0*60, TWTIME, TM_ZON},   /* Greenwich */
X    {"utc",          0*60, TWTIME, TM_ZON},
X    {"ut",           0*60, TWTIME, TM_ZON},
X
X    {"nzst",        -12*60, TWTIME, TM_ZON},  /* New Zealand */
X    {"jst",         -9*60, TWTIME, TM_ZON},   /* Japan */
X    {"kst",         -9*60, TWTIME, TM_ZON},   /* Korea */
X    {"ist",         -5*60-30, TWTIME, TM_ZON},/* India */
X    {"eet",         -2*60, TWTIME, TM_ZON},   /* Eastern Europe */
X    {"cet",         -1*60, TWTIME, TM_ZON},   /* Central Europe */
X    {"met",         -1*60, TWTIME, TM_ZON},   /* Middle Europe */
X    {"wet",          0*60, TWTIME, TM_ZON},   /* Western Europe */
X    {"nst",          3*60+30, TWTIME, TM_ZON},/* Newfoundland */
X    {"ast",          4*60, TWTIME, TM_ZON},   /* Atlantic */
X    {"est",          5*60, TWTIME, TM_ZON},   /* Eastern */
X    {"cst",          6*60, TWTIME, TM_ZON},   /* Central */
X    {"mst",          7*60, TWTIME, TM_ZON},   /* Mountain */
X    {"pst",          8*60, TWTIME, TM_ZON},   /* Pacific */
X    {"akst",         9*60, TWTIME, TM_ZON},   /* Alaska */
X    {"hast",         10*60, TWTIME, TM_ZON},  /* Hawaii-Aleutian */
X    {"hst",          10*60, TWTIME, TM_ZON},  /* Hawaii */
X    {"sst",          11*60, TWTIME, TM_ZON},  /* Samoa */
X
X    {"nzdt",        -12*60, TWTIME+TWDST, TM_ZON},    /* New Zealand */
X    {"kdt",         -9*60, TWTIME+TWDST, TM_ZON},     /* Korea */
X    {"bst",          0*60, TWTIME+TWDST, TM_ZON},     /* Britain */
X    {"ndt",          2*60+30, TWTIME+TWDST, TM_ZON}, /*Newfoundland (DDST)*/
X    {"adt",          4*60, TWTIME+TWDST, TM_ZON},     /* Atlantic */
X    {"edt",          5*60, TWTIME+TWDST, TM_ZON},     /* Eastern */
X    {"cdt",          6*60, TWTIME+TWDST, TM_ZON},     /* Central */
X    {"mdt",          7*60, TWTIME+TWDST, TM_ZON},     /* Mountain */
X    {"pdt",          8*60, TWTIME+TWDST, TM_ZON},     /* Pacific */
X    {"akdt",         9*60, TWTIME+TWDST, TM_ZON},     /* Alaska */
X    {"hadt",         10*60, TWTIME+TWDST, TM_ZON},    /* Hawaii-Aleutian */
X
X#if 0
X    /*
X     * The following names are duplicates or are not well attested.
X     * A standard is needed.
X     */
X    {"?st",         -13*60, TWTIME, TM_ZON},  /* Uelen */
X    {"?st",         -11*60, TWTIME, TM_ZON},  /* Magadan */
X    {"east",        -10*60, TWTIME, TM_ZON},  /* Eastern Australia */
X    {"cast",        -9*60-30, TWTIME, TM_ZON},/* Central Australia */
X    {"cst",         -8*60, TWTIME, TM_ZON},   /* China */
X    {"hkt",         -8*60, TWTIME, TM_ZON},   /* Hong Kong */
X    {"sst",         -8*60, TWTIME, TM_ZON},   /* Singapore */
X    {"wast",        -8*60, TWTIME, TM_ZON},   /* Western Australia */
X    {"?st",         -7*60, TWTIME, TM_ZON},   /* Novosibirsk */
X    {"jt",          -7*60-30, TWTIME, TM_ZON},/* Java */
X    {"nst",         -6*60-30, TWTIME, TM_ZON},/* North Sumatra */
X    {"?st",         -6*60, TWTIME, TM_ZON},   /* Tashkent */
X    {"?st",         -5*60, TWTIME, TM_ZON},	  /* Sverdlovsk */
X    {"?",           -4*60-30, TWTIME, TM_ZON},/* Afghanistan */
X    {"?st",         -4*60, TWTIME, TM_ZON},	  /* Rostov */
X    {"it",          -3*60-30, TWTIME, TM_ZON},/* Iran */
X    {"?st",         -3*60, TWTIME, TM_ZON},   /* Moscow */
X    {"ist",         -2*60, TWTIME, TM_ZON},   /* Israel */
X    {"ast",          1*60, TWTIME, TM_ZON},   /* Azores */
X    {"fst",          2*60, TWTIME, TM_ZON},   /* Fernando de Noronha */
X    {"bst",          3*60, TWTIME, TM_ZON},   /* Brazil */
X    {"wst",          4*60, TWTIME, TM_ZON},   /* Western Brazil */
X    {"ast",          5*60, TWTIME, TM_ZON},   /* Acre Brazil */
X    {"?",            9*60+30, TWTIME, TM_ZON},/* Marquesas */
X    {"?st",          12*60, TWTIME, TM_ZON},  /* Kwajalein */
X
X    {"?dt",         -13*60, TWTIME+TWDST, TM_ZON},	  /* Uelen */
X    {"?dt",         -11*60, TWTIME+TWDST, TM_ZON},	  /* Magadan */
X    {"eadt",        -10*60, TWTIME+TWDST, TM_ZON},    /* Eastern Australia */
X    {"cadt",        -9*60-30, TWTIME+TWDST, TM_ZON},  /* Central Australia */
X    {"cdt",         -8*60, TWTIME+TWDST, TM_ZON},     /* China */
X    {"wadt",        -8*60, TWTIME+TWDST, TM_ZON},     /* Western Australia */
X    {"?dt",         -7*60, TWTIME+TWDST, TM_ZON},	  /* Novosibirsk */
X    {"?dt",         -6*60, TWTIME+TWDST, TM_ZON},	  /* Tashkent */
X    {"?dt",         -5*60, TWTIME+TWDST, TM_ZON},	  /* Sverdlovsk */
X    {"?dt",         -4*60, TWTIME+TWDST, TM_ZON},	  /* Rostov */
X    {"?dt",         -3*60, TWTIME+TWDST, TM_ZON},     /* Moscow */
X    {"idt",         -2*60, TWTIME+TWDST, TM_ZON},     /* Israel */
X    {"eest",        -2*60, TWTIME+TWDST, TM_ZON},     /* Eastern Europe */
X    {"cest",        -1*60, TWTIME+TWDST, TM_ZON},     /* Central Europe */
X    {"mest",        -1*60, TWTIME+TWDST, TM_ZON},     /* Middle Europe */
X    {"west",         0*60, TWTIME+TWDST, TM_ZON},     /* Western Europe */
X    {"adt",          1*60, TWTIME+TWDST, TM_ZON},	  /* Azores */
X    {"fdt",          2*60, TWTIME+TWDST, TM_ZON},     /* Fernando de Noronha */
X    {"edt",          3*60, TWTIME+TWDST, TM_ZON},     /* Eastern Brazil */
X    {"wdt",          4*60, TWTIME+TWDST, TM_ZON},     /* Western Brazil */
X    {"adt",          5*60, TWTIME+TWDST, TM_ZON},     /* Acre Brazil */
X#endif
X
X    {"lt",           0, TWTIME, TM_LT},       /* local time */
X    {"dst",          1*60, TWTIME, TM_DST},      /* daylight savings time */
X    {"ddst",         2*60, TWTIME, TM_DST},      /* double dst */
X
X    {"am",           T12_AM,	TWTIME, TM_12},
X    {"pm",           T12_PM,	TWTIME, TM_12},
X    {"noon",         T12_NOON,	TWTIME, TM_12},
X    {"midnight",     T12_MIDNIGHT,	TWTIME, TM_12},
X
X    {0, 0, 0, 0},             /* Zero entry to terminate searches */
X};
X
Xstruct token {
X  const char *tokStart;/* pointer to string */
X  int tokSize;	/* # chars */
X  char nextDelim;	/* "break" char */
X  char prevDelim;	/* last break char */
X  BoolType isNumeric;/* 0 = alpha, 1 = numeric */
X  union {         /* Resulting value; */
X    int tnum;		      /* either a #, or */
X    const struct tmwent *ttmw;/* ptr to a tmwent. */
X    } tval;
X  };
X
Xstatic const struct tmwent *ptmatchstr(
X#if defined(FLG_PROTOTYPE)
X    const char *astr, int cnt, const struct tmwent *astruc
X#endif
X    );
X
Xstatic BoolType pt12hack(
X#if defined(FLG_PROTOTYPE)
X    struct tm *,int
X#endif
X    );
X
Xstatic BoolType ptitoken(
X#if defined(FLG_PROTOTYPE)
X    register struct token *tkp
X#endif
X    );
X
Xstatic BoolType ptstash(
X#if defined(FLG_PROTOTYPE)
X    int *adr, int val
X#endif
X    );
X
Xstatic int pttoken(
X#if defined(FLG_PROTOTYPE)
X    register struct token *tkp
X#endif
X    );
X
X#if defined(FLG_PROTOTYPE)
Xstatic BoolType goodzone(register const struct token *t, int offset, int *am)
X#else
Xstatic BoolType goodzone(t, offset, am)
X  register const struct token *t;
X  int offset;
X  int *am;
X#endif
X{
X  register int m;
X
X  if (
X      t->isNumeric  &&
X      t->tokSize == 4+offset  &&
X      (m = t->tval.tnum) <= 2400  &&
X      isdigit(t->tokStart[offset]) &&
X      (m %= 100) < 60 ) {
X    m += t->tval.tnum / 100 * 60;
X    if (t->tokStart[offset - 1] == '+')
X      m = -m;
X    *am = m;
X    return TRUE;
X    }
X  return FALSE;
X}
X
X#if defined(FLG_PROTOTYPE)
XBoolType ParseTime(const char *astr, register struct tm *atm, int *zone)
X#else
XBoolType ParseTime(astr, atm, zone)
Xconst char *astr;
Xregister struct tm *atm;
Xint *zone;
X#endif
X{
X  register int i;
X  struct token curToken, nextToken;
X  int zone_offset; /* minutes west of GMT, plus TZ_OFFSET */
X  register const char *cp;
X  register char ch;
X  BoolType numericMonth = TRUE;
X  int midnoon;
X  int *atmfield, dst, m;
X  BoolType got1 = FALSE;
X  BoolType result = FALSE;
X
X  *zone = MAKETIME_LOCALZONE;
X
X  atm->tm_sec = PARTIME_TMNULL;
X  atm->tm_min = PARTIME_TMNULL;
X  atm->tm_hour = PARTIME_TMNULL;
X  atm->tm_mday = PARTIME_TMNULL;
X  atm->tm_mon = PARTIME_TMNULL;
X  atm->tm_year = PARTIME_TMNULL;
X  atm->tm_wday = PARTIME_TMNULL;
X  atm->tm_yday = PARTIME_TMNULL;
X  midnoon = PARTIME_TMNULL;		/* and our own temp stuff */
X  zone_offset = PARTIME_TMNULL;
X  dst = PARTIME_TMNULL;
X  curToken.tokSize = 0;
X  curToken.nextDelim = '\0';
X  curToken.tokStart = astr;
X
X  for (;; got1 = TRUE) {
X    if (!ptitoken(&curToken)) {			/* Get a token */
X      if (curToken.tval.tnum)
X	goto LABEL_DONE;         /* Read error? */
X      if (MAKETIME_GIVEN(midnoon))			/* EOF, wrap up */
X	if (!pt12hack(atm, midnoon))
X	  goto LABEL_DONE;
X      if (!MAKETIME_GIVEN(atm->tm_min))
X	atm->tm_min = 0;
X      result = got1;
X      goto LABEL_DONE;
X      }
X    if (curToken.isNumeric == FALSE) {	/* Alpha? */
X      i = curToken.tval.ttmw->wval;
X      switch (curToken.tval.ttmw->wtype) {
X	default:
X	  goto LABEL_DONE;
X
X	case TM_MON:
X	  numericMonth = FALSE;
X	  atmfield = &atm->tm_mon;
X	  break;
X
X	case TM_WDAY:
X	  atmfield = &atm->tm_wday;
X	  break;
X
X	case TM_DST:
X	  atmfield = &dst;
X	  break;
X
X	case TM_LT:
X	  if (ptstash(&dst, 0))
X	    goto LABEL_DONE;
X	  i = MAKETIME_LOCALZONE;
X	/* fall into */
X#if defined(FLG_CSET2)
X	  goto FALL_THROUGH;
X#endif
X
X	case TM_ZON:
X#if defined(FLG_CSET2)
XFALL_THROUGH:
X#endif
X	  i += TZ_OFFSET;
X	  if (curToken.tval.ttmw->wflgs & TWDST)
X	    if (ptstash(&dst, 60))
X	      goto LABEL_DONE;
X	  /* Peek ahead for offset immediately afterwards. */
X	  if (
X	      (curToken.nextDelim == '-' || curToken.nextDelim == '+') &&
X	      (nextToken=curToken, ++nextToken.tokSize, ptitoken(&nextToken)) &&
X	      goodzone(&nextToken, 0, &m)) {
X	    i += m;
X	    curToken = nextToken;
X	    }
X	  atmfield = &zone_offset;
X	  break;
X
X	case TM_12:
X	  atmfield = &midnoon;
X	}
X      if (ptstash(atmfield, i))
X	goto LABEL_DONE;		/* ERR: val already set */
X      continue;
X      }
X
X    /* Token is number.  Lots of hairy heuristics. */
X    if (!isdigit(*curToken.tokStart)) {
X      if (!goodzone(&curToken, 1, &m))
X	goto LABEL_DONE;
X      zone_offset = TZ_OFFSET + m;
X      continue;
X      }
X
X    i = curToken.tval.tnum;   /* Value now known to be valid; get it. */
X    if (curToken.tokSize == 3) { /*  3 digits = HMM   */
Xhhmm4:
X      if (ptstash(&atm->tm_min, i % 100))
X	goto LABEL_DONE;		/* ERR: min conflict */
X      i /= 100;
Xhh2:
X      if (ptstash(&atm->tm_hour, i))
X	goto LABEL_DONE;		/* ERR: hour conflict */
X      continue;
X      }
X
X    if (4 < curToken.tokSize)
X      goto year4; /* far in the future */
X    if (curToken.tokSize == 4) { /* 4 digits = YEAR or HHMM */
X      if (MAKETIME_GIVEN(atm->tm_year))
X	goto hhmm4;	/* Already got yr? */
X      if (MAKETIME_GIVEN(atm->tm_hour))
X	goto year4;	/* Already got hr? */
X      if (curToken.nextDelim == ':')			/* HHMM:SS ? */
X	if (ptstash(&atm->tm_hour, i / 100)
X	    || ptstash(&atm->tm_min, i % 100))
X	  goto LABEL_DONE;		/* ERR: hr/min clash */
X	else
X	  goto coltm2;		/* Go handle SS */
X      if (curToken.nextDelim != ',' && curToken.nextDelim != '/'
X	  && (nextToken=curToken, ptitoken(&nextToken))	/* Peek */
X	  && ( nextToken.isNumeric
X	     ? !isdigit(*nextToken.tokStart)
X	     : nextToken.tval.ttmw->wflgs & TWTIME)) /* HHMM-ZON */
X	goto hhmm4;
X      goto year4;			/* Give up, assume year. */
X      }
X
X    /* From this point on, assume tokSize == 1 or 2 */
X    /* 2 digits = MM, DD, or HH (MM and SS caught at coltime) */
X    if (curToken.nextDelim == ':')		/* HH:MM[:SS] */
X      goto coltime;		/*  must be part of time. */
X    if (31 < i)
X      goto LABEL_DONE;
X
X    /* Check for numerical-format date */
X    for (cp = "/-."; (ch = *cp++) != 0;) {
X      if (curToken.nextDelim == ch) {	/* "NN-" */
X	if (curToken.prevDelim != ch) {
X	  nextToken = curToken;
X	  nextToken.tokSize++;
X	  if (ptitoken(&nextToken) /* peek */
X	      && nextToken.isNumeric == FALSE
X	      && nextToken.tval.ttmw->wtype == TM_MON) {
X	    numericMonth = FALSE;
X	    goto dd2;
X	    }
X	  goto monthOrDay;
X	  } /* "NN-" */
X	/* "-NN-" */
X	if (!MAKETIME_GIVEN(atm->tm_mday) && MAKETIME_GIVEN(atm->tm_year)) {
X	  /* If "YYYY-NN-" then always MM */
X	  numericMonth = FALSE;
X	  goto mm2;
X	  }
X	goto monthOrDay;
X	}
X      if (curToken.prevDelim == ch) 	/* "-NN" */
X	goto monthOrDay;
X      }
X
X    /* Now reduced to choice between HH and DD */
X    if (MAKETIME_GIVEN(atm->tm_hour))
X      goto dd2;	/* Have hour? Assume day. */
X    if (MAKETIME_GIVEN(atm->tm_mday))
X      goto hh2;	/* Have day? Assume hour. */
X    if (MAKETIME_GIVEN(atm->tm_mon))
X      goto dd2;	/* Have month? Assume day. */
X    if (i > 24)
X      goto dd2;			/* Impossible HH means DD */
X    nextToken = curToken;
X    if (!ptitoken(&nextToken))	/* Read ahead! */
X      if (nextToken.tval.tnum)
X	goto LABEL_DONE; /* ERR: bad token */
X      else
X	goto dd2;		/* EOF, assume day. */
X    if ( nextToken.isNumeric ? !isdigit(*nextToken.tokStart)
X       : nextToken.tval.ttmw->wflgs & TWTIME)
X      /* If next token is a time spec, assume hour */
X      goto hh2;		/* e.g. "3 PM", "11-EDT"  */
X
Xdd2:
X    if (ptstash(&atm->tm_mday, i))	/* Store day (1 based) */
X      goto LABEL_DONE;
X    continue;
X    /* NOTREACHED */
X
Xmm2:
X    if (ptstash(&atm->tm_mon, i-1))	/* Store month (make zero based) */
X      goto LABEL_DONE;
X    continue;
X    /* NOTREACHED */
X
XmonthOrDay:
X    /* we have 2 digit numeral.  Could be either day or month... */
X    if (!numericMonth)
X      goto dd2; /* current int can't be a month. */
X    if (!MAKETIME_GIVEN(atm->tm_mday))
X      goto dd2; /* shove numeral into day slot; we'll fix it later if needed */
X    if (MAKETIME_GIVEN(atm->tm_mon))
X      goto LABEL_DONE; /* overspecified */
X
X    /* we have atm->tm_mday versus i.  What's right? */
X    if (i > 12) { /* we clearly have a day; tm_mday is really a month */
X      if (atm->tm_mday > 12)
X	goto LABEL_DONE; /* two days specified?  yucch. */
X      /* we assumed another numeral was a day, but it was a month.
X	 back it out. */
X      atm->tm_mon = atm->tm_mday - 1; /* zero-bias */
X      atm->tm_mday = PARTIME_TMNULL;
X      goto dd2;
X      }
X    else
X      goto mm2;
X    /* NOTREACHED */
X
Xyear4:
X    if ((i-=1900) < 0  ||  ptstash(&atm->tm_year, i)) /* Store year-1900 */
X      goto LABEL_DONE;		/* ERR: year conflict */
X    continue;
X
X    /* Hack HH:MM[[:]SS] */
Xcoltime:
X    if (ptstash(&atm->tm_hour, i))
X      goto LABEL_DONE;
X    if (!ptitoken(&curToken)) {
X      result = !curToken.tval.tnum;
X      goto LABEL_DONE;
X      }
X    if (!curToken.isNumeric)
X      goto LABEL_DONE;	/* ERR: HH:<alpha> */
X    if (curToken.tokSize == 4)		/* MMSS */
X      if (ptstash(&atm->tm_min, curToken.tval.tnum / 100)
X	  || ptstash(&atm->tm_sec, curToken.tval.tnum%100))
X	goto LABEL_DONE;
X      else
X	continue;
X    if (curToken.tokSize != 2 || ptstash(&atm->tm_min, curToken.tval.tnum))
X      goto LABEL_DONE;		/* ERR: MM bad */
X    if (curToken.nextDelim != ':')
X      continue;	/* Seconds follow? */
X
Xcoltm2:
X    if (!ptitoken(&curToken)) {
X      result = !curToken.tval.tnum;
X      goto LABEL_DONE;
X      }
X    if (!curToken.isNumeric || curToken.tokSize != 2	/* Verify SS */
X	|| ptstash(&atm->tm_sec, curToken.tval.tnum))
X      goto LABEL_DONE; /* ERR: SS bad */
X    }
X
XLABEL_DONE:
X  if (result) {
X    if (!MAKETIME_GIVEN(zone_offset))
X      *zone = MAKETIME_LOCALZONE;
X    else {
X      *zone  = zone_offset - TZ_OFFSET;
X      if (MAKETIME_GIVEN(dst))
X	*zone -= dst;
X      }
X    }
X  return result;
X}
X
X/* Store date/time value, return 0 if successful.
X * Fail if entry is already set.
X */
X#if defined(FLG_PROTOTYPE)
Xstatic BoolType ptstash(int *adr, int val)
X#else
Xstatic BoolType ptstash(adr,val)
Xint *adr;
Xint val;
X#endif
X{
X  register int *a;
X
X  if (MAKETIME_GIVEN(*(a=adr)))
X    return TRUE;
X  *a = val;
X  return FALSE;
X}
X
X/* This subroutine is invoked for AM, PM, NOON and MIDNIGHT when wrapping up
X * just prior to returning from partime.
X */
X
X#if defined(FLG_PROTOTYPE)
Xstatic BoolType pt12hack(register struct tm *tm, register int aval)
X#else
Xstatic BoolType pt12hack(tm, aval)
Xregister struct tm *tm;
Xregister int aval;
X#endif
X{
X  register int h = tm->tm_hour;
X
X  switch (aval) {
X    case T12_AM:
X    case T12_PM:
X      if (h > 12)
X	return FALSE;
X      if (h == 12)
X	tm->tm_hour = 0;
X      if (aval == T12_PM)
X	tm->tm_hour += 12;
X      break;
X
X    default:
X      if (0 < tm->tm_min  ||  0 < tm->tm_sec)
X	return FALSE;
X      if (!MAKETIME_GIVEN(h) || h==12)
X	tm->tm_hour = aval;
X      else
X      if (aval==T12_MIDNIGHT  &&  (h==0 || h==24))
X	return FALSE;
X  }
X  return TRUE;
X}
X
X/* Get a token and identify it to some degree.
X * Returns 0 on failure; token.tval will be 0 for normal EOF, otherwise
X * hit error of some sort
X */
X
X#if defined(FLG_PROTOTYPE)
Xstatic BoolType ptitoken(register struct token *tkp)
X#else
Xstatic BoolType ptitoken(tkp)
Xregister struct token *tkp;
X#endif
X{
X  register const char *cp;
X  register int i, j, k;
X
X  if (pttoken(tkp) == 0) {
X#ifdef TRACING
X    printf("EOF from pttoken\n");
X#endif
X    return FALSE;
X    }
X  cp = tkp->tokStart;
X
X#ifdef TRACING
X  VOID printf("Token: \"%.*s\" ", tkp->tokSize, cp);
X#endif
X
X  if (tkp->isNumeric) {
X    i = tkp->tokSize;
X    if (*cp == '+' || *cp == '-') {
X      cp++;
X      i--;
X      }
X    while (0 <= --i) {
X      j = tkp->tval.tnum*10;
X      k = j + (*cp++ - '0');
X      if (j / 10 != tkp->tval.tnum  ||  k < j) { /* arithmetic overflow */
X	tkp->tval.tnum = 1;
X	return FALSE;
X	}
X      tkp->tval.tnum = k;
X      }
X    }
X  else
X  if (!(tkp->tval.ttmw  =  ptmatchstr(cp, tkp->tokSize, tmwords))) {
X#ifdef TRACING
X    printf("Not found!\n");
X#endif
X    tkp->tval.tnum = 1;
X    return FALSE;
X    }
X
X#ifdef TRACING
X  if (tkp->isNumeric)
X    printf("Val: %d.\n",tkp->tval.tnum);
X  else 
X    printf("Found: \"%s\", val: %d, type %d\n",
X	  tkp->tval.ttmw->went,tkp->tval.ttmw->wval,tkp->tval.ttmw->wtype);
X#endif
X
X  return TRUE;
X}
X
X/* Read token from input string into token structure */
X#if defined(FLG_PROTOTYPE)
Xstatic int pttoken(register struct token *tkp)
X#else
Xstatic int pttoken(tkp)
Xregister struct token *tkp;
X#endif
X{
X  register const char *cp;
X  register int c;
X  const char *astr;
X
X  tkp->tokStart = astr = cp = tkp->tokStart + tkp->tokSize;
X  tkp->prevDelim = tkp->nextDelim;		/* Set "last break" */
X  tkp->tokSize = tkp->nextDelim = 0;
X  tkp->isNumeric = FALSE;
X  tkp->tval.tnum = 0;
X
X  while((c = *cp++) != 0) {
X    switch(c) {
X      case ' ':
X      case '\t':	/* Flush all whitespace */
X      case '\r':
X      case '\n':
X      case '\v':
X      case '\f':
X	if (!tkp->tokSize) {	/* If no token yet */
X	  tkp->tokStart = cp;	/* ignore the brk */
X	  continue;	        /* and go on. */
X	  }
X      /* fall into */
X#if defined(FLG_CSET2)
X      goto FALL_THROUGH;
X#endif
X
X      case '(':
X      case ')':	/* Perhaps any non-alphanum */
X      case '-':
X      case ',':	/* shd qualify as break? */
X      case '+':
X      case '/':
X      case ':':
X      case '.':	/* Break chars */
X#if defined(FLG_CSET2)
XFALL_THROUGH:
X#endif
X	if (tkp->tokSize == 0) {	/* If no token yet */
X	  tkp->tokStart = cp;	/* ignore the brk */
X	  tkp->prevDelim = (char)c;
X	  continue;	/* and go on. */
X	  }
X	tkp->nextDelim = (char)c;
X	return tkp->tokSize;
X      }
X    if (!tkp->tokSize++) {		/* If first char of token, */
X      if (isdigit(c)) {
X	tkp->isNumeric = TRUE;
X	if (astr < cp - 2 && (cp[-2] == '-' || cp[-2] == '+')) {
X	  /* timezone is break+sign+digit */
X	  tkp->tokStart--;
X	  tkp->tokSize++;
X	  }
X	}
X      }
X    else
X    if ((isdigit(c) != 0) != tkp->isNumeric) { /* else check type */
X      tkp->nextDelim = (char)c;
X      return --tkp->tokSize;	/* Wrong type, back up */
X      }
X    }
X  return tkp->tokSize;		/* When hit EOF */
X}
X
X
X#if defined(FLG_PROTOTYPE)
Xstatic const struct tmwent *ptmatchstr(const char *astr, int cnt,
X    const struct tmwent *astruc)
X#else
Xstatic const struct tmwent *ptmatchstr(astr,cnt,astruc)
X	const char *astr;
X	int cnt;
X	const struct tmwent *astruc;
X#endif
X{
X  register const char *cp, *mp;
X  register int c;
X  const struct tmwent *lastptr;
X  int i;
X
X  lastptr = 0;
X  for (;(mp = astruc->went) != 0; astruc += 1) {
X    cp = astr;
X    for (i = cnt; i > 0; i--) {
X      c = *mp++;
X      switch (*cp++ - c) {
X	case 0:
X	  continue;	/* Exact match */
X	case 'A'-'a':
X	  if (isalpha(c))
X	    continue;
X	}
X      break;
X      }
X    if (i == 0)
X      if (*mp == '\0')
X        return astruc;	/* Exact match */
X      else
X      if (lastptr)
X	return NULL;	/* Ambiguous */
X      else
X	lastptr = astruc;		/* 1st ambig */
X    }
X  return lastptr;
X}
X
X/*========================================================================
X * Semi-public software; should only be used in gemcopy!
X *
X * Name - maketime.c (stolen from RCS 5.5 sources)
X *
X * $Id: partime.c,v 35.7 1994/04/30 08:52:01 darrel Exp $
X *
X * $Log: partime.c,v $
X * Revision 35.7  1994/04/30  08:52:01  darrel
X * Added "cheat" line for quick dependency analysis.
X *
X * Revision 35.6  1994/04/06  17:47:12  otisa
X * lint fixes for OS/2
X *
X * Revision 35.5  1994/02/10  00:56:59  darrel
X * 1. BoolType typedef changed from 'unsigned char' to 'int'.
X * 2. Added NRS modifiers #netldi, #dir, and #log.
X * 3. GcGem's and SharedPCmonitors no longer need a netldi to start them.
X *    They will be started by either the stone or pgsvr.
X *
X * Revision 35.4  1993/12/31  00:04:51  darrel
X * purged the rcs log comment.
X *
X * Revision 35.3  1993/08/27  02:14:55  otisa
X * merge fixes from 3.2
X *
X * Revision 35.2  1993/08/03  00:01:17  garyh
X * Changes for Sequent and Solaris.
X *
X * Revision 35.1.1.2  1993/07/23  20:23:17  garyh
X * Bringing up to date per 23 July
X *
X * Revision 3.2.1.6  1993/08/08  23:48:50  penneyj
X * Fix Sequent and Solaris problems.  Make coredump more cautious.
X *
X * Revision 3.2.1.5  1993/07/30  01:43:55  darrel
X * 1. backend will now compile cleanly with gcc 2.4.5 and SunOs 4.1
X * 2. added netldi "guest mode" and "captive account mode"
X * 3. Introduced the typedef ArraySizeType that should be used for
X *    variables that represent the size of an array.
X *
X * Revision 3.2.1.4  1993/06/28  18:09:39  darrel
X * Commit of Windows NT changes.
X *
X * Revision 3.2.1.3  1993/03/16  06:37:55  penneyj
X * Change includes to double quotes (for the Macintosh)
X * Revived Ultrix-32 (DECstation) port.  Removed warnings from DYNIX port.
X *
X * Revision 3.2.1.2  1992/08/11  19:47:50  penneyj
X * many fixes
X *
X * Revision 1.3.1.1  1992/07/21  21:46:25  penneyj
X * Fix bug5414.  Add env expansion to HostExpandFileName (386 platforms).
X * Extend logic for sunset dates (more friendly).
X * Fix port to MS Windows (utl.c)
X *
X * Revision 1.3  1992/07/21  21:46:24  penneyj
X * Fix bug5414.  Add env expansion to HostExpandFileName (386 platforms).
X * Extend logic for sunset dates (more friendly).
X * Fix port to MS Windows (utl.c)
X *
X *
X *
X * MAKETIME		derive 32-bit time value from TM structure.
X *
X * Usage:
X *	int zone;	Minutes west of GMT, or
X *			48*60 for localtime
X *	time_t t;
X *	struct tm *tp;	Pointer to TM structure from <time.h>
X *	t = maketime(tp,zone);
X *
X * Returns:
X *	-1 if failure; parameter out of range or nonsensical.
X *	else time-value.
X * Notes:
X *	This code is quasi-public; it may be used freely in like software.
X *	It is not to be sold, nor used in licensed software without
X *	permission of the author.
X *	For everyone's benefit, please report bugs and improvements!
X * 	Copyright 1981 by Ken Harrenstien, SRI International.
X *	(ARPANET: KLH @ SRI)
X * 
X * 
X * Revision 5.2  1990/11/01  05:03:30  eggert
X * Remove lint.
X *
X * Revision 5.1  1990/10/04  06:30:13  eggert
X * Calculate the GMT offset of 'xxx LT' as of xxx, not as of now.
X * Don't assume time_t is 32 bits.  Fix bugs near epoch and near end of time.
X *
X * Revision 5.0  1990/08/22  08:12:38  eggert
X * Switch to GMT and fix the bugs exposed thereby.
X * Permit dates past 1999/12/31.  Ansify and Posixate.
X *
X * Revision 1.8  88/11/08  13:54:53  narten
X * allow negative timezones (-24h <= x <= 24h)
X * 
X * Revision 1.7  88/08/28  14:47:52  eggert
X * Allow cc -R.  Remove unportable "#endif XXX"s.
X * 
X * Revision 1.6  87/12/18  17:05:58  narten
X * include rcsparam.h
X * 
X * Revision 1.5  87/12/18  11:35:51  narten
X * maketime.c: fixed USG code - you have tgo call "tzset" in order to have
X * "timezone" set. ("localtime" calls it, but it's probably better not to 
X * count on "localtime" having been called.)
X * 
X * Revision 1.4  87/10/18  10:26:57  narten
X * Updating version numbers. Changes relative to 1.0 are actually 
X * relative to 1.2
X * 
X * Revision 1.3  87/09/24  13:58:45  narten
X * Sources now pass through lint (if you ignore printf/sprintf/fprintf 
X * warnings)
X * 
X * Revision 1.2  87/03/27  14:21:48  jenkins
X * Port to suns
X * 
X * Revision 1.2  83/12/05  10:12:56  wft
X * added cond. compilation for USG Unix; long timezone;
X * 
X * Revision 1.1  82/05/06  11:38:00  wft
X * Initial revision
X * 
X */
X
X/*
X* Convert Unix time to struct tm format.
X*/
X#define time2tm(x) gmtime(&x)
X
Xstatic const int daytb[] = {
X	/* # days in year thus far, indexed by month (0-12!!) */
X	0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
X};
X
X#if defined(FLG_PROTOTYPE)
Xtime_t MakeTime(const struct tm *atm, int zone, const char **errReason)
X#else
Xtime_t MakeTime(atm,zone, errReason)
X    const struct tm *atm;
X    int zone;
X    const char **errReason;
X#endif
X{
X  register const struct tm *tp;
X  register int i;
X  BoolType localzone, leap;
X  int year, yday, mon, day, hour, min, sec;
X  int attempts;
X  time_t t, tres;
X
X  *errReason = "internal error"; /* be safe! */
X  attempts = 2;
X  localzone = (zone == MAKETIME_LOCALZONE);
X  tres = -1;
X  year = mon = day = 0;  /* Keep lint happy.  */
X
X  do {
X    if (localzone || !MAKETIME_GIVEN(atm->tm_year)) {
X      if (tres == -1)
X	if ((tres = time(NULL))  ==  -1) {
X	  *errReason = "can't get current time";
X	  return -1;
X	  }
X      tp = time2tm(tres);
X      /* Get breakdowns of default time, adjusting to zone. */
X      year = tp->tm_year;		/* Use to set up defaults */
X      yday = tp->tm_yday;
X      mon = tp->tm_mon;
X      day = tp->tm_mday;
X      hour = tp->tm_hour;
X      min = tp->tm_min;
X      if (localzone) {
X	tp = localtime(&tres);
X	zone = min - tp->tm_min + 60 * (
X	    hour - tp->tm_hour + 24 * (
X		  /* If years differ, it's by one day. */
X	    year - tp->tm_year
X		  ? year - tp->tm_year
X		  : yday - tp->tm_yday));
X	}
X      /* Adjust the default day, month and year according to zone.  */
X      min -= zone;
X      if (min < 0) {
X	if (hour - (59 - min) / 60 < 0  &&  --day <= 0) {
X	  mon --;
X	  if (mon < 0) {
X	    --year;
X	    mon = 11;
X	    }
X	  day  =  daytb[mon + 1] - daytb[mon] +
X	      (mon == 1 && !((year & 3) != 0));
X	  }
X	}
X      else
X      if (24 <= hour + min / 60 &&
X	  daytb[mon + 1] - daytb[mon] + (mon == 1&& !((year & 3) != 0)) < ++day
X	  ) {
X        mon ++;
X	if (11 < mon) {
X	  ++year;
X	  mon = 0;
X	  }
X	day = 1;
X	}
X      }
X      if (zone < -24*60  ||  24*60 < zone) {
X	*errReason = "timezone error";
X	return -1;
X	}
X
X
X#ifdef TRACING
Xprintf("first YMD: %d %d %d\n",year,mon,day);
X#endif
X      tp = atm;
X
X      /* First must find date, using specified year, month, day.
X       * If one of these is unspecified, it defaults either to the
X       * current date (if no more global spec was given) or to the
X       * zero-value for that spec (i.e. a more global spec was seen).
X       * Reject times that do not fit in time_t,
X       * without assuming that time_t is 32 bits or is signed.
X       */
X      if (MAKETIME_GIVEN(tp->tm_year)) {
X	year = tp->tm_year;
X	mon = 0;		/* Since year was given, default */
X	day = 1;		/* for remaining specs is zero */
X	}
X      if (year < 69) {			/* 1969/12/31 OK in some timezones.  */
X	*errReason = "year out of range";
X	return -1;		/* ERR: year out of range */
X	}
X      leap = (!(year&3)  &&  (year%100 || !((year+300)%400)));
X      year -= 70;			/* UNIX time starts at 1970 */
X
X      /*
X       * Find day of year.
X       */
X      if (MAKETIME_GIVEN(tp->tm_mon)) {
X	mon = tp->tm_mon;	/* Month was specified */
X	day = 1;		/* so set remaining default */
X	}
X      if (11 < (unsigned)mon) {
X	*errReason = "month out of range";
X	return -1;		/* ERR: bad month */
X	}
X      if (MAKETIME_GIVEN(tp->tm_mday))
X	day = tp->tm_mday;
X      if (day < 1 || (((daytb[mon + 1] - daytb[mon]) < day)
X	  && (day != 29 || mon != 1 || !leap) )) {
X	*errReason = "day out of range";
X	return -1;	/* ERR: bad day */
X	}
X      yday = daytb[mon]		/* Add # of days in months so far */
X	  + ((leap		/* Leap year, and past Feb?  If */
X	  && mon > 1) ? 1 :0)	/* so, add leap day for this year */
X	  + day-1;		/* And finally add # days this mon */
X
X      if ((int)leap + 365 <= yday) {
X	*errReason = "bad yday";
X	return -1;		/* ERR: bad YDAY */
X	}
X
X      if (year < 0) {
X	if (yday != 364) {
X	  *errReason = "too early";
X	  return -1;		/* ERR: too early */
X	  }
X	t = -1;
X	}
X      else {
X	tres = year * 365;		/* Get # days of years so far */
X	if (tres / 365 != year) {
X	  *errReason = "overflow coverting year to days";
X	  return -1;		/* ERR: overflow */
X	  }
X	t = tres
X	  + ((year+1)>>2)		/* plus # of leap days since 1970 */
X	  + yday;			/* and finally add # days this year */
X	if (t + 4 < tres) {
X	  *errReason = "overflow coverting year to days";
X	  return -1;		/* ERR: overflow */
X	  }
X	}
X      tres = t;
X
X      i = tp->tm_wday; /* Check WDAY if present */
X      if (MAKETIME_GIVEN(i)) /* Check WDAY if present */
X	if (i != (tres + 4) % 7) {	/* 1970/01/01 was Thu = 4 */
X	  *errReason = "bad wday";
X	  return -1;	/* ERR: bad WDAY */
X	  }
X
X#ifdef TRACING
Xprintf("YMD: %d %d %d, T=%ld\n",year,mon,day,tres);
X#endif
X      /*
X       * Now determine time.  If not given, default to zeros
X       * (since time is always the least global spec)
X       */
X      tres *= 86400L;			/* Get # seconds (24*60*60) */
X      if (tres / 86400L != t) {
X	*errReason = "overflow converting to seconds";
X	return -1;		/* ERR: overflow */
X	}
X      hour = min = sec = 0;
X      if (MAKETIME_GIVEN(tp->tm_hour))
X	hour = tp->tm_hour;
X      if (MAKETIME_GIVEN(tp->tm_min))
X	min  = tp->tm_min;
X      if (MAKETIME_GIVEN(tp->tm_sec))
X	sec  = tp->tm_sec;
X      if (60 <= (unsigned)min  ||  60 < (unsigned)sec) {
X	*errReason = "minutes/seconds out of range";
X	return -1;		/* ERR: MS out of range */
X	}
X      if (24 <= (unsigned)hour)
X	if (hour != 24 || (min + sec) != 0) {	/* Allow 24:00 */
X	  *errReason = "hour out of range";
X	  return -1;	/* ERR: H out of range */
X	  }
X
X      t = tres;
X      tres += sec + 60L*(zone + min + 60 * hour);
X
X#ifdef TRACING
Xprintf("HMS: %d %d %d T=%ld\n",hour,min,sec,tres);
X#endif
X
X      *errReason = "obscure overflow";
X      if (!localzone) {			/* check for overflow */
X#if 0 /* ugly atrocity, isn't even right */
X	  return (year < 0 ? (tres < 0 || 86400L <= tres) : tres < t)
X		      ?  -1  :  tres;
X#endif
X          if (year < 0) {
X	    if (tres < 0 || 86400L <= tres)
X	      return -1;
X            }
X#if 0
X          else {
X	    if (tres < t)
X	      return -1;
X	    }
X#endif
X	  return tres;
X        }
X      *errReason = NULL;
X
X      /* Check results; LT may have had a different GMT offset back then.  */
X      tp = localtime(&tres);
X      if (MAKETIME_GIVEN(atm->tm_sec)  &&  atm->tm_sec != tp->tm_sec) {
X	*errReason = "localtime mismatch";
X	return -1; /* If seconds don't match, we're in trouble.  */
X	}
X      if (!(
X	  (MAKETIME_GIVEN(atm->tm_min)  &&  atm->tm_min != tp->tm_min)  ||
X	  (MAKETIME_GIVEN(atm->tm_hour)  &&  atm->tm_hour != tp->tm_hour)  ||
X	  (MAKETIME_GIVEN(atm->tm_mday)  &&  atm->tm_mday != tp->tm_mday)  ||
X	  (MAKETIME_GIVEN(atm->tm_mon)  &&  atm->tm_mon != tp->tm_mon)  ||
X	  (MAKETIME_GIVEN(atm->tm_year)  &&  atm->tm_year != tp->tm_year)
X      ))
X	return tres; /* Everything matches.  */
X
X  } while (--attempts != 0);
X
X  *errReason = "too many attempts";
X  return -1;
X}
END_OF_FILE
if test 34282 -ne `wc -c <'partime.c'`; then
    echo shar: \"'partime.c'\" unpacked with wrong size!
fi
# end of 'partime.c'
fi
if test -f 'global.ht' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'global.ht'\"
else
echo shar: Extracting \"'global.ht'\" \(194 characters\)
sed "s/^X//" >'global.ht' <<'END_OF_FILE'
Xtypedef int BoolType;
X#define FALSE 0
X#define TRUE 1
X
X#include <stdio.h>
X#include <stdlib.h>
X#include <time.h>
X
X/* Define this if you are using function prototypes */
X#define FLG_PROTOTYPE TRUE
END_OF_FILE
if test 194 -ne `wc -c <'global.ht'`; then
    echo shar: \"'global.ht'\" unpacked with wrong size!
fi
# end of 'global.ht'
fi
if test -f 'partime.hf' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'partime.hf'\"
else
echo shar: Extracting \"'partime.hf'\" \(1370 characters\)
sed "s/^X//" >'partime.hf' <<'END_OF_FILE'
X#if !defined(PARTIME_HF)
X#define PARTIME_HF TRUE
X/*========================================================================
X * Copyright (C) Servio Corp. 1986-1994.  All Rights Reserved.
X *
X * Name - partime.hf.hf
X *
X * Description: 
X *
X * $Id: partime.hf,v 35.4 1994/04/30 08:52:04 darrel Exp $
X *
X * $Log: partime.hf,v $
X * Revision 35.4  1994/04/30  08:52:04  darrel
X * Added "cheat" line for quick dependency analysis.
X *
X * Revision 35.3  1993/12/31  00:04:53  darrel
X * purged the rcs log comment.
X *
X *========================================================================
X */
X
X/* no more includes. KEEP THIS LINE */
X
X#define PARTIME_TMNULL (-1) /* Items not given are given this value */
X
X#define MAKETIME_GIVEN(v) (0 <= (long)(v))/* Negative values are unspecified. */
X
X/* local time magic number -- see maketime() */
X#define MAKETIME_LOCALZONE (48 * 60)
X
X/*
X * Returns:
X *	0 if parsing failed
X *	else time values in specified TM structure and zone (unspecified values
X *		set to PARTIME_TMNULL)
X */
X
X#if defined(FLG_PROTOTYPE)
XBoolType ParseTime(const char *astr, register struct tm *atm, int *zone);
X#else
XBoolType ParseTime();
X#endif
X
X/* mktime.  returns -1 in case of error, and sets *errReason */
X#if defined(FLG_PROTOTYPE)
Xtime_t MakeTime(const struct tm *atm, int zone, const char **errReason);
X#else
Xtime_t MakeTime();
X#endif
X
X#endif /* PARTIME_HF */
END_OF_FILE
if test 1370 -ne `wc -c <'partime.hf'`; then
    echo shar: \"'partime.hf'\" unpacked with wrong size!
fi
# end of 'partime.hf'
fi
echo shar: End of shell archive.
exit 0

----[cut here]
-- 
D. Jason Penney (jason@slc.com), Servio Corporation
Work: 15400 NW Greenbrier Pkwy #280; Aloha, OR 97006; (503)690-3636 FAX:629-8556
Home: POB 5342; Aloha, OR 97006-0342; (503)848-9219
--
Technical Details
Message-ID: <jason.769193127@servio>
Path: arc1-ca.pugleaf.net!wupost!crcnis1.unl.edu!ace.mid.net!newsfeed.ksu.ksu.edu!moe.ksu.ksu.edu!vixen.cso.uiuc.edu!sdd.hp.com!ihnp4.ucsd.edu!library.ucla.edu!csulb.edu!csus.edu!netcom.com!netcomsv!slcgate!servio!servio!jason
References: <eadCpx95q.6xr@netcom.com>

Show Full Headers
Complete Article Headers
Newsgroups: netcom.programmers,alt.sources
Path: arc1-ca.pugleaf.net!wupost!crcnis1.unl.edu!ace.mid.net!newsfeed.ksu.ksu.edu!moe.ksu.ksu.edu!vixen.cso.uiuc.edu!sdd.hp.com!ihnp4.ucsd.edu!library.ucla.edu!csulb.edu!csus.edu!netcom.com!netcomsv!slcgate!servio!servio!jason
From: jason@slc.com (D. Jason Penney)
Subject: Re: wanted: public domain strptime(3)
Message-ID: <jason.769193127@servio>
Sender: news@slc.com (USENET News)
Nntp-Posting-Host: servio
Organization: Servio Corporation, Beaverton OR, USA
References: <eadCpx95q.6xr@netcom.com>
Date: 17 May 94 16:45:27 GMT
Lines: 1296