[net.sources] PHOON, part one of two.

jef@unisoft.UUCP (Jef Poskanzer) (11/20/86)

First distribution of phoon, deltime, and libtws - 15nov86.


This package contains two programs and a library:

    phoon - program to display the PHase of the mOON.  Unlike other
    such programs, which just tell you how long since first quarter
    or something like that, phoon *shows* you the phase with a little
    picture.  I've put an example at the end of this file.

    deltime - program to subtract date/times.  Tells you the difference
    between two date/times, or between now and a specified date/time.
    I once used this to help a friend quit smoking - every time she
    logged in, the computer told her how many days since her last
    cigarette.  I also use it in my .login, to tell me how old I am.

    libtws - date/time library.  Unlike the standard Unix(R)
    date/time routines, libtws lets you parse a date/time string
    into internal form.  Most of this library came from version
    6.5 of the MH message handling system, courtesy of Marshall Rose.


Files in this distribution:

    README		this
    Makefile		guess
    deltime.c		source for time subtraction tool
    deltime.man		manual for time subtraction tool
    dtime.c		source for most of the time routines
    dtimep.lex		source for time-parsing routine
    lexedit.sed		script to modify output of lex
    lexstring.c		front end for time-parsing routine
    libtws.man		manual for time library
    parsetime.c		source for test program
    phoon.c		source for phase of moon program
    phoon.man		manual for phase of moon program
    tws.h		include file for time library


Unpack the files, edit Makefile and change the options to suit,
make, and enjoy!  I've tested this stuff under 4.2 BSD, 4.3 BSD,
and System V rel 2.  Nevertheless, I'm sure bugs remain.  Feedback
is welcome - send bug reports, enhancements, checks, money orders,
etc. to the addresses below.


     Jef Poskanzer, UniSoft Systems, Berkeley
	 unisoft!jef@ucbvax.Berkeley.Edu
	      ...ucbvax!unisoft!jef
		  (415)644-1230

                  ------------.
             .--'  o     . .   `--.
          .-'   .    O   .       . `-.
        -'@   @@@@@@@   .  @@@@@      `-.
       @@@  @@@@@@@@@@@   @@@@@@@   .    \
     /    o @@@@@@@@@@@   @@@@@@@       . \.
    @@  o   @@@@@@@@@@@.   @@@@@@@   O      \
   @@@@   .   @@@@@@@o    @@@@@@@@@@     @@@ \
   @@@@@               . @@@@@@@@@@@@@ o @@@@|
  @@@@@  O  `.-./  .      @@@@@@@@@@@@    @@  \		First Quarter +
   @@@@    --`-'       o     @@@@@@@@ @@@@    |		5 22:33:24
  @ @@@        `    o      .  @@   . @@@@@@@  |		Full Moon -    
         @@            .-.     @@@   @@@@@@@  |		1 10:37:39
    . o        @@@     `-'   . @@@@   @@@@  o /
         @@   @@@@@ .           @@   .       |
        @@@@  @\@@    /  .  O    .     o   . /
      o  @@     \ \  /         .    .       /
     \     .    .\.-.___   .      .   .-. /'
                  `-'                `-' /
        -.   o   / |     o    O   .   .-'
          `-.   /     .       .    .-'
             `--.       .      .--'
                  ------------'


#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	README
#	Makefile
#	deltime.c
#	deltime.man
#	dtime.c
#	dtimep.lex
# This archive created: Mon Nov 17 11:55:54 1986
# By:	Jef Poskanzer ()
export PATH; PATH=/bin:$PATH
echo shar: extracting "'README'" '(3041 characters)'
if test -f 'README'
then
	echo shar: will not over-write existing file "'README'"
