home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-11-10 | 32.5 KB | 1,034 lines |
- Newsgroups: comp.sources.misc
- From: dfs@doe.carleton.ca (David F. Skoll)
- Subject: v33i065: remind - A replacement for calendar, Part08/12
- Message-ID: <1992Nov10.041947.1209@sparky.imd.sterling.com>
- X-Md4-Signature: 2efa42a2148a58c176c2c6116aaf76c1
- Date: Tue, 10 Nov 1992 04:19:47 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: dfs@doe.carleton.ca (David F. Skoll)
- Posting-number: Volume 33, Issue 65
- Archive-name: remind/part08
- Environment: UNIX, MS-DOS
- Supersedes: remind: Volume 17, Issue 3-6
-
- #!/bin/sh
- # This is part 08 of Remind 03.00.00
- if touch 2>&1 | fgrep 'amc' > /dev/null
- then TOUCH=touch
- else TOUCH=true
- fi
- # ============= omit.c ==============
- if test X"$1" != X"-c" -a -f 'omit.c'; then
- echo "File already exists: skipping 'omit.c'"
- else
- echo "x - extracting omit.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > omit.c &&
- X/***************************************************************/
- X/* */
- X/* OMIT.C */
- X/* */
- X/* This file handles all global OMIT commands, and maintains */
- X/* the data structures for OMITted dates. */
- X/* */
- X/* This file is part of REMIND. */
- X/* Copyright (C) 1992 by David F. Skoll. */
- X/* */
- X/***************************************************************/
- X#include "config.h"
- X#include <stdio.h>
- X#ifdef HAVE_STDLIB_H
- X#include <stdlib.h>
- X#endif
- X#ifdef HAVE_MALLOC_H
- X#include <malloc.h>
- X#endif
- X#include "types.h"
- X#include "protos.h"
- X#include "globals.h"
- X#include "err.h"
- X
- XPRIVATE int BexistsIntArray ARGS ((int array[], int num, int key));
- XPRIVATE void InsertIntoSortedArray ARGS ((int *array, int num, int key));
- X
- X/* Arrays for the global omits */
- Xstatic int FullOmitArray[MAX_FULL_OMITS];
- Xstatic int PartialOmitArray[MAX_PARTIAL_OMITS];
- X
- X/* How many of each omit types do we have? */
- Xstatic int NumFullOmits, NumPartialOmits;
- X
- X/* The structure for saving and restoring OMIT contexts */
- Xtypedef struct _omitcontext {
- X struct _omitcontext *next;
- X int numfull, numpart;
- X int *fullsave;
- X int *partsave;
- X} OmitContext;
- X
- X/* The stack of saved omit contexts */
- Xstatic OmitContext *SavedOmitContexts = NULL;
- X
- X/***************************************************************/
- X/* */
- X/* ClearGlobalOmits */
- X/* */
- X/* Clear all the global OMIT context. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC int ClearGlobalOmits(void)
- X#else
- Xint ClearGlobalOmits()
- X#endif
- X{
- X NumFullOmits = NumPartialOmits = 0;
- X return OK;
- X}
- X
- X/***************************************************************/
- X/* */
- X/* DoClear */
- X/* */
- X/* The command-line function CLEAR-OMIT-CONTEXT */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC int DoClear(ParsePtr p)
- X#else
- Xint DoClear(p)
- XParsePtr p;
- X#endif
- X{
- X ClearGlobalOmits();
- X return VerifyEoln(p);
- X}
- X
- X/***************************************************************/
- X/* */
- X/* DestroyOmitContexts */
- X/* */
- X/* Free all the memory used by saved OMIT contexts. */
- X/* As a side effect, return the number of OMIT contexts */
- X/* destroyed. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC int DestroyOmitContexts(void)
- X#else
- Xint DestroyOmitContexts()
- X#endif
- X{
- X OmitContext *c = SavedOmitContexts;
- X OmitContext *d;
- X int num = 0;
- X
- X while (c) {
- X num++;
- X if (c->fullsave) free(c->fullsave);
- X if (c->partsave) free(c->partsave);
- X d = c->next;
- X free(c);
- X c = d;
- X }
- X SavedOmitContexts = NULL;
- X return num;
- X}
- X
- X/***************************************************************/
- X/* */
- X/* PushOmitContext */
- X/* */
- X/* Push the OMIT context on to the stack. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC int PushOmitContext(ParsePtr p)
- X#else
- Xint PushOmitContext(p)
- XParsePtr p;
- X#endif
- X{
- X register int i;
- X OmitContext *context;
- X
- X/* Create the saved context */
- X context = NEW(OmitContext);
- X if (!context) return E_NO_MEM;
- X
- X context->numfull = NumFullOmits;
- X context->numpart = NumPartialOmits;
- X context->fullsave = (int *) malloc(NumFullOmits * sizeof(int));
- X if (NumFullOmits && !context->fullsave) {
- X free(context);
- X return E_NO_MEM;
- X }
- X context->partsave = (int *) malloc(NumPartialOmits * sizeof(int));
- X if (NumPartialOmits && !context->partsave) {
- X free(context->fullsave);
- X free(context);
- X return E_NO_MEM;
- X }
- X
- X/* Copy the context over */
- X for (i=0; i<NumFullOmits; i++)
- X *(context->fullsave + i) = FullOmitArray[i];
- X
- X for (i=0; i<NumPartialOmits; i++)
- X *(context->partsave + i) = PartialOmitArray[i];
- X
- X/* Add the context to the stack */
- X context->next = SavedOmitContexts;
- X SavedOmitContexts = context;
- X return VerifyEoln(p);
- X}
- X
- X/***************************************************************/
- X/* */
- X/* PopOmitContext */
- X/* */
- X/* Pop the OMIT context off of the stack. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC int PopOmitContext(ParsePtr p)
- X#else
- Xint PopOmitContext(p)
- XParsePtr p;
- X#endif
- X{
- X
- X register int i;
- X OmitContext *c = SavedOmitContexts;
- X
- X if (!c) return E_POP_NO_PUSH;
- X NumFullOmits = c->numfull;
- X NumPartialOmits = c->numpart;
- X
- X/* Copy the context over */
- X for (i=0; i<NumFullOmits; i++)
- X FullOmitArray[i] = *(c->fullsave + i);
- X
- X for (i=0; i<NumPartialOmits; i++)
- X PartialOmitArray[i] = *(c->partsave + i);
- X
- X/* Remove the context from the stack */
- X SavedOmitContexts = c->next;
- X
- X/* Free memory used by the saved context */
- X if (c->partsave) free(c->partsave);
- X if (c->fullsave) free(c->fullsave);
- X free(c);
- X
- X return VerifyEoln(p);
- X}
- X
- X/***************************************************************/
- X/* */
- X/* IsOmitted */
- X/* */
- X/* Return non-zero if date is OMITted, zero if it is not. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC int IsOmitted(int jul, int localomit)
- X#else
- Xint IsOmitted(jul, localomit)
- Xint jul, localomit;
- X#endif
- X{
- X int y, m, d;
- X
- X /* Is it omitted because of local omits? */
- X if (localomit & (1 << (jul % 7))) return 1;
- X
- X /* Is it omitted because of fully-specified omits? */
- X if (BexistsIntArray(FullOmitArray, NumFullOmits, jul)) return 1;
- X
- X /* Get the syndrome */
- X FromJulian(jul, &y, &m, &d);
- X if (BexistsIntArray(PartialOmitArray, NumPartialOmits, (m << 5) + d))
- X return 1;
- X
- X /* Not omitted */
- X return 0;
- X}
- X
- X/***************************************************************/
- X/* */
- X/* BexistsIntArray */
- X/* */
- X/* Perform a binary search on an integer array. Return 1 if */
- X/* element is found, 0 otherwise. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPRIVATE int BexistsIntArray(int array[], int num, int key)
- X#else
- Xstatic int BexistsIntArray(array, num, key)
- Xint array[], num, key;
- X#endif
- X{
- X int top=num-1, bot=0, mid;
- X
- X while (top >= bot) {
- X mid = (top+bot)/2;
- X if (array[mid] == key) return 1;
- X else if (array[mid] > key) top = mid-1;
- X else bot=mid+1;
- X }
- X return 0;
- X}
- X
- X/***************************************************************/
- X/* */
- X/* InsertIntoSortedArray */
- X/* */
- X/* Insert a key into a sorted array. We assume that there is */
- X/* room in the array for it. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPRIVATE void InsertIntoSortedArray(int *array, int num, int key)
- X#else
- Xstatic void InsertIntoSortedArray(array, num, key)
- Xint *array, num, key;
- X#endif
- X{
- X /* num is number of elements CURRENTLY in the array. */
- X int *cur = array+num;
- X
- X while (cur > array && *(cur-1) > key) {
- X *cur = *(cur-1);
- X cur--;
- X }
- X *cur = key;
- X}
- X
- X/***************************************************************/
- X/* */
- X/* DoOmit */
- X/* */
- X/* Do a global OMIT command. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC int DoOmit(ParsePtr p)
- X#else
- Xint DoOmit(p)
- XParsePtr p;
- X#endif
- X{
- X int y = NO_YR, m = NO_MON, d = NO_DAY, r;
- X Token tok;
- X int parsing=1;
- X int syndrome;
- X
- X/* Parse the OMIT. We need a month and day; year is optional. */
- X while(parsing) {
- X if (r=ParseToken(p, TokBuffer)) return r;
- X FindToken(TokBuffer, &tok);
- X switch (tok.type) {
- X case T_Year:
- X if (y != NO_YR) {
- X Eprint("Year specified twice");
- X return E_PARSE_ERR;
- X }
- X y = tok.val;
- X break;
- X
- X case T_Month:
- X if (m != NO_MON) {
- X Eprint("Month specified twice");
- X return E_PARSE_ERR;
- X }
- X m = tok.val;
- X break;
- X
- X case T_Day:
- X if (d != NO_DAY) {
- X Eprint("Day specified twice");
- X return E_PARSE_ERR;
- X }
- X d = tok.val;
- X break;
- X
- X case T_Delta:
- X break;
- X
- X case T_Empty:
- X case T_Comment:
- X case T_RemType:
- X parsing = 0;
- X break;
- X
- X default:
- X Eprint("Unknown token '%s' in OMIT command", TokBuffer);
- X return E_PARSE_ERR;
- X }
- X }
- X if (m == NO_MON || d == NO_DAY) {
- X Eprint("Must specify month and day in OMIT command");
- X return E_PARSE_ERR;
- X }
- X if (y == NO_YR) {
- X if (NumPartialOmits == MAX_PARTIAL_OMITS) {
- X Eprint("Too many partial OMITs");
- X return E_NO_MEM;
- X }
- X if (d > MonthDays[m]) return E_BAD_DATE;
- X syndrome = (m<<5) + d;
- X if (!BexistsIntArray(PartialOmitArray, NumPartialOmits, syndrome)) {
- X InsertIntoSortedArray(PartialOmitArray, NumPartialOmits, syndrome);
- X NumPartialOmits++;
- X }
- X } else {
- X if (NumFullOmits == MAX_FULL_OMITS) {
- X Eprint("Too many full OMITs");
- X return E_NO_MEM;
- X }
- X if (d > DaysInMonth(m, y)) return E_BAD_DATE;
- X syndrome = Julian(y, m, d);
- X if (!BexistsIntArray(FullOmitArray, NumFullOmits, syndrome)) {
- X InsertIntoSortedArray(FullOmitArray, NumFullOmits, syndrome);
- X NumFullOmits++;
- X }
- X }
- X if (tok.type == T_RemType) return E_PARSE_AS_REM;
- X return OK;
- X
- X}
- SHAR_EOF
- $TOUCH -am 1109141292 omit.c &&
- chmod 0600 omit.c ||
- echo "restore of omit.c failed"
- set `wc -c omit.c`;Wc_c=$1
- if test "$Wc_c" != "11727"; then
- echo original size 11727, current size $Wc_c
- fi
- fi
- # ============= queue.c ==============
- if test X"$1" != X"-c" -a -f 'queue.c'; then
- echo "File already exists: skipping 'queue.c'"
- else
- echo "x - extracting queue.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > queue.c &&
- X/***************************************************************/
- X/* */
- X/* QUEUE.C */
- X/* */
- X/* Queue up reminders for subsequent execution. */
- X/* */
- X/* This file is part of REMIND. */
- X/* Copyright (C) 1992 by David F. Skoll. */
- X/* */
- X/***************************************************************/
- X#include <stdio.h>
- X#include <signal.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include "config.h"
- X#ifdef HAVE_STDLIB_H
- X#include <stdlib.h>
- X#endif
- X#ifdef HAVE_MALLOC_H
- X#include <malloc.h>
- X#endif
- X#include "globals.h"
- X#include "err.h"
- X#include "types.h"
- X#include "protos.h"
- X
- X/* List structure for holding queued reminders */
- Xtypedef struct _queuedrem {
- X struct _queuedrem *next;
- X int typ;
- X int RunDisabled;
- X char *text;
- X TimeTrig tt;
- X} QueuedRem;
- X
- X/* Global variables */
- X
- Xstatic QueuedRem *QueueHead;
- Xstatic time_t FileModTime;
- Xstatic struct stat StatBuf;
- X
- XPRIVATE void CheckInitialFile ARGS ((void));
- XPRIVATE int CalculateNextTime ARGS ((QueuedRem *q));
- XPRIVATE QueuedRem *FindNextReminder ARGS ((void));
- XPRIVATE void SigIntHandler ARGS ((void));
- X
- X/***************************************************************/
- X/* */
- X/* QueueReminder */
- X/* */
- X/* Put the reminder on a queue for later, if queueing is */
- X/* enabled. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC int QueueReminder(ParsePtr p, int typ, TimeTrig *tim)
- X#else
- Xint QueueReminder(p, typ, tim)
- XParsePtr p;
- Xint typ;
- XTimeTrig *tim;
- X#endif
- X{
- X QueuedRem *qelem;
- X
- X if (DontQueue ||
- X tim->ttime == NO_TIME ||
- X typ == CAL_TYPE ||
- X tim->ttime < SystemTime() / 60 ||
- X ((typ == RUN_TYPE) && RunDisabled)) return OK;
- X
- X qelem = NEW(QueuedRem);
- X if (!qelem) {
- X Eprint("No memory to queue reminder.");
- X return E_NO_MEM;
- X }
- X qelem->text = StrDup(p->pos); /* Guaranteed that parser is not nested. */
- X if (!qelem->text) {
- X free(qelem);
- X Eprint("No memory to queue reminder.");
- X return E_NO_MEM;
- X }
- X qelem->typ = typ;
- X qelem->tt = *tim;
- X qelem->next = QueueHead;
- X qelem->RunDisabled = RunDisabled;
- X QueueHead = qelem;
- X NumQueued++;
- X return OK;
- X}
- X
- X/***************************************************************/
- X/* */
- X/* HandleQueuedReminders */
- X/* */
- X/* Handle the issuing of queued reminders in the background */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC void HandleQueuedReminders(void)
- X#else
- Xvoid HandleQueuedReminders()
- X#endif
- X{
- X QueuedRem *q = QueueHead;
- X long TimeToSleep;
- X unsigned SleepTime;
- X Parser p;
- X Trigger trig;
- X
- X /* Suppress the BANNER from being issued */
- X NumTriggered = 1;
- X
- X /* If we are not connected to a tty, then we must close the
- X * standard file descriptors. This is to prevent someone
- X * doing:
- X * remind file | <filter> | >log
- X * and have <filter> hung because the child (us) is still
- X * connected to it. This means the only commands that will be
- X * processed correctly are RUN commands, provided they mail
- X * the result back or use their own resource (as a window).
- X */
- X if (!DontFork && (!isatty(1) || !isatty(2))) {
- X close(1);
- X close(2);
- X }
- X
- X /* If we're a daemon, get the mod time of initial file */
- X if (Daemon) {
- X if (stat(InitialFile, &StatBuf)) {
- X fprintf(ErrFp, "Cannot stat %s - not running as daemon!\n",
- X InitialFile);
- X Daemon = 0;
- X } else FileModTime = StatBuf.st_mtime;
- X }
- X
- X /* Initialize the queue - initialize all the entries time of issue */
- X
- X while (q) {
- X q->tt.nexttime = (int) (SystemTime()/60 - 1);
- X q->tt.nexttime = CalculateNextTime(q);
- X q = q->next;
- X }
- X
- X if (!DontFork || Daemon) signal(SIGINT, SigIntHandler);
- X
- X /* Sit in a loop, issuing reminders when necessary */
- X while(1) {
- X q = FindNextReminder();
- X
- X /* If no more reminders to issue, we're unless we're a daemon. */
- X if (!q && !Daemon) exit(0);
- X
- X if (Daemon && !q)
- X TimeToSleep = (long) 60*Daemon;
- X else
- X TimeToSleep = (long) q->tt.nexttime * 60L - SystemTime();
- X
- X while (TimeToSleep > 0L) {
- X SleepTime = (unsigned) ((TimeToSleep > 30000L) ? 30000 : TimeToSleep);
- X
- X if (Daemon && SleepTime > 60*Daemon) SleepTime = 60*Daemon;
- X
- X sleep(SleepTime);
- X
- X if (Daemon && SleepTime) CheckInitialFile();
- X
- X if (Daemon && !q)
- X TimeToSleep = (long) 60*Daemon;
- X else
- X TimeToSleep = (long) q->tt.nexttime * 60L - SystemTime();
- X }
- X
- X /* Trigger the reminder */
- X CreateParser(q->text, &p);
- X trig.typ = q->typ;
- X (void) TriggerReminder(&p, &trig, &q->tt, JulianToday);
- X fflush(stdout);
- X
- X /* Calculate the next trigger time */
- X q->tt.nexttime = CalculateNextTime(q);
- X }
- X}
- X
- X
- X/***************************************************************/
- X/* */
- X/* CalculateNextTime */
- X/* */
- X/* Calculate the next time when a reminder should be issued. */
- X/* Return NO_TIME if reminder expired. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPRIVATE int CalculateNextTime(QueuedRem *q)
- X#else
- Xstatic int CalculateNextTime(q)
- XQueuedRem *q;
- X#endif
- X{
- X int tim = q->tt.ttime;
- X int rep = q->tt.rep;
- X int delta = q->tt.delta;
- X int curtime = q->tt.nexttime+1;
- X
- X if (delta == NO_DELTA)
- X if (tim < curtime) return NO_TIME; else return tim;
- X
- X tim -= delta;
- X if (rep == NO_REP) rep = delta;
- X if (tim < curtime) tim += ((curtime - tim) / rep) * rep;
- X if (tim < curtime) tim += rep;
- X if (tim > q->tt.ttime) tim = q->tt.ttime;
- X if (tim < curtime) return NO_TIME; else return tim;
- X}
- X
- X/***************************************************************/
- X/* */
- X/* FindNextReminder */
- X/* */
- X/* Find the next reminder to trigger */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPRIVATE QueuedRem *FindNextReminder(void)
- X#else
- Xstatic QueuedRem *FindNextReminder()
- X#endif
- X{
- X QueuedRem *q = QueueHead;
- X QueuedRem *ans = NULL;
- X
- X while (q) {
- X if (q->tt.nexttime != NO_TIME) {
- X if (!ans) ans = q;
- X else if (q->tt.nexttime < ans->tt.nexttime) ans = q;
- X }
- X
- X q = q->next;
- X }
- X return ans;
- X}
- X
- X
- X/***************************************************************/
- X/* */
- X/* SigIntHandler */
- X/* */
- X/* For debugging purposes, when sent a SIGINT, we print the */
- X/* contents of the queue. This does NOT work when the -f */
- X/* command-line flag is supplied. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPRIVATE void SigIntHandler(void)
- X#else
- Xstatic void SigIntHandler()
- X#endif
- X{
- X QueuedRem *q = QueueHead;
- X
- X#ifdef SYSV
- X signal(SIGINT, SigIntHandler);
- X#endif
- X
- X printf("Contents of AT queue:%s", NL);
- X
- X while (q) {
- X printf("Trigger: %02d:%02d Activate: %02d:%02d Rep: %d Delta: %d%s",
- X q->tt.ttime / 60, q->tt.ttime % 60,
- X q->tt.nexttime / 60, q->tt.nexttime % 60,
- X q->tt.rep, q->tt.delta, NL);
- X printf("Text: %s %s%s%s", ((q->typ == MSG_TYPE) ? "MSG" : "RUN"),
- X q->text,
- X NL, NL);
- X q = q->next;
- X }
- X printf(NL);
- X}
- X/***************************************************************/
- X/* */
- X/* CheckInitialFile */
- X/* */
- X/* If the initial file has been modified, then restart the */
- X/* daemon. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPRIVATE void CheckInitialFile(void)
- X#else
- Xstatic void CheckInitialFile()
- X#endif
- X{
- X /* If date has rolled around, or file has changed, spawn a new version. */
- X time_t tim = FileModTime;
- X int y, m, d;
- X
- X if (stat(InitialFile, &StatBuf) == 0) tim = StatBuf.st_mtime;
- X if (tim != FileModTime ||
- X RealToday != SystemDate(&y, &m, &d))
- X execvp(ArgV[0], ArgV);
- X}
- X
- SHAR_EOF
- $TOUCH -am 1109141292 queue.c &&
- chmod 0600 queue.c ||
- echo "restore of queue.c failed"
- set `wc -c queue.c`;Wc_c=$1
- if test "$Wc_c" != "9705"; then
- echo original size 9705, current size $Wc_c
- fi
- fi
- # ============= token.c ==============
- if test X"$1" != X"-c" -a -f 'token.c'; then
- echo "File already exists: skipping 'token.c'"
- else
- echo "x - extracting token.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > token.c &&
- X/***************************************************************/
- X/* */
- X/* TOKEN.C */
- X/* */
- X/* Contains routines for parsing the reminder file and */
- X/* classifying the tokens parsed. */
- X/* */
- X/* This file is part of REMIND. */
- X/* Copyright (C) 1991 by David F. Skoll. */
- X/* */
- X/***************************************************************/
- X#include <stdio.h>
- X#include <ctype.h>
- X#include "config.h"
- X#ifdef HAVE_STDLIB_H
- X#include <stdlib.h>
- X#endif
- X#ifdef HAVE_MALLOC_H
- X#include <malloc.h>
- X#endif
- X#include "types.h"
- X#include "globals.h"
- X#include "protos.h"
- X#include "err.h"
- X
- X/* The macro PARSENUM parses a char pointer as an integer. It simply
- X executes 'return' if an initial non-numeric char is found. */
- X#define PARSENUM(var, string) \
- X if (!isdigit(*(string))) return; \
- X var = 0; \
- X while (isdigit(*(string))) { \
- X var *= 10; \
- X var += *(string) - '0'; \
- X string++; \
- X }
- X
- X#define UPPER(c) ( ((c) >= 'a' && (c) <= 'z') ? (c) - 'a' + 'A' : (c) )
- X
- X/* The big array holding all recognized (literal) tokens in reminder file.
- X Keep this array sorted, or software will not work. */
- XToken TokArray[] = {
- X /* NAME MINLEN TYPE VALUE */
- X
- X { "after", 3, T_Skip, AFTER_SKIP },
- X { "april", 3, T_Month, 3 },
- X { "at", 2, T_At, 0 },
- X { "august", 3, T_Month, 7 },
- X { "banner", 3, T_Banner, 0 },
- X { "before", 3, T_Skip, BEFORE_SKIP },
- X { "cal", 3, T_RemType, CAL_TYPE },
- X { "clear-omit-context", 5, T_Clr, 0 },
- X { "debug", 5, T_Debug, 0 },
- X { "december", 3, T_Month, 11 },
- X { "dumpvars", 4, T_Dumpvars, 0 },
- X { "else", 4, T_Else, 0 },
- X { "endif", 5, T_EndIf, 0 },
- X { "errmsg", 6, T_ErrMsg, 0 },
- X { "exit", 4, T_Exit, 0 },
- X { "february", 3, T_Month, 1 },
- X { "friday", 3, T_WkDay, 4 },
- X { "fset", 4, T_Fset, 0 },
- X { "if", 2, T_If, 0 },
- X { "iftrig", 6, T_IfTrig, 0 },
- X { "include", 3, T_Include, 0 },
- X { "january", 3, T_Month, 0 },
- X { "july", 3, T_Month, 6 },
- X { "june", 3, T_Month, 5 },
- X { "march", 3, T_Month, 2 },
- X { "may", 3, T_Month, 4 },
- X { "monday", 3, T_WkDay, 0 },
- X { "msg", 3, T_RemType, MSG_TYPE },
- X { "november", 3, T_Month, 10 },
- X { "october", 3, T_Month, 9 },
- X { "omit", 3, T_Omit, 0 },
- X { "once", 3, T_Once, 0 },
- X { "pop-omit-context", 3, T_Pop, 0 },
- X { "preserve", 8, T_Preserve, 0 },
- X { "Push-omit-context", 4, T_Push, 0 },
- X { "rem", 3, T_Rem, 0 },
- X { "run", 3, T_RemType, RUN_TYPE },
- X { "satisfy", 7, T_RemType, SAT_TYPE },
- X { "saturday", 3, T_WkDay, 5 },
- X { "september", 3, T_Month, 8 },
- X { "set", 3, T_Set, 0 },
- X { "skip", 3, T_Skip, SKIP_SKIP },
- X { "sunday", 3, T_WkDay, 6 },
- X { "thursday", 3, T_WkDay, 3 },
- X { "tuesday", 3, T_WkDay, 1 },
- X { "unset", 5, T_UnSet, 0 },
- X { "until", 3, T_Until, 0 },
- X { "wednesday", 3, T_WkDay, 2 }
- X};
- X
- XPRIVATE int TokStrCmp ARGS((const Token *t, const char *s));
- X
- X/***************************************************************/
- X/* */
- X/* FindInitialToken */
- X/* */
- X/* Find the initial token on the command line. If it's a */
- X/* left square bracket, return a T_Illegal type. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC char *FindInitialToken(Token *tok, char *s)
- X#else
- Xchar *FindInitialToken(tok, s)
- XToken *tok;
- Xchar *s;
- X#endif
- X{
- X char *t;
- X int len=0;
- X
- X while (isspace(*s)) s++;
- X
- X t = TokBuffer;
- X
- X while (*s && !isspace(*s)) {
- X if (len < TOKSIZE) {
- X *t++ = *s++;
- X len++;
- X }else s++;
- X }
- X
- X *t = 0;
- X
- X FindToken(TokBuffer, tok);
- X return s;
- X}
- X
- X
- X/***************************************************************/
- X/* */
- X/* FindToken */
- X/* */
- X/* Given a string, which token is it? */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC void FindToken(const char *s, Token *tok)
- X#else
- Xvoid FindToken(s, tok)
- Xchar *s;
- XToken *tok;
- X#endif
- X{
- X register int top, bot, mid, r;
- X
- X tok->type = T_Illegal;
- X if (! *s) {
- X tok->type = T_Empty;
- X return;
- X }
- X
- X if (*s == '#' || *s == ';') {
- X tok->type = T_Comment;
- X return;
- X }
- X
- X /* Quickly give up the search if first char not a letter */
- X if ( ! ((*s >= 'A' && *s <= 'Z') || (*s >= 'a' && *s <= 'z')) ) {
- X FindNumericToken(s, tok);
- X return;
- X }
- X
- X bot = 0;
- X top = sizeof(TokArray) / sizeof(TokArray[0]) - 1;
- X
- X while(top >= bot) {
- X mid = (top + bot) / 2;
- X r = TokStrCmp(&TokArray[mid], s);
- X if (!r) {
- X tok->type = TokArray[mid].type;
- X tok->val = TokArray[mid].val;
- X return;
- X }
- X if (r > 0) top = mid-1; else bot=mid+1;
- X }
- X return;
- X}
- X
- X/***************************************************************/
- X/* */
- X/* FindNumericToken */
- X/* */
- X/* Parse a numeric token: */
- X/* Year - number between 1990 and 2085, or 90-99. */
- X/* Day - number between 1 and 31 */
- X/* Delta - +[+]n */
- X/* Back - -[-]n */
- X/* Rep - *n */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC void FindNumericToken(const char *s, Token *t)
- X#else
- Xvoid FindNumericToken(s, t)
- Xchar *s;
- XToken *t;
- X#endif
- X{
- X int mult = 1, hour, min;
- X
- X t->type = T_Illegal;
- X t->val = 0;
- X if (isdigit(*s)) {
- X PARSENUM(t->val, s);
- X
- X /* If we hit a colon, we've probably got a time hr:min */
- X if (*s == ':') {
- X s++;
- X hour = t->val;
- X PARSENUM(min, s);
- X if (*s || hour > 23 || min > 59) return; /* Illegal time */
- X t->val = hour*60 + min; /* Convert to minutes past midnight */
- X t->type = T_Time;
- X return;
- X }
- X
- X /* If we hit a non-digit, error! */
- X if (*s) return;
- X
- X /* Special hack - convert years between 90 and 99 to 1990 and 1999 */
- X if (t->val >= 90 && t->val <= 99) t->val += 1900;
- X
- X /* Classify the number we've got */
- X if (t->val >= BASE && t->val <= BASE+YR_RANGE) t->type = T_Year;
- X else if (t->val >= 1 && t->val <= 31) t->type = T_Day;
- X else t->type = T_Number;
- X return;
- X } else if (*s == '*') {
- X s++;
- X PARSENUM(t->val, s);
- X if (*s) return; /* Illegal token if followed by non-numeric char */
- X t->type = T_Rep;
- X return;
- X } else if (*s == '+') {
- X s++;
- X if (*s == '+') { mult = -1; s++; }
- X PARSENUM(t->val, s);
- X if (*s) return; /* Illegal token if followed by non-numeric char */
- X t->type = T_Delta;
- X t->val *= mult;
- X return;
- X } else if (*s == '-') {
- X s++;
- X if (*s == '-') { mult = -1; s++; }
- X PARSENUM(t->val, s);
- X if (*s) return; /* Illegal token if followed by non-numeric char */
- X t->type = T_Back;
- X t->val *= mult;
- X return;
- X }
- X return; /* Unknown token type */
- X}
- X
- X
- X/***************************************************************/
- X/* */
- X/* TokStrCmp */
- X/* */
- X/* Compare a token to a string. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPRIVATE int TokStrCmp(const Token *t, const char *s)
- X#else
- Xstatic int TokStrCmp(t, s)
- XToken *t;
- Xchar *s;
- X#endif
- X{
- X register int r;
- X register int l=0;
- X char *tk = t->name;
- X while(*tk && *s) {
- X r = UPPER(*tk) - UPPER(*s);
- X tk++;
- X s++;
- X l++;
- X if (r) return r;
- X }
- X if (l < t->MinLen) return 1;
- X if (!*s) return 0;
- X return (*tk - *s);
- X}
- SHAR_EOF
- $TOUCH -am 1109141292 token.c &&
- chmod 0600 token.c ||
- echo "restore of token.c failed"
- set `wc -c token.c`;Wc_c=$1
- if test "$Wc_c" != "8965"; then
- echo original size 8965, current size $Wc_c
- fi
- fi
- echo "End of part 8, continue with part 9"
- exit 0
-
- exit 0 # Just in case...
-