cute verbose "date"
Fred Fish
fnf at unisoft.UUCP
Fri Jan 25 13:13:35 AEST 1985
[...........]
Another cute little program from an old DECUS C distribution.
This one puts out something of the form:
"Today is Thursday, the twenty-fourth day of January, nineteen
eighty-five. The time is twelve minutes and forty seconds after seven
PM, Daylight Savings Time. The moon is new."
--Fred
#--------CUT---------CUT---------CUT---------CUT--------#
#########################################################
# #
# This is a shell archive file. To extract files: #
# #
# 1) Make a directory for the files. #
# 2) Write a file, such as "file.shar", containing #
# this archive file into the directory. #
# 3) Type "sh file.shar". Do not use csh. #
# #
#########################################################
#
#
echo Extracting Makefile:
sed 's/^Z//' >Makefile <<\STUNKYFLUFF
Z#
Z# Makefile for very verbose date command (today).
Z
ZOBJ = datetx.o moontx.o nbrtxt.o timetx.o today.o
Z
Ztoday: $(OBJ)
Z $(CC) -o $@ $(OBJ)
Z
STUNKYFLUFF
set `sum Makefile`
if test 62527 != $1
then
echo Makefile: Checksum error. Is: $1, should be: 62527.
fi
#
#
echo Extracting datetx.c:
sed 's/^Z//' >datetx.c <<\STUNKYFLUFF
Z#
Z/*
Z * Convert Date to Readable Format.
Z *
Z * Synopsis:
Z *
Z * char *datetxt(buffer, year, month, day);
Z * char *buffer; -- Output string goes here
Z * int year; -- Year, 1979 = 1979
Z * int month; -- Month, January = 1
Z * int day; -- Day, 1 = 1
Z *
Z * The readable date will be written into the outpub buffer, terminated by
Z * a null byte. datetxt returns a pointer to the null byte.
Z *
Z * External routines called:
Z *
Z * nbrtxt (Number to ascii conversion)
Z * copyst (String copy routine)
Z */
Z
Zextern char *nbrtxt();
Zextern char *copyst();
Zextern char *datetxt();
Z
Zstatic char *daynames[] = {
Z "Sunday", /* Sunday is day zero */
Z "Monday",
Z "Tuesday",
Z "Wednesday",
Z "Thursday",
Z "Friday",
Z "Saturday",
Z};
Z
Zstatic char *monthnames[] = {
Z "?Nomember?", /* Illegal month */
Z "January",
Z "February",
Z "March",
Z "April",
Z "May",
Z "June",
Z "July",
Z "August",
Z "September",
Z "October",
Z "November",
Z "December",
Z};
Z
Zchar *datetxt(buffer, year, month, day)
Zchar *buffer; /* Output goes here */
Zint year; /* Year, 1979 = 1979 */
Zint month; /* Month of year, Jan = 1 */
Zint day; /* Day in the month 1 = 1 */
Z/*
Z * Output the date in readable format:
Z * Tuesday, the third of October
Z */
Z{
Z register char *op; /* Output pointer */
Z
Z op = buffer; /* Setup output pointer */
Z op = copyst(op, daynames[dayofweek(year, month, day)]);
Z op = copyst(op, ", the ");
Z op = nbrtxt(op, day, 1);
Z op = copyst(op, " day of ");
Z op = copyst(op, monthnames[(month < 0 || month > 12) ? 0 : month]);
Z op = copyst(op, ", ");
Z if (year < 1000 || year >= 2000)
Z return(nbrtxt(op, year, 0));
Z else {
Z op = nbrtxt(op, year/100, 0);
Z op = copyst(op, " ");
Z if ((year = year % 100) == 0)
Z return(copyst(op, "hundred"));
Z else
Z return(nbrtxt(op, year, 0));
Z }
Z}
Z
Zdayofweek(year, month, day)
Zint year; /* Year, 1978 = 1978 */
Zint month; /* Month, January = 1 */
Zint day; /* Day of month, 1 = 1 */
Z/*
Z * Return the day of the week on which this date falls: Sunday = 0.
Z * Note, this routine is valid only for the Gregorian calender.
Z */
Z{
Z register int yearfactor;
Z
Z yearfactor = year + (month - 14)/12;
Z return (( (13 * (month + 10 - (month + 10)/13*12) - 1)/5
Z + day + 77 + 5 * (yearfactor % 100)/4
Z + yearfactor / 400
Z - yearfactor / 100 * 2) % 7);
Z}
STUNKYFLUFF
set `sum datetx.c`
if test 65180 != $1
then
echo datetx.c: Checksum error. Is: $1, should be: 65180.
fi
#
#
echo Extracting moontx.c:
sed 's/^Z//' >moontx.c <<\STUNKYFLUFF
Z#
Z/*
Z * Phase of the Moon Conversion.
Z *
Z * Synopsis
Z *
Z * char *moontxt(buffer, year, month, day)
Z * char *buffer; -- Output goes here.
Z * int year; -- Year 1979 = 1979
Z * int month; -- Month Jan. = 1
Z * int day; -- Day 1 = 1
Z *
Z * The phase of the moon (in readable ascii) is written into the buffer,
Z * followed by a null. The routine returns a pointer to the trailing null.
Z *
Z * External routines called:
Z *
Z * copyst (String copy routine)
Z */
Z
Zextern char *copyst(); /* String output routine */
Z
Zstatic char *phasetxt[] = {
Z "new",
Z "waxing crescent",
Z "in its first quarter",
Z "waxing gibbous",
Z "full",
Z "waning gibbous",
Z "in its last quarter",
Z "waning crescent"
Z};
Z
Zstatic int day_year[] = { /* Days in year for each month */
Z -1, -1, 30, 58, 89, 119, 150, 180, 211, 241, 272, 303, 333
Z}; /* Note: Jan. 1 will equal zero */
Z
Zchar *moontxt(buffer, year, month, day)
Zchar *buffer; /* Where to put the text */
Zint year; /* Year, 1978 = 1978 */
Zint month; /* Month, Jan = 1 */
Zint day; /* Day, 1 = 1 */
Z/*
Z * Output the phase of the moon for the given year, month, day.
Z * The routine calculates the year's epact (the age of the moon on Jan 1.),
Z * adds this to the number of days in the year, and calculates the phase
Z * of the moon for this date.
Z *
Z * In the algorithm:
Z *
Z * diy Is the day of the year - 1 (i.e., Jan 1 is day 0).
Z *
Z * golden Is the number of the year in the Mentonic cycle, used to
Z * determine the position of the calender moon.
Z *
Z * epact Is the age of the calender moon (in days) at the beginning
Z * of the year. To calculate epact, two century-based
Z * corrections are applied:
Z * Gregorian: (3 * cent)/4 - 12
Z * is the number of years such as 1700, 1800 when
Z * leap year was not held.
Z * Clavian: (((8 * cent) + 5) / 25) - 5
Z * is a correction to the Mentonic cycle of about
Z * 8 days evry 2500 years. Note that this will
Z * overflow 16 bits in the year 409600. Beware.
Z *
Z * The algorithm is accurate for the Gregorian calender only.
Z *
Z * The magic numbers used in the phase calculation are as follows:
Z * 29.5 The moon's period in days.
Z * 177 29.5 scaled by 6
Z * 22 (29.5 / 8) scaled by 6 (this gets the phase)
Z * 11 ((29.5 / 8) / 2) scaled by 6
Z *
Z * Theoretically, this should yield a number in the range 0 .. 7. However,
Z * two days per year, things don't work out too well.
Z *
Z * Epact is calculated by the algorithm given in Knuth vol. 1 (calculation
Z * of Easter). See also the article on Calenders in the Encyclopaedia
Z * Britannica and Knuth's algorithm in CACM April 1962, page 209.
Z */
Z{
Z int phase; /* Moon phase */
Z register int cent; /* Century number (1979 = 20) */
Z register int epact; /* Age of the moon on Jan. 1 */
Z register int diy; /* Day in the year */
Z int golden; /* Moon's golden number */
Z
Z if (month < 0 || month > 12) month = 0; /* Just in case */
Z diy = day + day_year[month]; /* Day in the year */
Z if ((month > 2) && ((year % 4 == 0) &&
Z ((year % 400 == 0) || (year % 100 != 0))))
Z diy++; /* Leapyear fixup */
Z cent = (year / 100) + 1; /* Century number */
Z golden = (year % 19) + 1; /* Golden number */
Z epact = ((11 * golden) + 20 /* Golden number */
Z + (((8 * cent) + 5) / 25) - 5 /* 400 year cycle */
Z - (((3 * cent) / 4) - 12)) % 30;/* Leap year correction */
Z if (epact <= 0)
Z epact += 30; /* Age range is 1 .. 30 */
Z if ((epact == 25 && golden > 11) || epact == 24)
Z epact++;
Z /*
Z * Calculate the phase, using the magic numbers defined above.
Z * Note that (phase and 7) is equivalent to (phase mod 8) and
Z * is needed on two days per year (when the algorithm yields 8).
Z */
Z phase = (((((diy + epact) * 6) + 11) % 177) / 22) & 7;
Z return(copyst(buffer, phasetxt[phase]));
Z}
STUNKYFLUFF
set `sum moontx.c`
if test 12622 != $1
then
echo moontx.c: Checksum error. Is: $1, should be: 12622.
fi
#
#
echo Extracting nbrtxt.c:
sed 's/^Z//' >nbrtxt.c <<\STUNKYFLUFF
Z#
Z/*
Z * Integer to Readable ASCII Conversion Routine.
Z *
Z * Synopsis:
Z *
Z * char *nbrtxt(buffer, value, ordinal)
Z * char *buffer; -- The output buffer
Z * int value; -- The number to output
Z * int ordinal; -- Non-zero for ordinal number
Z *
Z *
Z * The value is converted to a readable number and put in the output
Z * buffer (null-terminated). A pointer to the first free location
Z * in the buffer (i.e., the null) is returned. The ordinal
Z * flag distinguishes between cardinal and ordinal numbers:
Z *
Z * nbrtxt(buffer, 1, 0) = "one"
Z * nbrtxt(buffer, 1, 1) = "first"
Z *
Z * The longest output string is:
Z *
Z * Twenty-seven thousand, three hundred and seventy-seventh.
Z *
Z *
Z *
Z * Copy a String
Z *
Z * Synopsis
Z *
Z * char *copyst(out, in)
Z * char *out; -- The output string
Z * char *in; -- The input string
Z *
Z * The input string is copied into the output string. Copyst returns
Z * a pointer to the null trailer.
Z *
Z */
Z
Zextern char *nbrtxt();
Zextern char *copyst();
Z
Zstatic char *cardinal[] = {
Z "zero",
Z "one",
Z "two",
Z "three",
Z "four",
Z "five",
Z "six",
Z "seven",
Z "eight",
Z "nine",
Z "ten",
Z "eleven",
Z "twelve",
Z "thirteen",
Z "fourteen",
Z "fifteen",
Z "sixteen",
Z "seventeen",
Z "eighteen",
Z "nineteen"
Z};
Z
Zstatic char *ordinal[] = {
Z "zeroth",
Z "first",
Z "second",
Z "third",
Z "fourth",
Z "fifth",
Z "sixth",
Z "seventh",
Z "eighth",
Z "ninth",
Z "tenth",
Z "eleventh",
Z "twelfth"
Z};
Z
Zstatic char *twenties[] = {
Z "twen",
Z "thir",
Z "for",
Z "fif",
Z "six",
Z "seven",
Z "eigh",
Z "nine"
Z};
Z
Zchar *nbrtxt(buffer, datum, ordflag)
Zchar *buffer; /* Output string buffer */
Zint datum; /* what to translate */
Zint ordflag; /* 0 if cardinal, 1 if ordinal */
Z/*
Z * Translate a number to a readable text string, punctuation and all.
Z * If ordflag is non-zero, ordinal numbers ("first, second") will
Z * be generated, rather than cardinal ("one, two").
Z * Note: nbrtxt() is recursive.
Z */
Z{
Z
Z register int value;
Z register char *op;
Z
Z op = buffer;
Z value = datum;
Z if (value < 0) {
Z op = copyst(op, "minus ");
Z value = (-value);
Z if (value < 0) { /* Hack -32768 */
Z op = copyst(op, twenties[1]);
Z value = 2768;
Z }
Z }
Z if (value >= 1000) {
Z op = nbrtxt(op, value/1000, 0);
Z op = copyst(op, " thousand");
Z value = value % 1000;
Z if (value == 0) goto exit;
Z op = copyst(op, (value >= 100) ? ", " : " and ");
Z }
Z if (value >= 100) {
Z op = copyst(op, cardinal[value/100]);
Z op = copyst(op, " hundred");
Z value = value % 100;
Z if (value == 0) goto exit;
Z op = copyst(op, " ");
Z }
Z if (value >= 20) {
Z if (value == 90 && ordflag)
Z return(copyst(op, "nintieth"));
Z op = copyst(op, twenties[(value-20) / 10]);
Z value = value % 10;
Z if (value == 0) {
Z return(copyst(op, (ordflag) ? "tieth" : "ty"));
Z }
Z op = copyst(op, "ty-");
Z }
Z if (value <= 12) {
Z return(copyst(op,
Z (ordflag) ? ordinal[value] : cardinal[value]));
Z }
Z op = copyst(op, cardinal[value]); /* fourteen, fourteenth */
Z /*
Z * Here on 100, 14000, etc.
Z */
Zexit: if (ordflag) op = copyst(op, "th");
Z return(op);
Z}
Z
Zchar *
Zcopyst(buffer, string)
Zchar *buffer;
Zchar *string;
Z/*
Z * Copy a string into buffer. Return the free pointer.
Z */
Z{
Z register char *ip;
Z register char *op;
Z
Z ip = string;
Z op = buffer;
Z
Z while ((*op = *ip++)) op++;
Z return (op);
Z}
STUNKYFLUFF
set `sum nbrtxt.c`
if test 30886 != $1
then
echo nbrtxt.c: Checksum error. Is: $1, should be: 30886.
fi
#
#
echo Extracting timetx.c:
sed 's/^Z//' >timetx.c <<\STUNKYFLUFF
Z#
Z/*
Z * Convert Time to a Readable Format.
Z *
Z * Synopsis:
Z *
Z * char *timetxt(buffer, hour, minute, second, daylight);
Z * char *buffer; -- Where output goes
Z * int hour; -- Hour, range is 0 to 24
Z * int minute; -- Minute, range is -1 to 59
Z * int second; -- Seconds, range is -1 to 59
Z * int daylight; -- Daylight savings time if non-zero.
Z *
Z * Note: if minute or second is less than zero, the value is not calculated.
Z * This distinguishes between "unknown seconds" and "exactly no seconds."
Z * If hour is less than zero, a null string is returned.
Z * Timetxt converts the time to a null-trailed string. It returns a pointer
Z * to the first free byte (i.e. the null);
Z *
Z * The output follows the syntax of Robert J. Lurtsema, and includes:
Z *
Z * In twenty-five seconds, the time will be ten minutes before noon.
Z *
Z *
Z * External routines called:
Z *
Z * nbrtxt (Number to ascii conversion)
Z * copyst (String copy routine)
Z */
Z
Zextern char *nbrtxt();
Zextern char *copyst();
Z
Zchar *timetxt(buffer, hour, minute, second, daylight)
Zchar *buffer; /* Output buffer */
Zint hour; /* Hours 00 - 23 */
Zint minute; /* Minutes */
Zint second; /* Seconds */
Zint daylight; /* Non-zero if savings time */
Z/*
Z * Output time of day.
Z */
Z{
Z char *op; /* Output pointer */
Z register int late; /* after hour or afternoon */
Z register int sec; /* Seconds temp */
Z char *stuff(); /* Buffer stuffer */
Z
Z op = buffer; /* Setup buffer pointer */
Z if (hour < 0) { /* If it's a dummy call, */
Z *op = 0; /* Return a null string */
Z return(op);
Z }
Z if (daylight == 0101010) { /* Secret flag */
Z op = copyst(op, "The big hand is on the ");
Z op = nbrtxt(op, (((minute + 2 + second/30)/5 + 11)%12)+1, 0);
Z op = copyst(op," and the little hand is on the ");
Z op = nbrtxt(op, ((hour + 11) % 12) + 1, 0);
Z return(copyst(op, ". "));
Z }
Z /*
Z * Check if the time is more than 30 minutes past the hour.
Z * If so, output the time before the next hour.
Z */
Z if (minute < 0) second = (-2); /* No minutes means no seconds */
Z else if ((late = (minute > 30 || (minute == 30 && second > 0)))) {
Z if (second > 0) { /* Before next hour */
Z second = 60 - second;
Z minute += 1; /* Diddle the minute, too */
Z }
Z minute = 60 - minute; /* Minutes before next hour */
Z hour += 1; /* Frobozz next hour getter */
Z }
Z /*
Z * Decisions, decisions:
Z * Minutes Seconds =>
Z * 00 00 Exactly Noon
Z * 00 01 One second after noon
Z * 01 00 Exactly one minute after noon
Z * 30 00 Exactly half past noon
Z * 59 00 Exactly one minute before noon
Z * 59 59 In one second, the time will be noon
Z */
Z if (late && second > 0) { /* Respectfully dedicated to */
Z /* Robert J. Lurtsema */
Z op = stuff(op, second, 1, "In ", " second");
Z op = copyst(op, ", the time will be ");
Z sec = -2; /* We've done seconds already */
Z }
Z else {
Z op = copyst(op, "The time is ");
Z sec = second; /* Seconds still to be done */
Z }
Z if (sec == 0) {
Z op = copyst(op, "exactly ");
Z if (minute == 30)
Z op = copyst(op, "half past ");
Z else op = stuff(op, minute, 1, " ", " minute");
Z }
Z else { /* Non exact or missing seconds */
Z op = stuff(op, minute, 0, " ", " minute");
Z op = stuff(op, sec, (minute > 0), " and ", " second");
Z }
Z op = copyst(op, (minute < 0 || (minute == 0 && late)
Z || (second == 0
Z && ((minute == 0 && late == 0)
Z || minute == 30))) ? " "
Z : (late) ? " before " : " after ");
Z /*
Z * Hours are not quite so bad
Z */
Z if (hour == 0 || hour == 24)
Z op = copyst(op, "midnight");
Z else if (hour == 12)
Z op = copyst(op, "noon");
Z else {
Z if (late = (hour > 12))
Z hour = hour - 12;
Z op = nbrtxt(op, hour, 0);
Z op = copyst(op, (late) ? " PM" : " AM");
Z }
Z return(copyst(op, (daylight)
Z ? ", Daylight Savings Time. "
Z : ", Digital Standard Time. "));
Z}
Z
Zstatic char *
Zstuff(buffer, value, flag, leading, trailing)
Zchar *buffer; /* Output goes here */
Zint value; /* The value to print if > 0 */
Zint flag; /* flag is set to print leading */
Zchar *leading; /* preceeded by ... */
Zchar *trailing; /* and followed by ... */
Z/*
Z * If value <= zero, output nothing. Else, output "leading" value "trailing".
Z * Note: leading is output only if flag is set.
Z * If value is not one, output an "s", too.
Z */
Z{
Z register char *op; /* Output pointer */
Z
Z op = buffer; /* Setup buffer pointer */
Z if (value > 0) {
Z if (flag)
Z op = copyst(op, leading);
Z op = nbrtxt(op, value, 0);
Z op = copyst(op, trailing);
Z if (value != 1)
Z op = copyst(op, "s");
Z }
Z return(op);
Z}
STUNKYFLUFF
set `sum timetx.c`
if test 32974 != $1
then
echo timetx.c: Checksum error. Is: $1, should be: 32974.
fi
#
#
echo Extracting today.c:
sed 's/^Z//' >today.c <<\STUNKYFLUFF
Z#
Z/*
Z * T O D A Y
Z *
Z * time of day
Z *
Z * Define UNIX for "native" Unix
Z */
Z
Z/*)BUILD $(PROGRAM) = today
Z $(FILES) = { today datetx timetx nbrtxt moontx }
Z $(TKBOPTIONS) = {
Z TASK = ...TOD
Z }
Z*/
Z
Z#ifdef DOCUMENTATION
Z
Ztitle today Date and Time in English
Zindex Date and Time in English
Z
Zsynopsis
Z
Z today [-] [x] | [date]
Z
Zdescription
Z
Z Today prints the date, time, and phase of the moon in English.
Z The following options are available:
Z .lm +8
Z .s.i -8;- or x Read date strings from the standard input file.
Z .s.i -8;date Print information for the indicated date.
Z .s.lm -8
Z Date and time information is given in ISO numeric notation. For
Z example, November 6, 1980 would be represented as "801106". If
Z a time is needed, it would be appended to the date, using 24-hour
Z notation: "801106110402" would be a time which is exact to the
Z second. To specify the century, the two-digit century number
Z may be preceeded by '+' as in "+18801106".
Z .s
Z Non-numeric separators between the various fields are permitted:
Z "+1776.07.04-11:15:21". Note that the full two digit entry must be
Z given.
Z .s
Z If no parameter is given, today outputs the current date and time.
Z
Zdiagnostics
Z
Z .lm +8
Z .s.i -8;Bad parameters or date out of range in ...
Z .s
Z An input date or time is incorrect.
Z .lm -8
Z
Zauthor
Z
Z Martin Minow
Z
Zbugs
Z
Z The algorithm is only valid for the Gregorian calender.
Z
Z#endif
Z
Z#define APRIL_FOOLS
Z
Zint __narg = 1; /* No prompt if no args */
Z#define LINEWIDTH 72 /* Width of line */
Z
Z#include <stdio.h>
Z#include <time.h>
Z#ifdef unix
Z#include <ctype.h>
Z#undef NULL
Z#endif
Z
Z#define NULL 0
Z#define EOS 0
Z#define FALSE 0
Z#define TRUE 1
Z
Zint day_month[] = { /* Needed for dotexttime() */
Z 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
Z};
Zint ccpos; /* Current line position */
Zchar lastbyte; /* Memory for output() */
Zchar line[100]; /* Data line for input function */
Zchar *valptr; /* Needed for number converter */
Zchar wordbuffer[LINEWIDTH]; /* Buffer for output function */
Zchar *wordptr = wordbuffer; /* Free byte in wordbuffer */
Zchar linebuffer[LINEWIDTH+2]; /* Output text buffer */
Zchar *lineptr = linebuffer; /* Free byte in linebuffer */
Zint polish; /* Funny mode flag */
Z
Zextern char *datetxt(); /* Date getter */
Zextern char *timetxt(); /* Time of day getter */
Zextern char *moontxt(); /* Phase of the moon getter */
Z
Zmain(argc, argv)
Zint argc;
Zchar *argv[];
Z/*
Z * Driver for time routines. Usage:
Z *
Z * today Prints current time of day in readable form,
Z * followed by a cookie.
Z *
Z * today {+cc}yymmddhhmmss Prints indicated time of day.
Z * Note, hh, mm, ss may be omitted.
Z * For example:
Z * today 401106 = Nov. 6, 1940
Z * today +19401106 = Nov. 6, 1940
Z * today 4011061015 = Nov. 6, 1940 10:15 AM
Z *
Z * today - Data is read from the standard input and
Z * today x output as needed. The format of each
Z * line is identical to the command format.
Z * ("today x" is needed for vms.)
Z */
Z
Z{
Z ccpos = 0; /* New line now */
Z wordptr = wordbuffer; /* Nothing buffered */
Z lineptr = linebuffer; /* Nothing in output buffer too */
Z polish = 0; /* Normal mode */
Z if (argc > 1 && tolower(argv[1][0]) == 'p') {
Z polish = 1;
Z argc--;
Z argv++;
Z }
Z if (argc == 2 && ((argv[1][0] == '-') || (argv[1][0] | 040) == 'x')) {
Z while (!getline()) { /* Read and print times */
Z dotexttime(line);
Z }
Z return;
Z }
Z else if (argc > 1) {
Z if (dotexttime(argv[1]) == 0)
Z return;
Z }
Z /*
Z * Here if no parameters or an error in the parameter field.
Z */
Z dotime(); /* Print the time. */
Z output("\n"); /* Space before cookie */
Z#ifdef UNIX
Z execl(COOKIEPROGRAM, "cookie", 0);
Z#endif
Z}
Z
Zdotime()
Z/*
Z * Print the time of day for Unix or VMS native mode.
Z */
Z{
Z int tvec[2]; /* Buffer for time function */
Z struct tm *localtime(); /* Unix time decompile function */
Z struct tm *p; /* Local pointer to time of day */
Z int year;
Z int month;
Z
Z time(tvec); /* Get the time of day */
Z p = localtime(tvec); /* Make it more understandable */
Z year = p->tm_year + 1900;
Z month = p->tm_mon + 1;
Z#ifdef APRIL_FOOLS
Z if (month == 4 && p->tm_mday == 1)
Z polish = !polish;
Z#endif
Z process(year, month, p->tm_mday, p->tm_hour,
Z p->tm_min, p->tm_sec, p->tm_wday);
Z}
Z
Zdotexttime(text)
Zchar *text; /* Time text */
Z/*
Z * Create the time values and print them, return 1 on error.
Z */
Z
Z{
Z int epoch; /* Which century */
Z int year;
Z int month;
Z int day;
Z int hour;
Z int minute;
Z int second;
Z int leapyear;
Z
Z valptr = text; /* Setup for getval() */
Z while (*valptr == ' ') valptr++; /* Leading blanks skip */
Z if (*valptr != '+')
Z epoch = 1900; /* Default for now */
Z else {
Z valptr++;
Z if ((epoch = getval(-1, 00, 99)) < 0) goto bad;
Z epoch *= 100; /* Make it a real epoch */
Z }
Z
Z if ((year = getval(-1, 00, 99)) < 0) goto bad;
Z year += epoch;
Z leapyear = ((year%4) == 0) && (((year%400) == 0) || (year%100 != 0));
Z if ((month = getval(-1, 1, 12)) < 0) goto bad;
Z if ((day = getval(-1, 1,
Z (month == 2 && leapyear) ? 29 : day_month[month])) < 0)
Z goto bad;
Z if ((hour = getval(-2, 0, 23)) == -1) goto bad;
Z if ((minute = getval(-2, 0, 59)) == -1) goto bad;
Z if ((second = getval(-2, 0, 59)) == -1) goto bad;
Z process(year, month, day, hour, minute, second, 0);
Z return(0); /* Normal exit */
Z
Zbad: output("Bad parameters or date out of range in \"");
Z output(text);
Z output("\" after scanning \"");
Z *valptr = '\0';
Z output(text);
Z output("\".\n");
Z return(1); /* Error exit */
Z}
Z
Zstatic char outline[500]; /* Output buffer */
Z
Zprocess(year, month, day, hour, minute, second, daylight)
Zint year; /* Year 1900 = 1900 */
Zint month; /* Month January = 1 */
Zint day; /* Day 1 = 1 */
Zint hour; /* Hour 0 .. 23 */
Zint minute; /* Minute 0 .. 59 */
Zint second; /* Second 0 .. 59 */
Zint daylight; /* Daylight savings time if 1 */
Z/*
Z * Output the information. Note that the parameters are within range.
Z */
Z{
Z
Z output("Today is ");
Z datetxt(outline, year, month, day);
Z output(outline);
Z output(". ");
Z timetxt(outline, hour, minute, second,
Z (polish) ? 0101010 : daylight);
Z output(outline);
Z output("The moon is ");
Z moontxt(outline, year, month, day);
Z output(outline);
Z output(". \n");
Z}
Z
Z
Zoutput(text)
Zchar *text; /* What to print */
Z/*
Z * Output routine. Text is output using put() so that lines are
Z * not more than LINEWIDTH bytes long. Current position is in global ccpos.
Z * (put is equivalent to putchar() except that it is locally buffered.)
Z */
Z{
Z register char *in; /* Current pos. in scan */
Z register char c; /* Current character */
Z register char *wp; /* Word pointer */
Z
Z in = text;
Z while (c = *in++) {
Z switch (c) {
Z case '\n': /* Force new line */
Z case ' ': /* or a space seen */
Z if ((wordptr-wordbuffer) + ccpos >= LINEWIDTH) {
Z put('\n'); /* Current word */
Z ccpos = 0; /* won't fit, dump it. */
Z }
Z if (wordptr > wordbuffer) {
Z if (ccpos) { /* Leading space needed */
Z put(' ');
Z ccpos++;
Z }
Z for (wp = wordbuffer; wp < wordptr;) {
Z put(*wp++);
Z }
Z ccpos += (wordptr - wordbuffer);
Z wordptr = wordbuffer; /* Empty buffer */
Z }
Z if (c == '\n') {
Z put('\n'); /* Print a newline */
Z ccpos = 0; /* and reset the cursor */
Z }
Z break;
Z
Z default:
Z *wordptr++ = c; /* Save piece of word */
Z }
Z }
Z}
Z
Zput(c)
Zregister char c;
Z/*
Z * Actual output routine
Z */
Z{
Z if (c == '\n' || (lineptr - linebuffer) >= LINEWIDTH) {
Z *lineptr = EOS;
Z puts(linebuffer);
Z lineptr = linebuffer;
Z if (c == '\n')
Z return;
Z }
Z *lineptr++ = c;
Z}
Z
Zgetline()
Z/*
Z * Read text to global line[]. Return 1 on end of file, zero on ok.
Z */
Z{
Z register char *t;
Z
Z return (gets(line) == NULL);
Z}
Z
Zgetval(flag, low, high)
Zint flag;
Zint low;
Zint high;
Z/*
Z * Global valptr points to a 2-digit positive decimal integer.
Z * Skip over leading non-numbers and return the value.
Z * Return flag if text[0] == '\0'. Return -1 if the text is bad,
Z * or if the value is out of the low:high range.
Z */
Z{
Z register int value;
Z register int i;
Z register int temp;
Z
Z if (*valptr == '\0') return(flag); /* Default? */
Z while (*valptr && (*valptr < '0' || *valptr > '9')) *valptr++;
Z /* The above allows for 78.04.22 format */
Z for (value = i = 0; i < 2; i++) {
Z temp = *valptr++ - '0';
Z if (temp < 0 || temp > 9) return(-1);
Z value = (value*10) + temp;
Z }
Z return((value >= low && value <= high) ? value : -1);
Z}
Z
STUNKYFLUFF
set `sum today.c`
if test 43354 != $1
then
echo today.c: Checksum error. Is: $1, should be: 43354.
fi
echo ALL DONE BUNKY!
exit 0
More information about the Comp.sources.unix
mailing list