else
sed 's/^X//' << \SHAR_EOF > 'README'
XFirst distribution of phoon, deltime, and libtws - 15nov86.
X
X
XThis package contains two programs and a library:
X
X    phoon - program to display the PHase of the mOON.  Unlike other
X    such programs, which just tell you how long since first quarter
X    or something like that, phoon *shows* you the phase with a little
X    picture.  I've put an example at the end of this file.
X
X    deltime - program to subtract date/times.  Tells you the difference
X    between two date/times, or between now and a specified date/time.
X    I once used this to help a friend quit smoking - every time she
X    logged in, the computer told her how many days since her last
X    cigarette.  I also use it in my .login, to tell me how old I am.
X
X    libtws - date/time library.  Unlike the standard Unix(R)
X    date/time routines, libtws lets you parse a date/time string
X    into internal form.  Most of this library came from version
X    6.5 of the MH message handling system, courtesy of Marshall Rose.
X
X
XFiles in this distribution:
X
X    README		this
X    Makefile		guess
X    deltime.c		source for time subtraction tool
X    deltime.man		manual for time subtraction tool
X    dtime.c		source for most of the time routines
X    dtimep.lex		source for time-parsing routine
X    lexedit.sed		script to modify output of lex
X    lexstring.c		front end for time-parsing routine
X    libtws.man		manual for time library
X    parsetime.c		source for test program
X    phoon.c		source for phase of moon program
X    phoon.man		manual for phase of moon program
X    tws.h		include file for time library
X
X
XUnpack the files, edit Makefile and change the options to suit,
Xmake, and enjoy!  I've tested this stuff under 4.2 BSD, 4.3 BSD,
Xand System V rel 2.  Nevertheless, I'm sure bugs remain.  Feedback
Xis welcome - send bug reports, enhancements, checks, money orders,
Xetc. to the addresses below.
X
X
X     Jef Poskanzer, UniSoft Systems, Berkeley
X	 unisoft!jef@ucbvax.Berkeley.Edu
X	      ...ucbvax!unisoft!jef
X		  (415)644-1230
X
X                  ------------.
X             .--'  o     . .   `--.
X          .-'   .    O   .       . `-.
X        -'@   @@@@@@@   .  @@@@@      `-.
X       @@@  @@@@@@@@@@@   @@@@@@@   .    \
X     /    o @@@@@@@@@@@   @@@@@@@       . \.
X    @@  o   @@@@@@@@@@@.   @@@@@@@   O      \
X   @@@@   .   @@@@@@@o    @@@@@@@@@@     @@@ \
X   @@@@@               . @@@@@@@@@@@@@ o @@@@|
X  @@@@@  O  `.-./  .      @@@@@@@@@@@@    @@  \		First Quarter +
X   @@@@    --`-'       o     @@@@@@@@ @@@@    |		5 22:33:24
X  @ @@@        `    o      .  @@   . @@@@@@@  |		Full Moon -    
X         @@            .-.     @@@   @@@@@@@  |		1 10:37:39
X    . o        @@@     `-'   . @@@@   @@@@  o /
X         @@   @@@@@ .           @@   .       |
X        @@@@  @\@@    /  .  O    .     o   . /
X      o  @@     \ \  /         .    .       /
X     \     .    .\.-.___   .      .   .-. /'
X                  `-'                `-' /
X        -.   o   / |     o    O   .   .-'
X          `-.   /     .       .    .-'
X             `--.       .      .--'
X                  ------------'
SHAR_EOF
if test 3041 -ne "`wc -c < 'README'`"
then
	echo shar: error transmitting "'README'" '(should have been 3041 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'Makefile'" '(1873 characters)'
if test -f 'Makefile'
then
	echo shar: will not over-write existing file "'Makefile'"
else
sed 's/^X//' << \SHAR_EOF > 'Makefile'
X# Makefile for phoon, deltime, parsetime, and libtws (stolen from mh).
X
X
X# Valid options:
X#   BSD42      Set this if your system is BSD 4.2 or later.
X#   SYS5       Set this if your system is System V.
X#   EUROPE     Makes nn/nn/nn mean dd/mm/yy instead of mm/dd/yy.
X#   ATZ        This has something to do with alpha-numeric time zones.
X#   DSTXXX     This has something to do with daylight savings time.
X#   HUJI       I don't
X#   INETONLY           know what
X#   LEXDEBUG                     the rest of these
X#   ONECASE                                        do.
XOPTIONS	=	-DBSD42 -DATZ -DDSTXXX
X
X
XCC      =	cc
XCFLAGS  =	-O $(OPTIONS)
XLDFLAGS =	-ns
X
X.SUFFIXES:	.man .cat
X.man.cat:
X		nroff -h -man $< > $@
X
X
Xall:		phoon phoon.cat deltime deltime.cat parsetime libtws.cat
X
X
Xphoon:		phoon.o libtws.a
X		$(CC) $(LDFLAGS) -o phoon phoon.o -lm libtws.a
X
Xphoon.o:	phoon.c tws.h
X
X
Xdeltime:	deltime.o libtws.a
X		$(CC) $(LDFLAGS) -o deltime deltime.o libtws.a
X
Xdeltime.o:	deltime.c tws.h
X
X
Xparsetime:	parsetime.o libtws.a
X		$(CC) $(LDFLAGS) -o parsetime parsetime.o libtws.a
X
Xparsetime.o:	parsetime.c tws.h
X
X
Xlibtws.a:	dtime.o dtimep.o lexstring.o
X		ar r libtws.a dtime.o dtimep.o lexstring.o
X		ranlib libtws.a
X
X
Xdtime.o:	dtime.c tws.h
X
X
Xdtimep.o:	dtimep.c tws.h
X
Xdtimep.c:	dtimep.lex
X		lex -nt dtimep.lex | sed -f lexedit.sed > dtimep.c
X
X
Xlexstring.o:	lexstring.c
X		$(CC) $(CFLAGS) -c -DONECASE lexstring.c
X
X
Xclean:
X		-rm -f dtimep.c *.o libtws.a phoon deltime parsetime *.cat phoon.shar core
X
Xphoon.shar:	phoon.shar1 phoon.shar2
X
Xphoon.shar1:	README Makefile deltime.c deltime.man dtime.c dtimep.lex
X		shar -v -c -p X README Makefile deltime.c deltime.man dtime.c dtimep.lex > phoon.shar1
X
Xphoon.shar2:	lexedit.sed lexstring.c libtws.man parsetime.c phoon.c phoon.man tws.h
X		shar -v -c -p X lexedit.sed lexstring.c libtws.man parsetime.c phoon.c phoon.man tws.h > phoon.shar2
SHAR_EOF
if test 1873 -ne "`wc -c < 'Makefile'`"
then
	echo shar: error transmitting "'Makefile'" '(should have been 1873 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'deltime.c'" '(2156 characters)'
if test -f 'deltime.c'
then
	echo shar: will not over-write existing file "'deltime.c'"
