home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-11-10 | 42.0 KB | 1,486 lines |
- Newsgroups: comp.sources.misc
- From: dfs@doe.carleton.ca (David F. Skoll)
- Subject: v33i064: remind - A replacement for calendar, Part07/12
- Message-ID: <1992Nov10.041930.1136@sparky.imd.sterling.com>
- X-Md4-Signature: 7d2c35c5df5008c07f44b05fd7082ad0
- Date: Tue, 10 Nov 1992 04:19:30 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: dfs@doe.carleton.ca (David F. Skoll)
- Posting-number: Volume 33, Issue 64
- Archive-name: remind/part07
- Environment: UNIX, MS-DOS
- Supersedes: remind: Volume 17, Issue 3-6
-
- #!/bin/sh
- # This is part 07 of Remind 03.00.00
- if touch 2>&1 | fgrep 'amc' > /dev/null
- then TOUCH=touch
- else TOUCH=true
- fi
- # ============= init.c ==============
- if test X"$1" != X"-c" -a -f 'init.c'; then
- echo "File already exists: skipping 'init.c'"
- else
- echo "x - extracting init.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > init.c &&
- X/***************************************************************/
- X/* */
- X/* INIT.C */
- X/* */
- X/* Initialize remind; perform certain tasks between */
- X/* iterations in calendar mode; do certain checks after end */
- X/* in normal mode. */
- 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 <ctype.h>
- X#include "types.h"
- X#include "protos.h"
- X#include "expr.h"
- X#include "globals.h"
- X#include "err.h"
- X#include "version.h"
- X
- X/***************************************************************
- X *
- X * Command line options recognized:
- X *
- X * -n = Output next trigger date of each reminder in
- X * simple calendar format.
- X * -r = Disallow RUN mode
- X * -c[n] = Produce a calendar for n months (default = 1)
- X * -w[n] = Specify output device width (default = 80)
- X * -s[n] = Produce calendar in "simple calendar" format
- X * -v = Verbose mode
- X * -o = Ignore ONCE directives
- X * -a = Don't issue timed reminders which will be queued
- X * -q = Don't queue timed reminders
- X * -t = Trigger all reminders (infinite delta)
- X * -h = Hush mode
- X * -f = Do not fork
- X * -dchars = Debugging mode: Chars are:
- X * e = Echo input lines
- X * x = Display expression evaluation
- X * t = Display trigger dates
- X * v = Dump variables at end
- X * l = Display entire line in error messages
- X * -e = Send messages normally sent to stderr to stdout instead
- X * -z[n] = Daemon mode waking up every n (def 5) minutes.
- X * -bn = Time format for cal (0, 1, or 2)
- X * -xn = Max. number of iterations for SATISFY
- X *
- X **************************************************************/
- X
- X/* For parsing an integer */
- X#define PARSENUM(var, s) \
- X var = 0; \
- X while (isdigit(*(s))) { \
- X var *= 10; \
- X var += *(s) - '0'; \
- X s++; \
- X }
- X
- Xstatic char *BadDate = "Illegal date on command line\n";
- X
- X/***************************************************************/
- X/* */
- X/* InitRemind */
- X/* */
- X/* Initialize the system - called only once at beginning! */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC void InitRemind(int argc, char *argv[])
- X#else
- Xvoid InitRemind(argc, argv)
- Xint argc;
- Xchar *argv[];
- X#endif
- X{
- X char *arg;
- X int i;
- X int y, m, d;
- X Token tok;
- X
- X y = NO_YR;
- X m = NO_MON;
- X d = NO_DAY;
- X
- X RealToday = SystemDate(&CurYear, &CurMon, &CurDay);
- X if (RealToday < 0) {
- X fprintf(ErrFp, "Illegal system date: Year is less than %d\n", BASE);
- X exit(1);
- X }
- X JulianToday = RealToday;
- X FirstYear = -1;
- X FromJulian(JulianToday, &CurYear, &CurMon, &CurDay);
- X
- X /* Parse the command-line options */
- X i = 1;
- X while (i < argc) {
- X arg = argv[i];
- X if (*arg != '-') break; /* Exit the loop if it's not an option */
- X i++;
- X arg++;
- X
- X while (*arg) {
- X switch(*arg++) {
- X case 'n':
- X case 'N':
- X NextMode = 1;
- X#ifdef HAVE_QUEUED
- X DontQueue = 1;
- X#endif
- X break;
- X
- X case 'r':
- X case 'R':
- X RunDisabled = 1;
- X break;
- X
- X case 'o':
- X case 'O':
- X IgnoreOnce = 1;
- X break;
- X
- X case 't':
- X case 'T':
- X InfiniteDelta = 1;
- X break;
- X
- X case 'e':
- X case 'E':
- X ErrFp = stdout;
- X break;
- X
- X case 'h':
- X case 'H':
- X Hush = 1;
- X break;
- X
- X#ifdef HAVE_QUEUED
- X case 'z':
- X case 'Z':
- X DontFork = 1;
- X PARSENUM(Daemon, arg);
- X if (Daemon<5) Daemon=5;
- X else if (Daemon>60) Daemon=60;
- X break;
- X
- X case 'a':
- X case 'A':
- X DontIssueAts = 1;
- X break;
- X
- X case 'q':
- X case 'Q':
- X DontQueue = 1;
- X break;
- X
- X case 'f':
- X case 'F':
- X DontFork = 1;
- X break;
- X#endif
- X case 'c':
- X case 'C':
- X DoCalendar = 1;
- X if (*arg == '+') {
- X arg++;
- X PARSENUM(CalWeeks, arg);
- X if (!CalWeeks) CalWeeks = 1;
- X } else {
- X PARSENUM(CalMonths, arg);
- X if (!CalMonths) CalMonths = 1;
- X }
- X break;
- X
- X case 's':
- X case 'S':
- X DoSimpleCalendar = 1;
- X PARSENUM(CalMonths, arg);
- X if (!CalMonths) CalMonths = 1;
- X break;
- X
- X case 'w':
- X case 'W':
- X PARSENUM(CalWidth, arg);
- X if (CalWidth < 80) CalWidth = 80;
- X break;
- X
- X case 'd':
- X case 'D':
- X while (*arg) {
- X switch(*arg++) {
- X case 'e': case 'E': DebugFlag |= DB_ECHO_LINE; break;
- X case 'x': case 'X': DebugFlag |= DB_PRTEXPR; break;
- X case 't': case 'T': DebugFlag |= DB_PRTTRIG; break;
- X case 'v': case 'V': DebugFlag |= DB_DUMP_VARS; break;
- X case 'l': case 'L': DebugFlag |= DB_PRTLINE; break;
- X default:
- X fprintf(ErrFp, "Unknown debug flag '%c'\n", *(arg-1));
- X }
- X }
- X break;
- X
- X case 'v':
- X case 'V':
- X DebugFlag |= DB_PRTLINE;
- X ShowAllErrors = 1;
- X break;
- X
- X case 'b':
- X case 'B':
- X PARSENUM(ScFormat, arg);
- X if (ScFormat<0 || ScFormat>2) ScFormat=SC_AMPM;
- X break;
- X
- X case 'x':
- X case 'X':
- X PARSENUM(MaxSatIter, arg);
- X if (MaxSatIter < 10) MaxSatIter=10;
- X break;
- X
- X default:
- X fprintf(ErrFp, "Unknown option '%c'\n", *(arg-1));
- X }
- X
- X }
- X }
- X
- X
- X /* Get the filename. */
- X if (i >= argc) {
- X Usage();
- X exit(1);
- X }
- X InitialFile = argv[i];
- X i++;
- X
- X /* Get the date, if any */
- X if (i < argc) {
- X while (i < argc) {
- X arg = argv[i++];
- X FindToken(arg, &tok);
- X switch (tok.type) {
- X case T_Month:
- X if (m != NO_MON) Usage();
- X else m = tok.val;
- X break;
- X
- X case T_Day:
- X if (d != NO_DAY) Usage();
- X else d = tok.val;
- X break;
- X
- X case T_Year:
- X if (y != NO_YR) Usage();
- X else y = tok.val;
- X break;
- X
- X default: Usage();
- X }
- X }
- X
- X/* Must supply date in the form: day, mon, yr OR mon, yr */
- X if (m == NO_MON || y == NO_YR) Usage();
- X if (d == NO_DAY) d=1;
- X if (d > DaysInMonth(m, y)) {
- X fprintf(ErrFp, BadDate);
- X Usage();
- X }
- X JulianToday = Julian(y, m, d);
- X if (JulianToday == -1) {
- X fprintf(ErrFp, BadDate);
- X Usage();
- X }
- X CurYear = y;
- X CurMon = m;
- X CurDay = d;
- X if (JulianToday != RealToday) IgnoreOnce = 1;
- X }
- X/* Set JulFirst */
- X JulFirst = Julian(CurYear, 0, 1);
- X FirstYear = CurYear;
- X}
- X
- X/***************************************************************/
- X/* */
- X/* Usage */
- X/* */
- X/* Print the usage info. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC void Usage(void)
- X#else
- Xvoid Usage()
- X#endif
- X{
- X fprintf(ErrFp, "\nREMIND %s Copyright 1992 by David F. Skoll\n\n", VERSION);
- X fprintf(ErrFp, "Usage: remind [options] filename [date]\n\n");
- X fprintf(ErrFp, "Options:\n");
- X fprintf(ErrFp, " -n Output next occurrence of reminders in simple format\n");
- X fprintf(ErrFp, " -r Disable RUN directives\n");
- X fprintf(ErrFp, " -c[n] Produce a calendar for n (default 1) months\n");
- X fprintf(ErrFp, " -c+[n] Produce a calendar for n (default 1) weeks\n");
- X fprintf(ErrFp, " -w[n] Specify width (default 80) of calendar output\n");
- X fprintf(ErrFp, " -s[n] Produce 'simple calendar' for n (1) months\n");
- X fprintf(ErrFp, " -v Verbose mode\n");
- X fprintf(ErrFp, " -o Ignore ONCE directives\n");
- X fprintf(ErrFp, " -t Trigger all future reminders regardless of delta\n");
- X fprintf(ErrFp, " -h 'Hush' mode - be very quiet\n");
- X#ifdef HAVE_QUEUED
- X fprintf(ErrFp, " -a Don't trigger timed reminders immediately - just queue them\n");
- X fprintf(ErrFp, " -q Don't queue timed reminders\n");
- X fprintf(ErrFp, " -f Trigger timed reminders by staying in foreground\n");
- X fprintf(ErrFp, " -z[n] Enter daemon mode, waking every n (5) minutes.\n");
- X#endif
- X fprintf(ErrFp, " -d... Debug: e=echo x=expr-eval t=trig v=dumpvars l=showline\n");
- X fprintf(ErrFp, " -e Divert messages normally sent to stderr to stdout\n");
- X fprintf(ErrFp, " -b[n] Time format for cal: 0=am/pm, 1=24hr, 2=none\n");
- X fprintf(ErrFp, " -x[n] Iteration limit for SATISFY clause (def=150)\n");
- X exit(1);
- X}
- SHAR_EOF
- $TOUCH -am 1109141292 init.c &&
- chmod 0600 init.c ||
- echo "restore of init.c failed"
- set `wc -c init.c`;Wc_c=$1
- if test "$Wc_c" != "9425"; then
- echo original size 9425, current size $Wc_c
- fi
- fi
- # ============= main.c ==============
- if test X"$1" != X"-c" -a -f 'main.c'; then
- echo "File already exists: skipping 'main.c'"
- else
- echo "x - extracting main.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > main.c &&
- X/***************************************************************/
- X/* */
- X/* MAIN.C */
- X/* */
- X/* Main program loop, as well as miscellaneous conversion */
- X/* routines, etc. */
- X/* */
- X/* This file is part of REMIND. */
- X/* Copyright (C) 1992 by David F. Skoll. */
- X/* */
- X/***************************************************************/
- 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 <stdio.h>
- X#include <string.h>
- X#ifdef HAVE_STDARG
- X#include <stdarg.h>
- X#else
- X#include <varargs.h>
- X#endif
- X#include <ctype.h>
- X
- X#ifdef __MSDOS__
- X#include <dos.h>
- X#endif
- X
- X
- X#ifndef __MSDOS__
- X#include <sys/types.h>
- X#ifdef SYSV
- X#include <time.h>
- X#else
- X#include <sys/time.h>
- X#endif
- X#endif /* ifndef __MSDOS__ */
- X
- X#include "types.h"
- X#include "protos.h"
- X#include "expr.h"
- X#include "globals.h"
- X#include "err.h"
- X
- XPRIVATE void DoReminders ARGS ((void));
- X
- Xstatic char TPushBuffer[TOKSIZE+1]; /* Buffer for pushing back a token. */
- Xstatic char *TokenPushed = NULL;
- X
- X
- X/***************************************************************/
- X/***************************************************************/
- X/** **/
- X/** Main Program Loop **/
- X/** **/
- X/***************************************************************/
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC int main(int argc, char *argv[])
- X#else
- Xint main(argc, argv)
- Xint argc;
- Xchar *argv[];
- X#endif
- X{
- X#ifdef HAVE_QUEUED
- X int pid;
- X#endif
- X
- X/* The very first thing to do is to set up ErrFp to be stderr */
- X ErrFp = stderr;
- X
- X/* Set up global vars */
- X ArgC = argc;
- X ArgV = argv;
- X
- X InitRemind(argc, argv);
- X if(DoCalendar || DoSimpleCalendar) {
- X ProduceCalendar();
- X return 0;
- X }
- X
- X /* Not doing a calendar. Do the regular remind loop */
- X DoReminders();
- X
- X if (DebugFlag & DB_DUMP_VARS) DumpVarTable();
- X
- X if (!Hush) {
- X if (DestroyOmitContexts())
- X Eprint("Warning: PUSH-OMIT-CONTEXT without matching POP-OMIT-CONTEXT.");
- X#ifdef HAVE_QUEUED
- X if (!Daemon && !NextMode && !NumTriggered && !NumQueued) printf("No reminders.\n");
- X else
- X if (!Daemon && !NextMode && !NumTriggered) printf("%d reminder%s queued for later today.\n",
- X NumQueued, (NumQueued == 1) ? "" : "s");
- X#else
- X if (!NextMode && !NumTriggered) printf("No reminders.\n");
- X#endif
- X }
- X
- X /* If it's MS-DOS, reset the file access date */
- X#ifdef __MSDOS__
- X if (RealToday == JulianToday) SetAccessDate(InitialFile, RealToday);
- X#endif
- X
- X /* If there are any background reminders queued up, handle them */
- X#ifdef HAVE_QUEUED
- X if (NumQueued || Daemon) {
- X
- X if (DontFork) {
- X HandleQueuedReminders();
- X return 0;
- X } else {
- X pid = fork();
- X if (pid == 0) {
- X HandleQueuedReminders();
- X return 0;
- X }
- X if (pid == -1) {
- X fprintf(ErrFp, "Couldn't fork to do queued reminders.\n");
- X return 1;
- X }
- X }
- X }
- X#endif
- X
- X return 0;
- X}
- X
- X/***************************************************************/
- X/* */
- X/* DoReminders */
- X/* */
- X/* The normal case - we're not doing a calendar. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPRIVATE void DoReminders(void)
- X#else
- Xstatic void DoReminders()
- X#endif
- X{
- X int r;
- X Token tok;
- X char *s;
- X Parser p;
- X
- X FileAccessDate = GetAccessDate(InitialFile);
- X
- X if (FileAccessDate < 0) {
- X fprintf(ErrFp, "remind: Can't access file '%s'.\n", InitialFile);
- X exit(1);
- X }
- X
- X r=OpenFile(InitialFile);
- X if (r) {
- X fprintf(ErrFp, "Can't read %s: %s\n", InitialFile, ErrMsg[r]);
- X exit(1);
- X }
- X
- X while(1) {
- X r = ReadLine();
- X if (r == E_EOF) return;
- X if (r) {
- X Eprint("Error reading file: %s", ErrMsg[r]);
- X exit(1);
- X }
- X s = FindInitialToken(&tok, CurLine);
- X
- X /* Should we ignore it? */
- X if (NumIfs &&
- X tok.type != T_If &&
- X tok.type != T_Else &&
- X tok.type != T_EndIf &&
- X tok.type != T_IfTrig &&
- X ShouldIgnoreLine())
- X {
- X /*** IGNORE THE LINE ***/
- X }
- X else {
- X /* Create a parser to parse the line */
- X CreateParser(s, &p);
- X switch(tok.type) {
- X
- X case T_Empty:
- X case T_Comment:
- X break;
- X
- X case T_Rem: r=DoRem(&p); break;
- X case T_ErrMsg: r=DoErrMsg(&p); break;
- X case T_If: r=DoIf(&p); break;
- X case T_IfTrig: r=DoIfTrig(&p); break;
- X case T_Else: r=DoElse(&p); break;
- X case T_EndIf: r=DoEndif(&p); break;
- X case T_Include: r=DoInclude(&p); break;
- X case T_Exit: exit(99); break;
- X case T_Set: r=DoSet(&p); break;
- X case T_Fset: r=DoFset(&p); break;
- X case T_UnSet: r=DoUnset(&p); break;
- X case T_Clr: r=DoClear(&p); break;
- X case T_Debug: r=DoDebug(&p); break;
- X case T_Dumpvars: r=DoDump(&p); break;
- X case T_Banner: r=DoBanner(&p); break;
- X case T_Omit: r=DoOmit(&p);
- X if (r == E_PARSE_AS_REM) {
- X DestroyParser(&p);
- X CreateParser(s, &p);
- X r=DoRem(&p);
- X }
- X break;
- X case T_Pop: r=PopOmitContext(&p); break;
- X case T_Preserve: r=DoPreserve(&p); break;
- X case T_Push: r=PushOmitContext(&p); break;
- X case T_RemType: if (tok.val == RUN_TYPE) {
- X r=DoRun(&p);
- X break;
- X } else {
- X CreateParser(CurLine, &p);
- X r=DoRem(&p);
- X break;
- X }
- X
- X
- X /* If we don't recognize the command, do a REM by default */
- X /* Note: Since the parser hasn't been used yet, we don't */
- X /* need to destroy it here. */
- X
- X default: CreateParser(CurLine, &p); r=DoRem(&p); break;
- X }
- X if (r && (!Hush || r != E_RUN_DISABLED)) Eprint("%s", ErrMsg[r]);
- X
- X /* Destroy the parser - free up resources it may be tying up */
- X DestroyParser(&p);
- X }
- X }
- X}
- X
- X/***************************************************************/
- X/* */
- X/* Julian */
- X/* */
- X/* Given day, month, year, return Julian date in days since */
- X/* 1 January 1990. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC int Julian(int year, int month, int day)
- X#else
- Xint Julian(year, month, day)
- Xint day, month, year;
- X#endif
- X{
- X register int jul, iy;
- X
- X if (year < BASE) return -1;
- X
- X if (JulFirst == -1 || year < FirstYear) {
- X jul = 0;
- X for (iy = BASE; iy < year; iy++) jul += DaysInYear(iy);
- X } else {
- X jul = JulFirst;
- X for (iy = FirstYear; iy < year; iy++) jul += DaysInYear(iy);
- X }
- X
- X return jul + MonthIndex[IsLeapYear(year)][month] + day - 1;
- X}
- X
- X/***************************************************************/
- X/* */
- X/* FromJulian */
- X/* */
- X/* Convert a Julian date to year, month, day. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC void FromJulian(int jul, int *y, int *m, int *d)
- X#else
- Xvoid FromJulian(jul, y, m, d)
- Xint jul;
- Xint *y, *m, *d;
- X#endif
- X{
- X register int t;
- X
- X if (jul >= JulFirst && JulFirst != -1) {
- X *y = FirstYear;
- X jul -= JulFirst;
- X } else *y = BASE;
- X
- X *m = 0;
- X
- X t = DaysInYear(*y);
- X while (jul >= t) {
- X jul -= t;
- X (*y)++;
- X t = DaysInYear(*y);
- X }
- X
- X t = DaysInMonth(*m, *y);
- X while (jul >= t) {
- X jul -= t;
- X (*m)++;
- X t = DaysInMonth(*m, *y);
- X }
- X *d = jul + 1;
- X return;
- X}
- X
- X/***************************************************************/
- X/* */
- X/* ParseChar */
- X/* */
- X/* Parse a character from a parse pointer. If peek is non- */
- X/* zero, then just peek ahead; don't advance pointer. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC int ParseChar(ParsePtr p, int *err, int peek)
- X#else
- Xint ParseChar(p, err, peek)
- XParsePtr p;
- Xint *err;
- Xint peek;
- X#endif
- X{
- X Value val;
- X int r;
- X
- X *err = 0;
- X if (TokenPushed && *TokenPushed)
- X if (peek) return *TokenPushed;
- X else return *TokenPushed++;
- X
- X while(1) {
- X if (p->isnested) {
- X if (*(p->epos))
- X if (peek) return *(p->epos);
- X else return *(p->epos++);
- X free(p->etext); /* End of substituted expression */
- X p->etext = NULL;
- X p->epos = NULL;
- X p->isnested = 0;
- X }
- X if (!*(p->pos)) {
- X return 0;
- X }
- X if (*p->pos != BEG_OF_EXPR || !p->allownested)
- X if (peek) return *(p->pos);
- X else return *(p->pos++);
- X p->pos++;
- X r = EvalExpr(&(p->pos), &val);
- X if (r) {
- X *err = r;
- X DestroyParser(p);
- X return 0;
- X }
- X if (*p->pos != END_OF_EXPR) {
- X *err = E_MISS_END;
- X DestroyParser(p);
- X DestroyValue(&val);
- X return 0;
- X }
- X p->pos++;
- X r = DoCoerce(STR_TYPE, &val);
- X if (r) { *err = r; return 0; }
- X p->etext = val.v.str;
- X val.type = ERR_TYPE; /* So it's not accidentally destroyed! */
- X p->isnested = 1;
- X p->epos = p->etext;
- X }
- X}
- X
- X/***************************************************************/
- X/* */
- X/* ParseNonSpaceChar */
- X/* */
- X/* Parse the next non-space character. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC int ParseNonSpaceChar(ParsePtr p, int *err, int peek)
- X#else
- Xint ParseNonSpaceChar(p, err, peek)
- XParsePtr p;
- Xint *err;
- Xint peek;
- X#endif
- X{
- X int ch;
- X
- X ch = ParseChar(p, err, 1);
- X if (*err) return 0;
- X
- X while (isspace(ch)) {
- X ParseChar(p, err, 0); /* Guaranteed to work */
- X ch = ParseChar(p, err, 1);
- X if (*err) return 0;
- X }
- X if (!peek) ch = ParseChar(p, err, 0); /* Guaranteed to work */
- X return ch;
- X}
- X
- X/***************************************************************/
- X/* */
- X/* ParseToken */
- X/* */
- X/* Parse a token delimited by whitespace. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC int ParseToken(ParsePtr p, char *out)
- X#else
- Xint ParseToken(p, out)
- XParsePtr p;
- Xchar *out;
- X#endif
- X{
- X int c, err;
- X int len = 0;
- X
- X *out = 0;
- X
- X c = ParseChar(p, &err, 0);
- X if (err) return err;
- X while (c && isspace(c)) {
- X c = ParseChar(p, &err, 0);
- X if (err) return err;
- X }
- X if (!c) return OK;
- X *out++ = c;
- X len++;
- X
- X while (c && !isspace(c)) {
- X c = ParseChar(p, &err, 0);
- X if (err) return err;
- X if (len < TOKSIZE && c && !isspace(c)) {
- X *out++ = c;
- X len++;
- X }
- X }
- X *out = 0;
- X return OK;
- X}
- X
- X/***************************************************************/
- X/* */
- X/* ParseIdentifier */
- X/* */
- X/* Parse a valid identifier - ie, alpha or underscore */
- X/* followed by alphanum. Return E_BAD_ID if identifier is */
- X/* invalid. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC int ParseIdentifier(ParsePtr p, char *out)
- X#else
- Xint ParseIdentifier(p, out)
- XParsePtr p;
- Xchar *out;
- X#endif
- X{
- X int c, err;
- X int len = 0;
- X
- X *out = 0;
- X
- X c = ParseChar(p, &err, 0);
- X if (err) return err;
- X while (c && isspace(c)) {
- X c = ParseChar(p, &err, 0);
- X if (err) return err;
- X }
- X if (!c) return E_EOLN;
- X if (c != '_' && !isalpha(c)) return E_BAD_ID;
- X *out++ = c;
- X *out = 0;
- X len++;
- X
- X while (1) {
- X c = ParseChar(p, &err, 1);
- X if (err) return err;
- X if (c != '_' && !isalnum(c)) return OK;
- X
- X if (len < TOKSIZE) {
- X c = ParseChar(p, &err, 0); /* Guaranteed to work */
- X *out++ = c;
- X *out = 0;
- X len++;
- X }
- X }
- X}
- X/***************************************************************/
- X/* */
- X/* EvaluateExpr */
- X/* */
- X/* We are expecting an expression here. Evaluate it and */
- X/* return the value. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC int EvaluateExpr(ParsePtr p, Value *v)
- X#else
- Xint EvaluateExpr(p, v)
- XParsePtr p;
- XValue *v;
- X#endif
- X{
- X
- X int bracketed = 0;
- X int r;
- X
- X if (p->isnested) return E_PARSE_ERR; /* Can't nest expressions */
- X while (isspace(*p->pos)) (p->pos)++;
- X if (!p->pos) return E_PARSE_ERR; /* Missing expression */
- X if (*p->pos == BEG_OF_EXPR) {
- X (p->pos)++;
- X bracketed = 1;
- X }
- X r = EvalExpr(&(p->pos), v);
- X if (r) return r;
- X if (bracketed) {
- X if (*p->pos != END_OF_EXPR) return E_MISS_END;
- X (p->pos)++;
- X }
- X return OK;
- X}
- X
- X/***************************************************************/
- X/* */
- X/* Eprint - print an error message. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_STDARG
- X#ifdef HAVE_PROTOS
- XPUBLIC void Eprint(const char *fmt, ...)
- X#else
- Xvoid Eprint(fmt)
- Xchar *fmt;
- X#endif
- X#else
- X/*VARARGS0*/
- Xvoid Eprint(va_alist)
- Xva_dcl
- X#endif
- X{
- X va_list argptr;
- X#ifndef HAVE_STDARG
- X char *fmt;
- X#endif
- X
- X /* Check if more than one error msg. from this line */
- X if (!FreshLine && !ShowAllErrors) return;
- X
- X if (FreshLine) {
- X FreshLine = 0;
- X (void) fprintf(ErrFp, "%s(%d): ", FileName, LineNo);
- X if (DebugFlag & DB_PRTLINE) OutputLine(ErrFp);
- X } else fprintf(ErrFp, " ");
- X
- X#ifdef HAVE_STDARG
- X va_start(argptr, fmt);
- X#else
- X va_start(argptr);
- X fmt = va_arg(argptr, char *);
- X#endif
- X (void) vfprintf(ErrFp, fmt, argptr);
- X (void) fputc('\n', ErrFp);
- X#ifndef HAVE_STDARG
- X va_end(argptr)
- X#endif
- X return;
- X}
- X
- X/***************************************************************/
- X/* */
- X/* OutputLine */
- X/* */
- X/* Output a line from memory buffer to a file pointer. This */
- X/* simply involves escaping newlines. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC void OutputLine(FILE *fp)
- X#else
- Xvoid OutputLine(fp)
- XFILE *fp;
- X#endif
- X{
- X register char *s = CurLine;
- X while (*s) {
- X if (*s == '\n') putc('\\', fp);
- X putc(*s, fp);
- X s++;
- X }
- X if (*(s-1) != '\n') putc('\n', fp);
- X}
- X
- X/***************************************************************/
- X/* */
- X/* CreateParser */
- X/* */
- X/* Create a parser given a string buffer */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC void CreateParser(char *s, ParsePtr p)
- X#else
- Xvoid CreateParser(s, p)
- Xchar *s;
- XParsePtr p;
- X#endif
- X{
- X p->text = s;
- X p->pos = s;
- X p->isnested = 0;
- X p->epos = NULL;
- X p->etext = NULL;
- X p->allownested = 1;
- X TokenPushed = NULL;
- X}
- X
- X/***************************************************************/
- X/* */
- X/* DestroyParser */
- X/* */
- X/* Destroy a parser, freeing up resources used. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC void DestroyParser(ParsePtr p)
- X#else
- Xvoid DestroyParser(p)
- XParsePtr p;
- X#endif
- X{
- X if (p->isnested && p->etext) {
- X free(p->etext);
- X p->etext = NULL;
- X p->isnested = 0;
- X }
- X}
- X
- X/***************************************************************/
- X/* */
- X/* PushToken - one level of token pushback. This is */
- X/* GLOBAL, not on a per-parser basis. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC void PushToken(const char *tok)
- X#else
- Xvoid PushToken(tok)
- Xchar *tok;
- X#endif
- X{
- X TokenPushed = TPushBuffer;
- X strcpy(TPushBuffer, tok);
- X strcat(TPushBuffer, " "); /* Separate the pushed token from the next
- X token */
- X
- X}
- X
- X/***************************************************************/
- X/* */
- X/* SystemTime */
- X/* */
- X/* Return the system time in seconds past midnight */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC long SystemTime(void)
- X#else
- Xlong SystemTime()
- X#endif
- X{
- X#ifdef __MSDOS__
- X#ifdef __TURBOC__
- X/* Get time in Turbo C */
- X
- X struct time t;
- X
- X gettime(&t);
- X return (long) t.ti_hour * 3600L + (long) t.ti_min * 60L +
- X (long) t.ti_sec;
- X
- X#else
- X/* Get time in Microsoft C */
- X struct dostime_t tloc;
- X _dos_gettime(&tloc);
- X return (long) tloc.hour * 3600L + (long) tloc.minute * 60L +
- X (long) tloc.second;
- X
- X#endif
- X#else
- X/* Get time in Unix */
- X time_t tloc;
- X struct tm *t;
- X
- X (void) time(&tloc);
- X t = localtime(&tloc);
- X return (long) t->tm_hour * 3600L + (long) t->tm_min * 60L +
- X (long) t->tm_sec;
- X#endif
- X}
- X/***************************************************************/
- X/* */
- X/* SystemDate */
- X/* */
- X/* Obtains today's date. Returns Julian date or -1 for */
- X/* failure. (Failure happens if sys date is before BASE */
- X/* year.) */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC int SystemDate(int *y, int *m, int *d)
- X#else
- Xint SystemDate(y, m, d)
- Xint *d;
- Xint *m;
- Xint *y;
- X#endif
- X{
- X#ifdef __MSDOS__
- X#ifdef __TURBOC__
- X/* Get today's date in Turbo C */
- X struct date da;
- X
- X getdate(&da);
- X *y = da.da_year;
- X *m = da.da_mon - 1;
- X *d = da.da_day;
- X#else
- X/* Get today's date in Microsoft C */
- X struct dosdate_t buf;
- X
- X _dos_getdate(&buf);
- X
- X *d = buf.day;
- X *m = buf.month - 1;
- X *y = buf.year;
- X#endif
- X#else
- X/* Get today's date in UNIX */
- X time_t tloc;
- X struct tm *t;
- X
- X (void) time(&tloc);
- X t = localtime(&tloc);
- X
- X *d = t->tm_mday;
- X *m = t->tm_mon;
- X *y = t->tm_year + 1900;
- X#endif
- X return Julian(*y, *m, *d);
- X}
- X
- X
- X/***************************************************************/
- X/* */
- X/* DoIf - handle the IF command. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC int DoIf(ParsePtr p)
- X#else
- Xint DoIf(p)
- XParsePtr p;
- X#endif
- X{
- X Value v;
- X int r;
- X unsigned syndrome;
- X
- X if (NumIfs >= IF_NEST) return E_NESTED_IF;
- X
- X if (ShouldIgnoreLine()) syndrome = IF_TRUE | BEFORE_ELSE;
- X else {
- X if (r = EvaluateExpr(p, &v)) {
- X syndrome = IF_TRUE | BEFORE_ELSE;
- X Eprint("%s", ErrMsg[r]);
- X } else
- X if ( (v.type != STR_TYPE && v.v.val) ||
- X (v.type == STR_TYPE && strcmp(v.v.str, "")) )
- X syndrome = IF_TRUE | BEFORE_ELSE;
- X else
- X syndrome = IF_FALSE | BEFORE_ELSE;
- X }
- X
- X NumIfs++;
- X IfFlags &= ~(IF_MASK << (2*NumIfs - 2));
- X IfFlags |= syndrome << (2 * NumIfs - 2);
- X if (ShouldIgnoreLine()) return OK;
- X return VerifyEoln(p);
- X}
- X
- X
- X/***************************************************************/
- X/* */
- X/* DoElse - handle the ELSE command. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC int DoElse(ParsePtr p)
- X#else
- Xint DoElse(p)
- XParsePtr p;
- X#endif
- X{
- X unsigned syndrome;
- X
- X if (!NumIfs) return E_ELSE_NO_IF;
- X
- X syndrome = IfFlags >> (2 * NumIfs - 2);
- X
- X if ((syndrome & IF_ELSE_MASK) == AFTER_ELSE) return E_ELSE_NO_IF;
- X
- X IfFlags |= AFTER_ELSE << (2 * NumIfs - 2);
- X return VerifyEoln(p);
- X}
- X
- X/***************************************************************/
- X/* */
- X/* DoEndif - handle the Endif command. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC int DoEndif(ParsePtr p)
- X#else
- Xint DoEndif(p)
- XParsePtr p;
- X#endif
- X{
- X if (!NumIfs) return E_ENDIF_NO_IF;
- X NumIfs--;
- X return VerifyEoln(p);
- X}
- X
- X/***************************************************************/
- X/* */
- X/* DoIfTrig */
- X/* */
- X/* Handle the IFTRIG command. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC int DoIfTrig(ParsePtr p)
- X#else
- Xint DoIfTrig(p)
- XParsePtr p;
- X#endif
- X{
- X int r;
- X unsigned syndrome;
- X Trigger trig;
- X TimeTrig tim;
- X int jul;
- X
- X
- X if (NumIfs >= IF_NEST) return E_NESTED_IF;
- X if (ShouldIgnoreLine()) syndrome = IF_TRUE | BEFORE_ELSE;
- X else {
- X if (r=ParseRem(p, &trig, &tim)) return r;
- X if (trig.typ != NO_TYPE) return E_PARSE_ERR;
- X jul = ComputeTrigger(JulianToday, &trig, &r);
- X if (r) syndrome = IF_TRUE | BEFORE_ELSE;
- X else {
- X if (ShouldTriggerReminder(&trig, &tim, jul))
- X syndrome = IF_TRUE | BEFORE_ELSE;
- X else
- X syndrome = IF_FALSE | BEFORE_ELSE;
- X }
- X }
- X NumIfs++;
- X IfFlags &= ~(IF_MASK << (2*NumIfs - 2));
- X IfFlags |= syndrome << (2 * NumIfs - 2);
- X return OK;
- X}
- X
- X
- X/***************************************************************/
- X/* */
- X/* ShouldIgnoreLine - given the current state of the IF */
- X/* stack, should we ignore the current line? */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC int ShouldIgnoreLine(void)
- X#else
- Xint ShouldIgnoreLine()
- X#endif
- X{
- X register int i, syndrome;
- X
- X/* Algorithm - go from outer to inner, and if any should be ignored, then
- X ignore the whole. */
- X
- X for (i=0; i<NumIfs; i++) {
- X syndrome = (IfFlags >> (i*2)) & IF_MASK;
- X if (syndrome == IF_TRUE+AFTER_ELSE ||
- X syndrome == IF_FALSE+BEFORE_ELSE) return 1;
- X }
- X return 0;
- X}
- X
- X/***************************************************************/
- X/* */
- X/* VerifyEoln */
- X/* */
- X/* Verify that current line contains no more tokens. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC int VerifyEoln(ParsePtr p)
- X#else
- Xint VerifyEoln(p)
- XParsePtr p;
- X#endif
- X{
- X int r;
- X
- X if (r = ParseToken(p, TokBuffer)) return r;
- X if (*TokBuffer && (*TokBuffer != '#') && (*TokBuffer != ';')) {
- X Eprint("Expecting end-of-line, found '%s'", TokBuffer);
- X return E_EXTRANEOUS_TOKEN;
- X }
- X return OK;
- X}
- X
- X/***************************************************************/
- X/* */
- X/* DoDebug */
- X/* */
- X/* Set the debug options under program control. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC int DoDebug(ParsePtr p)
- X#else
- Xint DoDebug(p)
- XParsePtr p;
- X#endif
- X{
- X int err;
- X int ch;
- X int val=1;
- X
- X while(1) {
- X ch = ParseChar(p, &err, 0);
- X if (err) return err;
- X switch(ch) {
- X case '#':
- X case ';':
- X case 0:
- X return OK;
- X
- X case ' ':
- X case '\t':
- X break;
- X
- X case '+':
- X val = 1;
- X break;
- X
- X case '-':
- X val = 0;
- X break;
- X
- X case 'e':
- X case 'E':
- X if (val) DebugFlag |= DB_ECHO_LINE;
- X else DebugFlag &= ~DB_ECHO_LINE;
- X break;
- X
- X case 'x':
- X case 'X':
- X if (val) DebugFlag |= DB_PRTEXPR;
- X else DebugFlag &= ~DB_PRTEXPR;
- X break;
- X
- X case 't':
- X case 'T':
- X if (val) DebugFlag |= DB_PRTTRIG;
- X else DebugFlag &= ~DB_PRTTRIG;
- X break;
- X
- X case 'v':
- X case 'V':
- X if (val) DebugFlag |= DB_DUMP_VARS;
- X else DebugFlag &= ~DB_DUMP_VARS;
- X break;
- X
- X case 'l':
- X case 'L':
- X if (val) DebugFlag |= DB_PRTLINE;
- X else DebugFlag &= ~DB_PRTLINE;
- X break;
- X
- X }
- X }
- X}
- X
- X/***************************************************************/
- X/* */
- X/* DoBanner */
- X/* */
- X/* Set the banner to be printed just before the first */
- X/* reminder is issued. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC int DoBanner(ParsePtr p)
- X#else
- Xint DoBanner(p)
- XParsePtr p;
- X#endif
- X{
- X int err;
- X int c;
- X char buf[LINELEN]; /* So we don't mess up the banner if an error occurs */
- X char *s;
- X
- X c = ParseChar(p, &err, 0);
- X if (err) return err;
- X while (isspace(c)) {
- X c = ParseChar(p, &err, 0);
- X if (err) return err;
- X }
- X if (!c) return E_EOLN;
- X s = buf;
- X
- X while(c) {
- X *s++ = c;
- X c = ParseChar(p, &err, 0);
- X if (err) return err;
- X }
- X *s++ = 0;
- X strcpy(Banner, buf);
- X return OK;
- X}
- X
- X/***************************************************************/
- X/* */
- X/* DoRun */
- X/* */
- X/* Enable or disable the RUN command under program control */
- X/* */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC int DoRun(ParsePtr p)
- X#else
- Xint DoRun(p)
- XParsePtr p;
- X#endif
- X{
- X int r;
- X
- X if (!TopLevel())
- X return OK; /* Silently ignore RUN command in included file */
- X
- X if (r=ParseToken(p, TokBuffer)) return r;
- X
- X if (StriEq(TokBuffer, "ON"))
- X RunDisabled &= ~RUN_SCRIPT;
- X else if (StriEq(TokBuffer, "OFF"))
- X RunDisabled |= RUN_SCRIPT;
- X else return E_PARSE_ERR;
- X
- X return VerifyEoln(p);
- X}
- X
- X/***************************************************************/
- X/* */
- X/* DoErrMsg */
- X/* */
- X/* Issue an error message under program control. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC int DoErrMsg(ParsePtr p)
- X#else
- Xint DoErrMsg(p)
- XParsePtr p;
- X#endif
- X{
- X TimeTrig tt;
- X Trigger t;
- X int r;
- X char *s;
- X
- X t.typ = MSG_TYPE;
- X tt.ttime = SystemTime() / 60;
- X if (r=DoSubst(p, SubstBuffer, &t, &tt, JulianToday, NORMAL_MODE)) return r;
- X s = SubstBuffer;
- X while (isspace(*s)) s++;
- X fprintf(ErrFp, "%s\n", s);
- X return OK;
- X}
- X
- SHAR_EOF
- $TOUCH -am 1109141292 main.c &&
- chmod 0600 main.c ||
- echo "restore of main.c failed"
- set `wc -c main.c`;Wc_c=$1
- if test "$Wc_c" != "30576"; then
- echo original size 30576, current size $Wc_c
- fi
- fi
- echo "End of part 7, continue with part 8"
- exit 0
-
- exit 0 # Just in case...
-