sources-request@mirror.UUCP (02/28/87)
Submitted by: Jef Poskanzer <unisoft!charming> Mod.sources: Volume 8, Issue 79 Archive-name: phoon #! /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 lexedit.sed # lexstring.c libtws.man parsetime.c phoon.c phoon.man tws.h # This archive created by # Jef Poskanzer (Paratheo-Anametamystikhood Of Eris Esoteric, Ada Lovelace Cabal) export PATH; PATH=/bin:$PATH echo shar: extracting "'README'" '(2571 characters)' if test -f 'README' then echo shar: will not over-write existing file "'README'" else sed 's/^X//' << \SHAR_EOF > 'README' XSecond distribution of phoon, deltime, and libtws - 24feb87. 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. I first X wrote this program in Pascal / TOPS-20 at CMU in 1979; I translated X it to Ratfor / Software Tools in 1981; and now it's in C / Unix*. 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* 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 I extended it somewhat and added the manual entry. 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* Unix is a virus from outer space. X X X .-- X .-- X .-' X .-'@ X /@@@ X ./ X /@@ o X /@@@@ X |@@@@@ X /@@@@@ Last Quarter + X | @@@@ 4 1:36:10 X |@ @@@ New Moon - X | 3 7:34:53 X \ . @ X | X \ @ X \ o X `\ X \ X `-. X `-. X `-- X `-- SHAR_EOF if test 2571 -ne "`wc -c < 'README'`" then echo shar: error transmitting "'README'" '(should have been 2571 characters)' fi fi # end of overwriting check echo shar: extracting "'Makefile'" '(2137 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 -DONECASE 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 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# The following amusing bullshit makes sure that ranlib X# gets executed if it is present, no matter which shell X# make uses. If there's a better way to do this, someone X# please tell me! X -if test -r /usr/bin/ranlib ; then ranlib libtws.a ; fi X -if ( -r /usr/bin/ranlib ) 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 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 2137 -ne "`wc -c < 'Makefile'`" then echo shar: error transmitting "'Makefile'" '(should have been 2137 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'" '(803 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* 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 X.SH NOTE X* Unix is a virus from outer space. SHAR_EOF if test 803 -ne "`wc -c < 'deltime.man'`" then echo shar: error transmitting "'deltime.man'" '(should have been 803 characters)' fi fi # end of overwriting check echo shar: extracting "'dtime.c'" '(9035 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 } X X X/* * Unix is a virus from outer space. */ SHAR_EOF if test 9035 -ne "`wc -c < 'dtime.c'`" then echo shar: error transmitting "'dtime.c'" '(should have been 9035 characters)' fi fi # end of overwriting check echo shar: extracting "'dtimep.lex'" '(7327 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}{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}"-")|(" "{MONTH}" ")|({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 X X X#ifdef SYS5 X/* Not all SYS5's have bzero( ). */ X Xbzero( b, length ) Xchar *b; Xint length; X { X while ( length-- > 0 ) X *b++ = 0; X } X#endif SHAR_EOF if test 7327 -ne "`wc -c < 'dtimep.lex'`" then echo shar: error transmitting "'dtimep.lex'" '(should have been 7327 characters)' fi fi # end of overwriting check echo shar: extracting "'lexedit.sed'" '(356 characters)' if test -f 'lexedit.sed' then echo shar: will not over-write existing file "'lexedit.sed'" else sed 's/^X//' << \SHAR_EOF > 'lexedit.sed' X2,/^extern int yylineno;$/c\ Xstatic int start_cond = 0;\ X#define BEGIN start_cond = X/^struct yysvf \*yyestate;$/,/^extern struct yysvf yysvec/d X/^# define YYNEWLINE /,/^int nstr;/d X/^while((nstr = yylook()/,/^if(yywrap()) /d X/^case -1:$/,/^fprintf(yyout,"bad switch yylook /c\ X default: return(0); X/^struct yysvf *yybgin = yysvec+1;$/d X/^int yylineno /,$d SHAR_EOF if test 356 -ne "`wc -c < 'lexedit.sed'`" then echo shar: error transmitting "'lexedit.sed'" '(should have been 356 characters)' fi fi # end of overwriting check echo shar: extracting "'lexstring.c'" '(3765 characters)' if test -f 'lexstring.c' then echo shar: will not over-write existing file "'lexstring.c'" else sed 's/^X//' << \SHAR_EOF > 'lexstring.c' X#include <stdio.h> X#include <ctype.h> X X#define YYLERR yysvec X#define YYTYPE int X#define YYLMAX 256 X Xstruct yysvf { X struct yywork *yystoff; X struct yysvf *yyother; X int *yystops; X}; X Xstruct yywork { X YYTYPE verify; X YYTYPE advance; X}; X Xextern int yyvstop[]; Xextern struct yywork yycrank[]; Xextern struct yysvf yysvec[]; Xextern struct yywork *yytop; Xextern char yymatch[]; Xextern char yyextra[]; X X#ifdef LEXDEBUG Xstatic int debug = 0; X#endif LEXDEBUG X Xlex_string( strptr, start_cond) X char **strptr; X int start_cond; X{ X register struct yysvf *state, **lsp; X register struct yywork *tran; X register int ch; X register char *cp = *strptr; X register int *found; X struct yysvf *yylstate[YYLMAX]; X X /* start off machines */ X lsp = yylstate; X state = yysvec+1+start_cond; X for (;;){ X# ifdef LEXDEBUG X if(debug) X fprintf(stderr,"state %d\n",state-yysvec-1); X# endif X tran = state->yystoff; X if(tran == yycrank) X /* may not be any transitions */ X if (state->yyother == 0 || X state->yyother->yystoff == yycrank) X break; X X ch = *cp++; X#ifdef ONECASE X if (isupper(ch) ) X ch = tolower(ch); X#endif ONECASE Xtryagain: X# ifdef LEXDEBUG X if(debug){ X fprintf(stderr,"char "); X allprint(ch); X putchar('\n'); X } X# endif X if ( tran > yycrank){ X tran += ch; X if (tran <= yytop && tran->verify+yysvec == state){ X if ((state = tran->advance+yysvec) == YYLERR){ X /* error transitions */ X --cp; X break; X } X *lsp++ = state; X goto contin; X } X X } else if(tran < yycrank) { X /* r < yycrank */ X tran = yycrank+(yycrank-tran) + ch; X# ifdef LEXDEBUG X if (debug) X fprintf(stderr,"compressed state\n"); X# endif X if(tran <= yytop && tran->verify+yysvec == state){ X if ((state = tran->advance+yysvec) == YYLERR) X /* error transitions */ X break; X X *lsp++ = state; X goto contin; X } X tran += (yymatch[ch] - ch); X# ifdef LEXDEBUG X if(debug){ X fprintf(stderr,"try fall back character "); X allprint(yymatch[ch]); X putchar('\n'); X } X# endif X if(tran <= yytop && tran->verify+yysvec == state){ X if(tran->advance+yysvec == YYLERR) X /* error transition */ X break; X X *lsp++ = state = tran->advance+yysvec; X goto contin; X } X } X if ((state = state->yyother) && X (tran = state->yystoff) != yycrank){ X# ifdef LEXDEBUG X if(debug) X fprintf(stderr,"fall back to state %d\n", X state-yysvec-1); X# endif X goto tryagain; X } else X break; X Xcontin: X# ifdef LEXDEBUG X if(debug){ X fprintf(stderr,"state %d char ",state-yysvec-1); X allprint(ch); X putchar('\n'); X } X# endif X ; X } X# ifdef LEXDEBUG X if(debug){ X fprintf(stderr,"stopped at %d with ",*(lsp-1)-yysvec-1); X allprint(ch); X putchar('\n'); X } X# endif X while (lsp-- > yylstate){ X if (*lsp != 0 && (found= (*lsp)->yystops) && *found > 0){ X if(yyextra[*found]){ X /* must backup */ X ch = -*found; X do { X while (*found && *found++ != ch) X ; X } while (lsp > yylstate && X (found = (*--lsp)->yystops)); X } X# ifdef LEXDEBUG X if(debug){ X fprintf(stderr,"\nmatch "); X for ( cp = *strptr; X cp <= ((*strptr)+(lsp-yylstate)); X cp++) X allprint( *cp ); X fprintf(stderr," action %d\n",*found); X } X# endif X *strptr += (lsp - yylstate + 1); X return(*found); X } X } X /* the string didn't match anything - if we're looking at X * eos, just return 0. Otherwise, bump the string pointer X * and return -1. X */ X# ifdef LEXDEBUG X if(debug) X fprintf(stderr,"\nno match\n"); X#endif LEXDEBUG X if ( **strptr ) { X (*strptr)++; X return (-1); X } X return (0); X} X X#ifdef LEXDEBUG Xallprint(c) X char c; X{ X if ( c < 32 ) { X putc( '^', stderr ); X c += 32; X } else if ( c == 127 ) { X putc( '^', stderr ); X c = '?'; X } X putc( c, stderr ); X} X#endif LEXDEBUG SHAR_EOF if test 3765 -ne "`wc -c < 'lexstring.c'`" then echo shar: error transmitting "'lexstring.c'" '(should have been 3765 characters)' fi fi # end of overwriting check echo shar: extracting "'libtws.man'" '(2241 characters)' if test -f 'libtws.man' then echo shar: will not over-write existing file "'libtws.man'" else sed 's/^X//' << \SHAR_EOF > 'libtws.man' X.TH libtws 3 "08 November 1986" X.SH NAME Xlibtws \- alternate date and time routines including parsing X.SH SYNOPSIS X.nf X.fc ^ ~ X.ta \w'char *dtimezone( offset, flags ); 'u Xinclude "tws.h" X.PP X^struct tws *dlocaltime( clock );~^/* local clock into tws */ Xlong *clock; X.PP X^struct tws *gmtime( clock );~^/* GMT clock into tws */ Xlong *clock; X.PP X^char *dtime( clock );~^/* clock into string */ Xlong *clock; X.PP X^long twclock( t );~^/* tws into clock */ Xstruct tws *t; X.PP X^long twjuliandate( t );~^/* tws into Julian day number */ Xstruct tws *t; X.PP X^struct tws *dparsetime( str );~^/* string into tws */ Xchar *str; X.PP X^char *dctime( t );~^/* tws into string */ Xstruct tws *t; X.PP X^char *dasctime( t, flags );~^/* tws into string */ Xstruct tws *t; Xint flags; X.PP X^char *dtimezone( offset, flags );~^/* timezone into string */ Xint offset, flags; X.PP X^char *dtwszone( t );~^/* tws's timezone into string */ Xstruct tws *t; X.PP X^char *dtimemow( );~^/* current time into string */ X.PP X^struct tws *dtwstime( );~^/* current time into tws */ X.PP X^void twscopy( tot, fromt );~^/* copy a tws */ Xstruct tws *tot, *fromt; X.PP X^int twsort( t1, t2 );~^/* compare two tws's */ Xstruct tws *t1, *t2; X.PP X^long twsubtract( t1, t2 );~^/* seconds between t2 and t1 */ Xstruct tws *t1, *t2; X.fi X.SH DESCRIPTION X.I Libtws Xis a fairly complete date/time library. XUnlike the standard Unix* date/time routines, X.I libtws Xwill parse date/time strings into internal form. XThe format for specifying date/time strings is pretty loose - basically Xthe same as the format for date/times in network mail. X.PP XMost of the routines do not use the Unix* "clock" time Xformat, and therefore are not limited to dates after 01 January 1970. XIn particular, twsubtract() lets you subtract two dates without Xconverting them to "clock" form. X.SH "SEE\ ALSO" X.IR ctime(3), X.IR time(3) X.SH AUTHOR XMost of X.I libtws Xcame from version 6.5 of the MH message Xhandling system, courtesy of Marshall Rose. XSome improvements (?) were added by Jef Poskanzer. X.SH BUGS XThe return values point to static data whose contents are overwritten Xby the next call. X.PP XThe basic Unix* time format (clock) only goes back to 1970, limiting Xapplications somewhat. X.SH NOTE X* Unix is a virus from outer space. SHAR_EOF if test 2241 -ne "`wc -c < 'libtws.man'`" then echo shar: error transmitting "'libtws.man'" '(should have been 2241 characters)' fi fi # end of overwriting check echo shar: extracting "'parsetime.c'" '(1756 characters)' if test -f 'parsetime.c' then echo shar: will not over-write existing file "'parsetime.c'" else sed 's/^X//' << \SHAR_EOF > 'parsetime.c' X/* parsetime.c - parse a date/time and display the results X Xver date who remarks X--- ------- --- ------------------------------------------------------------- X01A 15nov86 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 Xmain( argc, argv ) Xint argc; Xchar *argv[]; X { X char buf[200]; X int i; X struct tws *twp; X X strcpy( buf, "" ); X for ( i = 1; i < argc; i++ ) X { X if ( i > 1 ) X strcat( buf, " " ); X strcat( buf, argv[i] ); X } X X twp = dparsetime( buf ); X if ( twp == NULL ) X { X fprintf( stderr, "illegal date/time: %s\n", buf ); X exit( 1 ); X } X X printf( "dparsetime( \"%s\" ):\n", buf ); X printf( " tw_sec = %d\n", twp->tw_sec ); X printf( " tw_min = %d\n", twp->tw_min ); X printf( " tw_hour = %d\n", twp->tw_hour ); X printf( " tw_mday = %d\n", twp->tw_mday ); X printf( " tw_mon = %d\n", twp->tw_mon ); X printf( " tw_year = %d\n", twp->tw_year ); X printf( " tw_wday = %d\n", twp->tw_wday ); X printf( " tw_yday = %d\n", twp->tw_yday ); X printf( " tw_zone = %d\n", twp->tw_zone ); X printf( " tw_clock = %ld\n", twp->tw_clock ); X printf( " tw_flags = %d (0x%04x)\n", twp->tw_flags, twp->tw_flags ); X printf( "\n" ); X printf( "dasctime: %s\n", dasctime( twp, 0 ) ); X X exit( 0 ); X } SHAR_EOF if test 1756 -ne "`wc -c < 'parsetime.c'`" then echo shar: error transmitting "'parsetime.c'" '(should have been 1756 characters)' fi fi # end of overwriting check echo shar: extracting "'phoon.c'" '(12899 characters)' if test -f 'phoon.c' then echo shar: will not over-write existing file "'phoon.c'" else sed 's/^X//' << \SHAR_EOF > 'phoon.c' X/* phoon - show the phase of the moon X Xver date who remarks X--- ------- --- ------------------------------------------------------------- X01C 26jan87 JP Added backgrounds for 29 and 18 lines. X01B 28dec86 JP Added -l flag, and backgrounds for 19 and 24 lines. X01A 08nov86 JP Translated from the ratfor version of 12nov85, which itself X was translated from the Pascal version of 05apr79. X XCopyright (C) 1986 by Jeffrey A. 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 Jeffrey A. Poskanzer.\n"; X X X#include <stdio.h> X#include <math.h> X#include "tws.h" X X X/* Global defines and declarations. */ X X#define SECSPERMINUTE 60 X#define SECSPERHOUR (60 * SECSPERMINUTE) X#define SECSPERDAY (24 * SECSPERHOUR) X X#define PI 3.14159 X X#define DEFAULTNUMLINES 23 X#define MOONSTARTCOL 18 X#define QUARTERLITLEN 16 X#define QUARTERLITLENPLUSONE 17 X X/* If you change the aspect ratio, the canned backgrounds won't work. */ X#define ASPECTRATIO 0.5 X X/* Main program. */ X Xmain( argc, argv, envp ) Xint argc; Xchar *argv[], *envp[]; X { X struct tws t, *twp; X char buf[100]; X int numlines, argi, i; X char *usage = "usage: %s [ -l <lines> ] [ <date/time> ]\n"; X X /* Parge args. */ X argi = 1; X /* Check for -l flag. */ X numlines = DEFAULTNUMLINES; X if ( argc - argi >= 1 ) X { X if ( argv[argi][0] == '-' ) X { X if ( argv[argi][1] != 'l' | argv[argi][2] != '\0' ) X { X fprintf( stderr, usage, argv[0] ); X exit( 1 ); X } X else X { X if ( argc - argi < 2 ) X { X fprintf( stderr, usage, argv[0] ); X exit( 1 ); X } X if ( sscanf( argv[argi + 1], "%d", &numlines ) != 1 ) X { X fprintf( stderr, usage, argv[0] ); X exit( 1 ); X } X argi += 2; X } X } X } X X /* Figure out what date and time to use. */ X if ( argc - argi == 0 ) X { X /* No arguments present - use the current date and time. */ X twscopy( &t, dtwstime( ) ); X } X else if ( argc - argi == 1 || argc - argi == 2 || argc - argi == 3 ) X { X /* One, two, or three args - use them. */ X strcpy( buf, argv[argi] ); X if ( argc - argi > 1 ) X { X strcat( buf, " " ); X strcat( buf, argv[argi + 1] ); X if ( argc - argi > 2 ) X { X strcat( buf, " " ); X strcat( buf, argv[argi + 2] ); X } X } X twp = dparsetime( buf ); X if ( twp == NULL || twp -> tw_flags & TW_JUNK ) X { X fprintf( stderr, "illegal date/time: %s\n", buf ); X exit( 1 ); X } X twscopy( &t, twp ); X } X else X { X /* Too many args! */ X fprintf( stderr, usage, argv[0] ); X exit( 1 ); X } X X /* Pseudo-randomly decide what the moon is made of, and print it. */ X if ( twclock( dtwstime( ) ) % 17 == 3 ) X putmoon( &t, numlines, "GREENCHEESE" ); X else X putmoon( &t, numlines, "@" ); X X /* All done. */ X exit( 0 ); X } X X Xputmoon( t, numlines, atfiller ) Xstruct tws *t; Xint numlines; Xchar *atfiller; X { X struct tws twsanewmoon; X long secsynodic = 29*SECSPERDAY + 12*SECSPERHOUR + 44*SECSPERMINUTE + 3; X long secdiff, secphase; X int atflrlen, atflridx, lin, col, midlin, qlitidx; X float angphase, mcap, yrad, xrad, y, xright, xleft; X int colright, colleft, i; X char c; X X static char background18[18][37] = { X " .----------. ", X " .--' o . `--. ", X " .'@ @@@@@@ O . . `. ", X " .'@@ @@@@@@@@ @@@@ . `. ", X " .' . @@@@@@@@ @@@@@@ . `. ", X " / @@ o @@@@@@. @@@@ O @\\ ", X " |@@@@ @@@@@@ @@| ", X " / @@@@@ `.-. . @@@@@@@@ . @@\\", X " | @@@@ --`-' . o @@@@@@@ |", X " |@ @@ @@@@@@ @@@ |", X " \\ @@ @ . () @@ @@@@@ /", X " | @ @@@ @@@ @@@ | ", X " \\ . @@ @\\ . . @@ o / ", X " `. @@@@ _\\ / . o .' ", X " `. @@ ()--- .' ", X " `. / | . o .' ", X " `--./ . .--' ", X " `----------' "}; X X static char background19[19][39] = { X " .----------. ", X " .--' o . `--. ", X " .-'@ @@@@@@ O . . `-. ", X " .' @@ @@@@@@@@ @@@@ . `. ", X " / . @@@@@@@@ @@@@@@ . \\ ", X " /@@ o @@@@@@. @@@@ O @\\ ", X " /@@@@ @@@@@@ @@@\\ ", X " . @@@@@ `.-./ . @@@@@@@@ . @@ .", X " | @@@@ --`-' . @@@@@@@ |", X " |@ @@ ` o @@@@@@ @@@@ |", X " | @@ o @@ @@@@@@ |", X " ` . @ @@ () @@@ @@@@ '", X " \\ @@ @@@@ . @@ . o / ", X " \\ @@@@ @@\\ . o / ", X " \\ . @@ _\\ / . .-. / ", X " `. . ()--- `-' .' ", X " `-. ./ | . o .-' ", X " `--./ . .--' ", X " `----------' "}; X X static char background23[23][47] = { X " .------------. ", X " .--' o . . `--. ", X " .-' . O . . `-. ", X " .-'@ @@@@@@@ . @@@@@ `-. ", X " /@@@ @@@@@@@@@@@ @@@@@@@ . \\ ", X " ./ o @@@@@@@@@@@ @@@@@@@ . \\. ", X " /@@ o @@@@@@@@@@@. @@@@@@@ O \\ ", X " /@@@@ . @@@@@@@o @@@@@@@@@@ @@@ \\ ", X " |@@@@@ . @@@@@@@@@@@@@ o @@@@| ", X " /@@@@@ O `.-./ . @@@@@@@@@@@@ @@ \\", X " | @@@@ --`-' o @@@@@@@@ @@@@ |", X " |@ @@@ ` o . @@ . @@@@@@@ |", X " | @@ @ .-. @@@ @@@@@@@ |", X " \\ . @ @@@ `-' . @@@@ @@@@ o /", X " | @@ @@@@@ . @@ . | ", X " \\ @@@@ @\\@@ / . O . o . / ", X " \\ o @@ \\ \\ / . . / ", X " `\\ . .\\.-.___ . . .-. /' ", X " \\ `-' `-' / ", X " `-. o / | o O . .-' ", X " `-. / . . .-' ", X " `--. . .--' ", X " `------------' "}; X X static char background24[24][49] = { X " .------------. ", X " .---' o . . `---. ", X " .-' . O . . `-. ", X " .'@ @@@@@@@ . @@@@@ `. ", X " .'@@ @@@@@@@@@@@ @@@@@@@ . `. ", X " / o @@@@@@@@@@@ @@@@@@@ . \\ ", X " /@ o @@@@@@@@@@@. @@@@@@@ O \\ ", X " /@@@ . @@@@@@@o @@@@@@@@@@ @@@ \\ ", X " /@@@@@ . @@@@@@@@@@@@@ o @@@@ \\ ", X " |@@@@ O `.-./ . @@@@@@@@@@@@ @@ | ", X " / @@@@ --`-' o @@@@@@@@ @@@@ \\", X " |@ @@@ @ ` . @@ @@@@@@@ |", X " | @ o @ @@@@@@@ |", X " \\ @@ .-. @@@ @@@@ o /", X " | . @ @@@ `-' . @@@@ | ", X " \\ @@ @@@@@ . @@ . / ", X " \\ @@@@ @\\@@ / . O . o . / ", X " \\ o @@ \\ \\ / . . / ", X " \\ . .\\.-.___ . . .-. / ", X " `. `-' `-' .' ", X " `. o / | o O . .' ", X " `-. / . . .-' ", X " `---. . .---' ", X " `------------' "}; X static char background29[29][59] = { X " .--------------. ", X " .---' o . `---. ", X " .-' . O . . `-. ", X " .-' @@@@@@ . `-. ", X " .'@@ @@@@@@@@@@@ @@@@@@@ . `. ", X " .'@@@ @@@@@@@@@@@@@@ @@@@@@@@@ `. ", X " /@@@ o @@@@@@@@@@@@@@ @@@@@@@@@ O \\ ", X " / @@@@@@@@@@@@@@ @ @@@@@@@@@ @@ . \\ ", X " /@ o @@@@@@@@@@@ . @@ @@@@@@@@@@@ @@ \\ ", X " /@@@ . @@@@@@ o @ @@@@@@@@@@@@@ o @@@@ \\ ", X " /@@@@@ @ . @@@@@@@@@@@@@@ @@@@@ \\ ", X " |@@@@@ O `.-./ . . @@@@@@@@@@@@@ @@@ | ", X " / @@@@@ --`-' o @@@@@@@@@@@ @@@ . \\", X " |@ @@@@ . @ @ ` @ @@ . @@@@@@ |", X " | @@ o @@ . @@@@@@ |", X " | . @ @ @ o @@ o @@@@@@. |", X " \\ @ @ @ .-. @@@@ @@@ /", X " | @ @ @ `-' . @@@@ . . | ", X " \\ . o @ @@@@ . @@ . . / ", X " \\ @@@ @@@@@@ . o / ", X " \\ @@@@@ @@\\@@ / O . / ", X " \\ o @@@ \\ \\ / __ . . .--. / ", X " \\ . . \\.-.--- `--' / ", X " `. `-' . .' ", X " `. o / | ` O . .' ", X " `-. / | o .-' ", X " `-. . . .-' ", X " `---. . .---' ", X " `--------------' "}; X X static char qlits[8][16] = { X "New Moon + ", X "First Quarter +", X "Full Moon + ", X "Last Quarter + ", X "First Quarter -", X "Full Moon - ", X "Last Quarter - ", X "New Moon - " }; X X X /* Find the length of the atfiller string. */ X atflrlen = strlen( atfiller ); X X /* Convert a new moon date from a string to a tws. */ X twscopy( &twsanewmoon, dparsetime( "05jan81 23:24:00 PST" ) ); X X /* Subtract the new moon date from the desired date to get the interval X since the new moon. */ X secdiff = twsubtract( t, &twsanewmoon ); X X /* Figure out the phase - the interval since the last new moon. */ X secphase = secdiff % secsynodic; X if ( secphase < 0L ) X secphase += secsynodic; /* fucking mathematician language designers */ X angphase = (float) secphase / (float) secsynodic * 2.0 * PI; X mcap = -cos( angphase ); X X /* Figure out how big the moon is. */ X yrad = numlines / 2.0; X xrad = yrad / ASPECTRATIO; X X /* Figure out some other random stuff. */ X midlin = numlines / 2; X qlitidx = angphase / PI * 2.0; X X /* Now output the moon, a slice at a time. */ X atflridx = 0; X for ( lin = 0; lin < numlines; lin = lin + 1 ) X { X /* Compute the edges of this slice. */ X y = lin + 0.5 - yrad; X xright = xrad * sqrt( 1.0 - ( y * y ) / ( yrad * yrad ) ); X xleft = -xright; X if ( angphase >= 0.0 && angphase < PI ) X xleft = mcap * xleft; X else X xright = mcap * xright; X colleft = (int) (xrad + 0.5) + (int) (xleft + 0.5); X colright = (int) (xrad + 0.5) + (int) (xright + 0.5); X X /* Now output the slice. */ X for ( i = 0; i < colleft; i++ ) X putchar( ' ' ); X for ( col = colleft; col <= colright; col = col + 1 ) X { X switch ( numlines ) X { X case 18: X c = background18[lin][col]; X break; X case 19: X c = background19[lin][col]; X break; X case 23: X c = background23[lin][col]; X break; X case 24: X c = background24[lin][col]; X break; X case 29: X c = background29[lin][col]; X break; X default: X c = '@'; X } X if ( c != '@' ) X putchar( c ); X else X { X putchar( atfiller[atflridx] ); X atflridx = ( atflridx + 1 ) % atflrlen; X } X } X X /* Output the end-of-line information, if any. */ X if ( lin == midlin - 2 ) X { X putchar( '\t' ); X putchar( '\t' ); X fputs( qlits[qlitidx], stdout ); X } X else if ( lin == midlin - 1) X { X putchar( '\t' ); X putchar( '\t' ); X putseconds( secphase % (secsynodic / 4) ); X } X else if ( lin == midlin ) X { X putchar( '\t' ); X putchar( '\t' ); X fputs( qlits[qlitidx + 4], stdout ); X } X else if ( lin == midlin + 1 ) X { X putchar( '\t' ); X putchar( '\t' ); X putseconds( (secsynodic - secphase) % (secsynodic / 4) ); X } X X putchar( '\n' ); X } X X } X X Xputseconds( secs ) Xlong secs; X { X long days, hours, minutes; X X days = secs / SECSPERDAY; X secs = secs - days * SECSPERDAY; X hours = secs / SECSPERHOUR; X secs = secs - hours * SECSPERHOUR; X minutes = secs / SECSPERMINUTE; X secs = secs - minutes * SECSPERMINUTE; X X printf( "%ld %2ld:%02ld:%02ld", days, hours, minutes, secs ); X } SHAR_EOF if test 12899 -ne "`wc -c < 'phoon.c'`" then echo shar: error transmitting "'phoon.c'" '(should have been 12899 characters)' fi fi # end of overwriting check echo shar: extracting "'phoon.man'" '(696 characters)' if test -f 'phoon.man' then echo shar: will not over-write existing file "'phoon.man'" else sed 's/^X//' << \SHAR_EOF > 'phoon.man' X.TH phoon 1 "08 November 1986" X.SH NAME Xphoon \- show the PHase of the mOON X.SH SYNOPSIS X.in +.5i X.ti -.5i Xphoon \%[ -l <lines> ] \%[ <date> ] X.in -.5i X.SH DESCRIPTION X.I Phoon Xdisplays the phase of the moon, either currently Xor at a specified date / time. XUnlike other such programs, which just tell you how long since first quarter Xor something like that, phoon X.I shows Xyou the phase with a cute little picture. XYou can vary the size of the picture with the -l flag, but only some Xsizes have pictures defined - other sizes use @'s. X.SH "SEE\ ALSO" X.IR deltime(1), X.IR libtws(3) X.SH AUTHOR XJef Poskanzer X.SH BUGS XThe algorithm for determining the phase is very simple, but not very Xaccurate. SHAR_EOF if test 696 -ne "`wc -c < 'phoon.man'`" then echo shar: error transmitting "'phoon.man'" '(should have been 696 characters)' fi fi # end of overwriting check echo shar: extracting "'tws.h'" '(2290 characters)' if test -f 'tws.h' then echo shar: will not over-write existing file "'tws.h'" else sed 's/^X//' << \SHAR_EOF > 'tws.h' X/* tws.h - header file for libtws date/time library */ X X X/* Definition of the tws data structure. */ X Xstruct tws { X int tw_sec; X int tw_min; X int tw_hour; X X int tw_mday; X int tw_mon; X int tw_year; X X int tw_wday; X int tw_yday; X X int tw_zone; X X long tw_clock; X X int tw_flags; X#define TW_NULL 0x0000 X#define TW_SDAY 0x0007 /* how day-of-week was determined */ X#define TW_SNIL 0x0000 /* not given */ X#define TW_SEXP 0x0001 /* explicitly given */ X#define TW_SIMP 0x0002 /* implicitly given */ X#define TW_DST 0x0010 /* daylight savings time */ X#define TW_ZONE 0x0020 /* use numeric timezones only */ X#define TW_JUNK 0x0040 /* date string contained junk */ X}; X X X/* Declarations of routines. */ X Xvoid twscopy( ); X /* twscopy( &totws, &fromtws ) copies a tws */ Xint twsort( ); X /* twsort( &tws1, &tws2 ) compares two tws's: 1 means tws1 is X later; -1 means tws1 is earlier; 0 means they are equal */ Xlong twclock( ); X /* twclock( &tws ) turns a tws into a time(3)-style clock value */ Xlong twjuliandate( ); X /* twjuliandate( &tws ) returns the Julian day number of a tws */ Xlong twsubtract( ); X /* twsubtract( &tws1, &tws2 ) returns seconds of difference */ X X/* These routines are functionally similar to the ctime(3) routines X in the standard Unix library. */ Xchar *dctime( ); X /* dctime( &tws ) returns a string for the date/time passed in */ Xstruct tws *dlocaltime( ); X /* dlocaltime( &clock ) turns a time(3) clock value into a tws */ Xstruct tws *dgmtime( ); X /* dgmtime( &clock ) turns a time(3) clock value into a tws */ Xchar *dasctime( ); X /* dasctime( &tws, flags ) turns a tws into a string */ Xchar *dtimezone( ); X /* dtimezone( offset, flags ) returns the name of the time zone */ X Xchar *dtimenow( ); X /* dtimenow( ) returns a string for the current date/time */ X Xstruct tws *dparsetime( ); X /* dparsetime( &str ) turns a string into a tws */ X Xstruct tws *dtwstime( ); X /* dtwstime( ) returns a tws for the current date/time */ X X#ifdef ATZ X#define dtime(cl) dasctime( dlocaltime( cl ), TW_NULL ) X#else ATZ X#define dtime(cl) dasctime( dlocaltime( cl ), TW_ZONE ) X#endif ATZ X X#define dtwszone(tw) dtimezone( tw -> tw_zone, tw -> tw_flags ) X X Xextern char *tw_dotw[], *tw_ldotw[], *tw_moty[]; SHAR_EOF if test 2290 -ne "`wc -c < 'tws.h'`" then echo shar: error transmitting "'tws.h'" '(should have been 2290 characters)' fi fi # end of overwriting check # End of shell archive exit 0