else
sed 's/^X//' << \SHAR_EOF > 'deltime.c'
X/* deltime.c - subtract date/times
X
Xver  date   who remarks
X--- ------- --- -------------------------------------------------------------
X01B 15nov86 JP  Modified to use twsubtract().
X01A 08nov86 JP  Written.
X
XCopyright (C) 1986 by Jef Poskanzer.  Permission to use, copy,
Xmodify, and distribute this software and its documentation for any
Xpurpose and without fee is hereby granted, provided that this copyright
Xnotice appear in all copies and in all supporting documentation.  No
Xrepresentation is made about the suitability of this software for any
Xpurpose.  It is provided "as is" without express or implied warranty.
X
X*/
X
Xstatic char copyright[] = "\nCopyright (C) 1986 by Jef Poskanzer.\n";
X
X
X#include "tws.h"
X#include <stdio.h>
X
X#define SECSPERMINUTE 60
X#define SECSPERHOUR (60 * SECSPERMINUTE)
X#define SECSPERDAY (24 * SECSPERHOUR)
X
Xmain( argc, argv )
Xint argc;
Xchar *argv[];
X    {
X    struct tws tws1, tws2, *twp;
X    long delta, days, hours, minutes, secs;
X    char *illdt = "illegal date/time: %s\n";
X
X    if ( argc == 2 )
X	{
X	twp = dparsetime( argv[1] );
X	if ( twp == NULL || twp -> tw_flags & TW_JUNK )
X	    {
X	    fprintf( stderr, illdt, argv[1] );
X	    exit( 1 );
X	    }
X	twscopy( &tws1, twp );
X	twscopy( &tws2, dtwstime( ) );
X	}
X    else if ( argc == 3 )
X	{
X	twp = dparsetime( argv[1] );
X	if ( twp == NULL || twp -> tw_flags & TW_JUNK )
X	    {
X	    fprintf( stderr, illdt, argv[1] );
X	    exit( 1 );
X	    }
X	twscopy( &tws1, twp );
X	twp = dparsetime( argv[2] );
X	if ( twp == NULL || twp -> tw_flags & TW_JUNK )
X	    {
X	    fprintf( stderr, illdt, argv[2] );
X	    exit( 1 );
X	    }
X	twscopy( &tws2, twp );
X	}
X    else
X	{
X	fprintf( stderr, "usage:  %s  <time>  [ <time2> ]\n", argv[0] );
X	exit( 1 );
X	}
X    
X    delta = twsubtract( &tws2, &tws1 );
X    if ( delta < 0 )
X	{
X	printf( "-" );
X	delta = -delta;
X	}
X
X    days = delta / SECSPERDAY;
X    delta = delta - days * SECSPERDAY;
X    hours = delta / SECSPERHOUR;
X    delta = delta - hours * SECSPERHOUR;
X    minutes = delta / SECSPERMINUTE;
X    delta = delta - minutes * SECSPERMINUTE;
X    secs = delta;
X
X    printf( "%ld %2ld:%02ld:%02ld\n", days, hours, minutes, secs );
X
X    exit( 0 );
X    }
SHAR_EOF
if test 2156 -ne "`wc -c < 'deltime.c'`"
then
	echo shar: error transmitting "'deltime.c'" '(should have been 2156 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'deltime.man'" '(760 characters)'
if test -f 'deltime.man'
then
	echo shar: will not over-write existing file "'deltime.man'"
else
sed 's/^X//' << \SHAR_EOF > 'deltime.man'
X.TH example 1 "08 November 1986"
X.SH NAME
Xdeltime \- compute a delta time
X.SH SYNOPSIS
X.in +.5i
X.ti -.5i
Xdeltime  <time>  \%[ <time2> ]
X.in -.5i
X.SH DESCRIPTION
X.PP
X.I Deltime
Xcomputes the elapsed time between now and a
Xspecified date/time, or between two specified date/times.
XThe format for specifying date/times is pretty loose - basically
Xthe same as the format for date/times in network mail.
XJust be careful to put them in quotes if they contain spaces.
XThe output format is dddd hh:mm:ss.
X.PP
XTimes earlier than 1970
X.I can
Xbe handled, because the internal Unix(R) time format is not used.
XHowever, time spans greater than 66 years
X.I cannot
Xbe handled, because that's 2**31 seconds.
X.SH "SEE\ ALSO"
X.IR phoon(1),
X.IR libtws(3)
X.SH AUTHOR
XJef Poskanzer
SHAR_EOF
if test 760 -ne "`wc -c < 'deltime.man'`"
then
	echo shar: error transmitting "'deltime.man'" '(should have been 760 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'dtime.c'" '(8989 characters)'
if test -f 'dtime.c'
then
	echo shar: will not over-write existing file "'dtime.c'"
else
sed 's/^X//' << \SHAR_EOF > 'dtime.c'
X/* dtime.c - routines to do ``ARPA-style'' time structures
X
Xver  date   who remarks
X--- ------- --- -------------------------------------------------------------
X01B 15nov86 JP  Thouroughly hacked by Jef Poskanzer.
X01A ??????? MTR Original version from the MH 6.5 distribution, courtesy
X	          of Marshall Rose.
X
X*/
X
X
X#include "tws.h"
X#include <stdio.h>
X#include <sys/types.h>
X#include <time.h>
X#ifdef  SYS5
X#include <string.h>
X#else SYS5
X#include <strings.h>
X#include <sys/timeb.h>
X#endif SYS5
X
X#ifdef	SYS5
Xextern int  daylight;
Xextern long timezone;
Xextern char *tzname[];
X#endif	SYS5
X
X/*  */
X
X#define	abs(a) ( a >= 0 ? a : -a )
X
Xchar *tw_moty[] = {
X    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
X    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL };
X
Xchar *tw_dotw[] = {
X    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL };
X
Xchar *tw_ldotw[] = {
X    "Sunday", "Monday", "Tuesday", "Wednesday",
X    "Thursday", "Friday", "Saturday", NULL };
X
X/*  */
X
Xstatic struct zone
X    {
X    char *std;
X    char *dst;
X    int shift;
X    }
X    zones[] = {
X	"GMT", "BST", 0,
X	"EST", "EDT", -5,
X	"CST", "CDT", -6,
X	"MST", NULL, -7,
X	"PST", "PDT", -8,
X	"A", NULL, -1,
X	"B", NULL, -2,
X	"C", NULL, -3,
X	"D", NULL, -4,
X	"E", NULL, -5,
X	"F", NULL, -6,
X	"G", NULL, -7,
X	"H", NULL, -8,
X	"I", NULL, -9,
X	"K", NULL, -10,
X	"L", NULL, -11,
X	"M", NULL, -12,
X	"N", NULL, 1,
X#ifndef	HUJI
X	"O", NULL, 2,
X#else	HUJI
X	"JST", "JDT", 2,
X#endif	HUJI
X	"P", NULL, 3,
X	"Q", NULL, 4,
X	"R", NULL, 5,
X	"S", NULL, 6,
X	"T", NULL, 7,
X	"U", NULL, 8,
X	"V", NULL, 9,
X	"W", NULL, 10,
X	"X", NULL, 11,
X	"Y", NULL, 12,
X	NULL };
X
X#define CENTURY 19
X
Xlong time( );
Xstruct tm *localtime( );
X
X/*  */
X
Xchar *dtimenow( )
X    {
X    long clock;
X
X    (void) time( &clock );
X    return ( dtime( &clock ) );
X    }
X
X
Xchar *
Xdctime( tw )
Xstruct tws *tw;
X    {
X    static char buffer[25];
X
X    if ( tw == NULL )
X	return ( NULL );
X
X    (void) sprintf( buffer, "%.3s %.3s %02d %02d:%02d:%02d %.4d\n",
X	    tw_dotw[tw -> tw_wday], tw_moty[tw -> tw_mon], tw -> tw_mday,
X	    tw -> tw_hour, tw -> tw_min, tw -> tw_sec,
X	    tw -> tw_year >= 100 ? tw -> tw_year : 1900 + tw -> tw_year );
X
X    return ( buffer );
X    }
X
X/*  */
X
Xstruct tws *
Xdtwstime( )
X    {
X    long clock;
X
X    (void) time( &clock );
X    return ( dlocaltime( &clock ) );
X    }
X
X
Xstruct tws *
Xdlocaltime( clock )
Xlong *clock;
X    {
X    register struct tm *tm;
X#ifndef SYS5
X    struct timeb tb;
X#endif not SYS5
X    static struct tws tw;
X
X    if ( clock == NULL )
X	return ( NULL );
X    tw.tw_flags = TW_NULL;
X
X    tm = localtime( clock );
X    tw.tw_sec = tm -> tm_sec;
X    tw.tw_min = tm -> tm_min;
X    tw.tw_hour = tm -> tm_hour;
X    tw.tw_mday = tm -> tm_mday;
X    tw.tw_mon = tm -> tm_mon;
X    tw.tw_year = tm -> tm_year;
X    tw.tw_wday = tm -> tm_wday;
X    tw.tw_yday = tm -> tm_yday;
X    if ( tm -> tm_isdst )
X	tw.tw_flags |= TW_DST;
X#ifndef  SYS5
X    ftime( &tb );
X    tw.tw_zone = -tb.timezone;
X#else   SYS5
X    tzset( );
X    tw.tw_zone = -(timezone / 60);
X#endif  SYS5
X    tw.tw_flags &= ~TW_SDAY;
X    tw.tw_flags |= TW_SEXP;
X    tw.tw_clock = *clock;
X
X    return ( &tw );
X    }
X
X
Xstruct tws *
Xdgmtime( clock )
Xlong *clock;
X    {
X    register struct tm *tm;
X    static struct tws tw;
X
X    if ( clock == NULL )
X	return ( NULL );
X    tw.tw_flags = TW_NULL;
X
X    tm = gmtime( clock );
X    tw.tw_sec = tm -> tm_sec;
X    tw.tw_min = tm -> tm_min;
X    tw.tw_hour = tm -> tm_hour;
X    tw.tw_mday = tm -> tm_mday;
X    tw.tw_mon = tm -> tm_mon;
X    tw.tw_year = tm -> tm_year;
X    tw.tw_wday = tm -> tm_wday;
X    tw.tw_yday = tm -> tm_yday;
X    if ( tm -> tm_isdst )
X	tw.tw_flags |= TW_DST;
X    tw.tw_zone = 0;
X    tw.tw_flags &= ~TW_SDAY;
X    tw.tw_flags |= TW_SEXP;
X    tw.tw_clock = *clock;
X
X    return( &tw );
X    }
X
X/*  */
X
Xchar *
Xdasctime( tw, flags )
Xstruct tws *tw;
Xint flags;
X    {
X    static char buffer[80], result[80];
X
X    if ( tw == NULL )
X	return ( NULL );
X
X    (void) sprintf( buffer, "%02d %s %02d %02d:%02d:%02d %s",
X	    tw -> tw_mday, tw_moty[tw -> tw_mon], tw -> tw_year,
X	    tw -> tw_hour, tw -> tw_min, tw -> tw_sec,
X	    dtimezone( tw -> tw_zone, tw -> tw_flags | flags ) );
X
X    if ( (tw -> tw_flags & TW_SDAY) == TW_SEXP )
X	(void) sprintf( result, "%s, %s", tw_dotw[tw -> tw_wday], buffer );
X    else
X	if ( (tw -> tw_flags & TW_SDAY) == TW_SNIL )
X	    (void) strcpy( result, buffer );
X	else
X	    (void) sprintf( result, "%s (%s)", buffer, tw_dotw[tw -> tw_wday] );
X
X    return ( result );
X    }
X
X/*  */
X
Xchar *
Xdtimezone( offset, flags )
Xint offset, flags;
X    {
X    register int hours, mins;
X    register struct zone *z;
X    static char buffer[10];
X
X    if ( offset < 0 )
X	{
X	mins = -((-offset) % 60);
X	hours = -((-offset) / 60);
X	}
X    else
X	{
X	mins = offset % 60;
X	hours = offset / 60;
X	}
X
X    if ( !(flags & TW_ZONE) && mins == 0 )
X	for ( z = zones; z -> std; z++ )
X	    if ( z -> shift == hours )
X		return ( z -> dst && (flags & TW_DST) ? z -> dst : z -> std );
X
X#ifdef	DSTXXX
X    if ( flags & TW_DST )
X	hours += 1;
X#endif	DSTXXX
X    (void) sprintf( buffer, "%s%02d%02d",
X	    offset < 0 ? "-" : "+", abs( hours ), abs( mins ) );
X    return ( buffer );
X    }
X
X/*  */
X
Xvoid
Xtwscopy( tb, tw )
Xstruct tws *tb, *tw;
X    {
X#ifdef	notdef
X    tb -> tw_sec = tw -> tw_sec;
X    tb -> tw_min = tw -> tw_min;
X    tb -> tw_hour = tw -> tw_hour;
X    tb -> tw_mday = tw -> tw_mday;
X    tb -> tw_mon = tw -> tw_mon;
X    tb -> tw_year = tw -> tw_year;
X    tb -> tw_wday = tw -> tw_wday;
X    tb -> tw_yday = tw -> tw_yday;
X    tb -> tw_zone = tw -> tw_zone;
X    tb -> tw_clock = tw -> tw_clock;
X    tb -> tw_flags = tw -> tw_flags;
X#else	not notdef
X    *tb = *tw;
X#endif	not notdef
X    }
X
X
Xint
Xtwsort( tw1, tw2 )
Xstruct tws *tw1, *tw2;
X    {
X    register long c1, c2;
X
X    (void) twclock( tw1 );
X    (void) twclock( tw2 );
X
X    return ( (c1 = tw1 -> tw_clock) > (c2 = tw2 -> tw_clock) ? 1
X	    : c1 == c2 ? 0 : -1 );
X    }
X
X/*  */
X
X
X/* Julian day number of the Unix clock's origin, 01 Jan 1970. */
X#define JD1970 2440587L
X
X
Xlong
Xtwjuliandate( tw )
Xstruct tws *tw;
X    {
X    register int mday, mon, year;
X    register long a, b;
X    double jd;
X
X    if ( (mday = tw -> tw_mday) < 1 || mday > 31 ||
X	    (mon = tw -> tw_mon + 1) < 1 || mon > 12 ||
X	    (year = tw -> tw_year) < 1 || year > 10000 )
X	return ( -1L );
X    if ( year < 100 )
X	year += CENTURY * 100;
X
X    if ( mon == 1 || mon == 2 )
X	{
X	--year;
X	mon += 12;
X	}
X    if ( year < 1583 )
X	return ( -1L );
X    a = year / 100;
X    b = 2 - a + a / 4;
X    b += (long) ( (double) year * 365.25 );
X    b += (long) ( 30.6001 * ( (double) mon + 1.0 ) );
X    jd = mday + b + 1720994.5;
X    return ( (long) jd );
X    }
X
X
Xlong
Xtwsubdayclock( tw )
Xstruct tws *tw;
X    {
X    register int i, sec, min, hour;
X    register long result;
X
X    if ( (sec = tw -> tw_sec) < 0 || sec > 59 ||
X	    (min = tw -> tw_min) < 0 || min > 59 ||
X	    (hour = tw -> tw_hour) < 0 || hour > 23 )
X	return ( -1L );
X
X    result = ( hour * 60 + min ) * 60 + sec;
X    result -= 60 * tw -> tw_zone;
X    if ( tw -> tw_flags & TW_DST )
X	result -= 60 * 60;
X
X    return ( result );
X    }
X
X
Xlong
Xtwclock( tw )
Xstruct tws *tw;
X    {
X    register long jd, sdc, result;
X
X    if ( tw -> tw_clock != 0L )
X	return ( tw -> tw_clock );
X
X    if ( ( jd = twjuliandate( tw ) ) == -1L )
X	return ( tw -> tw_clock = -1L );
X    if ( ( sdc = twsubdayclock( tw ) ) == -1L )
X	return ( tw -> tw_clock = -1L );
X
X    result = ( jd - JD1970 ) * 24 * 60 * 60 + sdc;
X
X    return ( tw -> tw_clock = result );
X    }
X
X/*  */
X
X/*** twsubtract - subtract tw2 from tw1, returning result in seconds
X
XThe point of this routine is that using twclock( tw1 ) - twclock( tw2 )
Xwould limit you to dates after the Unix Epoch ( 01 January 1970 ).  This
Xroutine avoids that limit.  However, because the result is represented
Xby 32 bits, it is still limited to a span of two billion seconds, which is
Xabout 66 years.
X
X*/
X
Xlong
Xtwsubtract( tw1, tw2 )
Xstruct tws *tw1, *tw2;
X    {
X    register long jd1, jd2, sdc1, sdc2, result;
X
X    if ( ( jd1 = twjuliandate( tw1 ) ) == -1L )
X	return ( 0L );
X    if ( ( sdc1 = twsubdayclock( tw1 ) ) == -1L )
X	return ( 0L );
X
X    if ( ( jd2 = twjuliandate( tw2 ) ) == -1L )
X	return ( 0L );
X    if ( ( sdc2 = twsubdayclock( tw2 ) ) == -1L )
X	return ( 0L );
X    
X    result = ( jd1 - jd2 ) * 24 * 60 * 60 + ( sdc1 - sdc2 );
X
X    return ( result );
X    }
X
X/*  */
X
X/*
X *    Simple calculation of day of the week.  Algorithm used is Zeller's
X *    congruence.  Currently, we assume if tw -> tw_year < 100
X *    then the century is CENTURY.
X */
X
Xset_dotw( tw )
Xstruct tws *tw;
X    {
X    register int month, day, year, century;
X
X    month = tw -> tw_mon - 1;
X    day = tw -> tw_mday;
X    year = tw -> tw_year % 100;
X    century = tw -> tw_year >= 100 ? tw -> tw_year / 100 : CENTURY;
X
X    if ( month <= 0 )
X	{
X	month += 12;
X	if ( --year < 0 )
X	    {
X	    year += 100;
X	    century--;
X	    }
X	}
X
X    tw -> tw_wday =
X	((26 * month - 2) / 10 + day + year + year / 4
X	    - 3 * century / 4 + 1) % 7;
X
X    tw -> tw_flags &= ~TW_SDAY;
X    tw -> tw_flags |= TW_SIMP;
X    }
SHAR_EOF
if test 8989 -ne "`wc -c < 'dtime.c'`"
then
	echo shar: error transmitting "'dtime.c'" '(should have been 8989 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'dtimep.lex'" '(7171 characters)'
if test -f 'dtimep.lex'
then
	echo shar: will not over-write existing file "'dtimep.lex'"
else
sed 's/^X//' << \SHAR_EOF > 'dtimep.lex'
X%e 2000
X%p 5000
X%n 1000
X%a 4000
X%START	Z
Xsun	(sun(day)?)
Xmon	(mon(day)?)
Xtue	(tue(sday)?)
Xwed	(wed(nesday)?)
Xthu	(thu(rsday)?)
Xfri	(fri(day)?)
Xsat	(sat(urday)?)
X
XDAY	({sun}|{mon}|{tue}|{wed}|{thu}|{fri}|{sat})
X
Xjan	(jan(uary)?)
Xfeb	(feb(ruary)?)
Xmar	(mar(ch)?)
Xapr	(apr(il)?)
Xmay	(may)
Xjun	(jun(e)?)
Xjul	(jul(y)?)
Xaug	(aug(ust)?)
Xsep	(sep(tember)?)
Xoct	(oct(ober)?)
Xnov	(nov(ember)?)
Xdec	(dec(ember)?)
X
XMONTH	({jan}|{feb}|{mar}|{apr}|{may}|{jun}|{jul}|{aug}|{sep}|{oct}|{nov}|{dec})
X
Xw	([ \t]*)
XW	([ \t]+)
XD	([0-9]?[0-9])
Xd	[0-9]
X%{
X/* dtimep.lex - routines to do ``ARPA-style'' time parsing
X
Xver  date   who remarks
X--- ------- --- -------------------------------------------------------------
X01B 15nov86 JP  Thouroughly hacked by Jef Poskanzer.
X01A ??????? MTR Original version from the MH 6.5 distribution, courtesy
X	          of Marshall Rose.
X
X*/
X
X#include "tws.h"
X#include <ctype.h>
X#include <sys/types.h>
X#include <time.h>
X#ifdef SYS5
X#include <string.h>
X#else SYS5
X#include <strings.h>
X#include <sys/timeb.h>
X#endif SYS5
X
X#ifdef SYS5
Xextern int  daylight;
Xextern long timezone;
Xextern char *tzname[];
X#endif SYS5
X
X/*
X * Table to convert month names to numeric month.  We use the
X * fact that the low order 5 bits of the sum of the 2nd & 3rd
X * characters of the name is a hash with no collisions for the 12
X * valid month names.  (The mask to 5 bits maps any combination of
X * upper and lower case into the same hash value).
X */
Xstatic int month_map[] = {
X	0,
X	6,	/* 1 - Jul */
X	3,	/* 2 - Apr */
X	5,	/* 3 - Jun */
X	0,
X	10,	/* 5 - Nov */
X	0,
X	1,	/* 7 - Feb */
X	11,	/* 8 - Dec */
X	0,
X	0,
X	0,
X	0,
X	0,
X	0,
X	0,	/*15 - Jan */
X	0,
X	0,
X	0,
X	2,	/*19 - Mar */
X	0,
X	8,	/*21 - Sep */
X	0,
X	9,	/*23 - Oct */
X	0,
X	0,
X	4,	/*26 - May */
X	0,
X	7 };	/*28 - Aug */
X/*
X * Same trick for day-of-week using the hash function
X *  (c1 & 7) + (c2 & 4)
X */
Xstatic int day_map[] = {
X	0,
X	0,
X	0,
X	6,	/* 3 - Sat */
X	4,	/* 4 - Thu */
X	0,
X	5,	/* 6 - Fri */
X	0,	/* 7 - Sun */
X	2,	/* 8 - Tue */
X	1	/* 9 - Mon */,
X	0,
X	3 };	/*11 - Wed */
X#define SETDAY tw.tw_wday= day_map[(cp[0] & 7) + (cp[1] & 4)];\
X		tw.tw_flags |= TW_SEXP;\
X		cp += 2;
X#define SETMONTH tw.tw_mon = month_map[(cp[0] + cp[1]) & 0x1f]; gotdate++;\
X		 cp += 2;\
X		 SKIPD;
X#define CVT1OR2 (i=(*cp++ - '0'), isdigit(*cp)? i*10 + (*cp++ - '0') : i)
X#define CVT2 ( (*cp++ - '0')*10 + (*cp++ - '0') )
X#define CVT3 ( ( (*cp++ - '0')*10 + (*cp++ - '0') )*10 + (*cp++ - '0') )
X#define CVT4 ( ( ( (*cp++ - '0')*10 + (*cp++ - '0') )*10 + (*cp++ - '0') )*10 + (*cp++ - '0') )
X#define SKIPD while ( ! isdigit( *cp++ ) ) ; --cp;
X#define ZONE(x) tw.tw_zone=(x);
X#define ZONED(x) tw.tw_zone=(x); tw.tw_flags |= TW_DST;
X#define LC(c) (isupper( c ) ? tolower( c ) : ( c ))
X%}
X%%
X%{
Xstruct tws *
Xdparsetime( str )
Xchar *str;
X    {
X    register int i;
X    static struct tws tw;
X    register char *cp;
X    register int gotdate = 0;
X#ifndef SYS5
X    struct timeb	tb;
X#endif not SYS5
X    long clock;
X
X    start_cond = 0;
X
X    /* Zero out the struct. */
X    bzero( (char *) &tw, sizeof tw );
X
X    /* Set default time zone. */
X#ifndef SYS5
X    ftime( &tb );
X    tw.tw_zone = -tb.timezone;
X#else SYS5
X    tzset( );
X    tw.tw_zone = -(timezone / 60);
X#endif SYS5
X
X    for ( ; ; )
X	switch ( cp = str, lex_string( &str, start_cond ) )
X	    {
X	    case -1:
X		if ( ! gotdate )
X			return ( NULL );
X		tw.tw_flags |= TW_JUNK;
X		/* fall through */
X	    case 0:
X		if ( tw.tw_year == 0 )
X		    {
X		    /* Set default year. */
X		    time( &clock );
X		    tw.tw_year = localtime( &clock ) -> tm_year;
X		    }
X		return ( &tw );
X
X%}
X{DAY}","?{w}				SETDAY;
X"("{DAY}")"(","?)			cp++, SETDAY;
X
X{D}"/"{D}"/"{D}?{d}{d}{w}		{
X#ifdef EUROPE
X					tw.tw_mday = CVT1OR2; cp++;
X					tw.tw_mon  = CVT1OR2 - 1; cp++;
X#else EUROPE
X					tw.tw_mon = CVT1OR2 - 1; cp++;
X					tw.tw_mday  = CVT1OR2; cp++;
X#endif EUROPE
X					for ( i = 0; isdigit( *cp ); )
X						i = i * 10 + (*cp++ - '0');
X					tw.tw_year = i;
X					gotdate++;
X					}
X{D}"/"{D}{w}				{
X#ifdef EUROPE
X					tw.tw_mday = CVT1OR2; cp++;
X					tw.tw_mon  = CVT1OR2 - 1;
X#else EUROPE
X					tw.tw_mon = CVT1OR2 - 1; cp++;
X					tw.tw_mday  = CVT1OR2;
X#endif EUROPE
X					gotdate++;
X					}
X{D}"-"?{MONTH}"-"?{D}?{d}{d}({W}at)?{w}	|
X{D}" "{MONTH}" "{D}?{d}{d}({W}at)?{w}	{
X					tw.tw_mday = CVT1OR2;
X					while ( ! isalpha( *cp++ ) )
X						;
X					SETMONTH;
X					for ( i = 0; isdigit( *cp ); )
X						i = i * 10 + (*cp++ - '0');
X					tw.tw_year = i;
X					gotdate++;
X					}
X{D}"-"?{MONTH}({W}at)?{w}		{
X					tw.tw_mday = CVT1OR2;
X					while ( ! isalpha( *cp++ ) )
X						;
X					SETMONTH;
X					gotdate++;
X					}
X{MONTH}{W}{D}","{W}{D}?{d}{d}{w}	{
X					cp++;
X					SETMONTH;
X					tw.tw_mday = CVT1OR2;
X					SKIPD;
X					for ( i = 0; isdigit( *cp ); )
X						i = i * 10 + (*cp++ - '0');
X					tw.tw_year = i;
X					gotdate++;
X					}
X{MONTH}{W}{D}{w}			{
X					cp++;
X					SETMONTH;
X					tw.tw_mday = CVT1OR2;
X					gotdate++;
X					}
X
X{D}:{D}:{D}({w}am)?{w}			{
X					tw.tw_hour = CVT1OR2; cp++;
X					tw.tw_min  = CVT1OR2; cp++;
X					tw.tw_sec  = CVT1OR2;
X					BEGIN Z;
X					}
X{D}:{D}:{D}{w}pm{w}			{
X					tw.tw_hour = CVT1OR2 + 12; cp++;
X					tw.tw_min  = CVT1OR2; cp++;
X					tw.tw_sec  = CVT1OR2;
X					BEGIN Z;
X					}
X{D}:{D}({w}am)?{w}			{
X					tw.tw_hour = CVT1OR2; cp++;
X					tw.tw_min  = CVT1OR2;
X					BEGIN Z;
X					}
X{D}:{D}{w}pm{w}				{
X					tw.tw_hour = CVT1OR2 + 12; cp++;
X					tw.tw_min  = CVT1OR2;
X					BEGIN Z;
X					}
X[0-2]{d}{d}{d}{d}{d}{w}			{
X					tw.tw_hour = CVT1OR2;
X					tw.tw_min  = CVT1OR2;
X					tw.tw_sec  = CVT1OR2;
X					BEGIN Z;
X					}
X[0-2]{d}{d}{d}{w}			{
X					tw.tw_hour = CVT1OR2;
X					tw.tw_min  = CVT1OR2;
X					BEGIN Z;
X					}
X<Z>"-"?ut				ZONE(0 * 60);
X<Z>"-"?gmt				ZONE(0 * 60);
X<Z>"-"?jst				ZONE(2 * 60);
X<Z>"-"?jdt				ZONED(2 * 60);
X<Z>"-"?est				ZONE(-5 * 60);
X<Z>"-"?edt				ZONED(-5 * 60);
X<Z>"-"?cst				ZONE(-6 * 60);
X<Z>"-"?cdt				ZONED(-6 * 60);
X<Z>"-"?mst				ZONE(-7 * 60);
X<Z>"-"?mdt				ZONED(-7 * 60);
X<Z>"-"?pst				ZONE(-8 * 60);
X<Z>"-"?pdt				ZONED(-8 * 60);
X<Z>"-"?nst				ZONE(-(3 * 60 + 30));
X<Z>"-"?ast				ZONE(-4 * 60);
X<Z>"-"?adt				ZONED(-4 * 60);
X<Z>"-"?yst				ZONE(-9 * 60);
X<Z>"-"?ydt				ZONED(-9 * 60);
X<Z>"-"?hst				ZONE(-10 * 60);
X<Z>"-"?hdt				ZONED(-10 * 60);
X<Z>"-"?bst				ZONED(-1 * 60);
X<Z>[a-i]				tw.tw_zone = 60 * (('a'-1) - LC (*cp));
X<Z>[k-m]				tw.tw_zone = 60 * ('a' - LC (*cp));
X<Z>[n-y]				tw.tw_zone = 60 * (LC (*cp) - 'm');
X<Z>"+"[0-1]{d}{d}{d}			{
X					cp++;
X					tw.tw_zone = ((cp[0] * 10 + cp[1])
X						     -('0' * 10   + '0'))*60
X						    +((cp[2] * 10 + cp[3])
X						     -('0' * 10   + '0'));
X#ifdef DSTXXX
X					zonehack (&tw);
X#endif DSTXXX
X					cp += 4;
X					}
X<Z>"-"[0-1]{d}{d}{d}			{
X					cp++;
X					tw.tw_zone = (('0' * 10   + '0')
X						     -(cp[0] * 10 + cp[1]))*60
X						    +(('0' * 10   + '0')
X						     -(cp[2] * 10 + cp[3]));
X#ifdef DSTXXX
X					zonehack (&tw);
X#endif DSTXXX
X					cp += 4;
X					}
X
X<Z>{W}{d}{d}{d}{d}			{
X					SKIPD;
X					tw.tw_year = CVT4;
X					}
X\n	|
X{W}	;
X%%
X
X#ifdef DSTXXX
Xstatic
Xzonehack( tw )
Xregister struct tws *tw;
X    {
X    register struct tm *tm;
X
X    if ( twclock( tw ) == -1L )
X	return;
X
X    tm = localtime( &tw -> tw_clock );
X    if ( tm -> tm_isdst )
X	{
X	tw -> tw_flags |= TW_DST;
X	tw -> tw_zone -= 60;
X	}
X    }
X#endif DSTXXX
SHAR_EOF
if test 7171 -ne "`wc -c < 'dtimep.lex'`"
then
	echo shar: error transmitting "'dtimep.lex'" '(should have been 7171 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0