home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume33 / remind / part07 < prev    next >
Encoding:
Text File  |  1992-11-10  |  42.0 KB  |  1,486 lines

  1. Newsgroups: comp.sources.misc
  2. From: dfs@doe.carleton.ca (David F. Skoll)
  3. Subject:  v33i064:  remind - A replacement for calendar, Part07/12
  4. Message-ID: <1992Nov10.041930.1136@sparky.imd.sterling.com>
  5. X-Md4-Signature: 7d2c35c5df5008c07f44b05fd7082ad0
  6. Date: Tue, 10 Nov 1992 04:19:30 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: dfs@doe.carleton.ca (David F. Skoll)
  10. Posting-number: Volume 33, Issue 64
  11. Archive-name: remind/part07
  12. Environment: UNIX, MS-DOS
  13. Supersedes: remind: Volume 17, Issue 3-6
  14.  
  15. #!/bin/sh
  16. # This is part 07 of Remind 03.00.00
  17. if touch 2>&1 | fgrep 'amc' > /dev/null
  18.  then TOUCH=touch
  19.  else TOUCH=true
  20. fi
  21. # ============= init.c ==============
  22. if test X"$1" != X"-c" -a -f 'init.c'; then
  23.     echo "File already exists: skipping 'init.c'"
  24. else
  25. echo "x - extracting init.c (Text)"
  26. sed 's/^X//' << 'SHAR_EOF' > init.c &&
  27. X/***************************************************************/
  28. X/*                                                             */
  29. X/*  INIT.C                                                     */
  30. X/*                                                             */
  31. X/*  Initialize remind; perform certain tasks between           */
  32. X/*  iterations in calendar mode; do certain checks after end   */
  33. X/*  in normal mode.                                            */
  34. X/*                                                             */
  35. X/*  This file is part of REMIND.                               */
  36. X/*  Copyright (C) 1992 by David F. Skoll.                      */
  37. X/*                                                             */
  38. X/***************************************************************/
  39. X#include "config.h"
  40. X#include <stdio.h>
  41. X#ifdef HAVE_STDLIB_H
  42. X#include <stdlib.h>
  43. X#endif
  44. X#ifdef HAVE_MALLOC_H
  45. X#include <malloc.h>
  46. X#endif
  47. X#include <ctype.h>
  48. X#include "types.h"
  49. X#include "protos.h"
  50. X#include "expr.h"
  51. X#include "globals.h"
  52. X#include "err.h"
  53. X#include "version.h"
  54. X
  55. X/***************************************************************
  56. X *
  57. X *  Command line options recognized:
  58. X *
  59. X *  -n       = Output next trigger date of each reminder in
  60. X *             simple calendar format.
  61. X *  -r       = Disallow RUN mode
  62. X *  -c[n]    = Produce a calendar for n months (default = 1)
  63. X *  -w[n]    = Specify output device width (default = 80)
  64. X *  -s[n]    = Produce calendar in "simple calendar" format
  65. X *  -v       = Verbose mode
  66. X *  -o       = Ignore ONCE directives
  67. X *  -a       = Don't issue timed reminders which will be queued
  68. X *  -q       = Don't queue timed reminders
  69. X *  -t       = Trigger all reminders (infinite delta)
  70. X *  -h       = Hush mode
  71. X *  -f       = Do not fork
  72. X *  -dchars  = Debugging mode:  Chars are:
  73. X *             e = Echo input lines
  74. X *             x = Display expression evaluation
  75. X *             t = Display trigger dates
  76. X *             v = Dump variables at end
  77. X *             l = Display entire line in error messages
  78. X *  -e       = Send messages normally sent to stderr to stdout instead
  79. X *  -z[n]    = Daemon mode waking up every n (def 5) minutes.
  80. X *  -bn      = Time format for cal (0, 1, or 2)
  81. X *  -xn      = Max. number of iterations for SATISFY
  82. X *
  83. X **************************************************************/
  84. X
  85. X/* For parsing an integer */
  86. X#define PARSENUM(var, s)   \
  87. X   var = 0;                \
  88. X   while (isdigit(*(s))) { \
  89. X      var *= 10;           \
  90. X      var += *(s) - '0';   \
  91. X      s++;                 \
  92. X   }
  93. X
  94. Xstatic char *BadDate = "Illegal date on command line\n";
  95. X
  96. X/***************************************************************/
  97. X/*                                                             */
  98. X/*  InitRemind                                                 */
  99. X/*                                                             */
  100. X/*  Initialize the system - called only once at beginning!     */
  101. X/*                                                             */
  102. X/***************************************************************/
  103. X#ifdef HAVE_PROTOS
  104. XPUBLIC void InitRemind(int argc, char *argv[])
  105. X#else
  106. Xvoid InitRemind(argc, argv)
  107. Xint argc;
  108. Xchar *argv[];
  109. X#endif
  110. X{
  111. X   char *arg;
  112. X   int i;
  113. X   int y, m, d;
  114. X   Token tok;
  115. X
  116. X   y = NO_YR;
  117. X   m = NO_MON;
  118. X   d = NO_DAY;
  119. X
  120. X   RealToday = SystemDate(&CurYear, &CurMon, &CurDay);
  121. X   if (RealToday < 0) {
  122. X      fprintf(ErrFp, "Illegal system date: Year is less than %d\n", BASE);
  123. X      exit(1);
  124. X   }
  125. X   JulianToday = RealToday;
  126. X   FirstYear = -1;
  127. X   FromJulian(JulianToday, &CurYear, &CurMon, &CurDay);
  128. X
  129. X   /* Parse the command-line options */
  130. X   i = 1;
  131. X   while (i < argc) {
  132. X      arg = argv[i];
  133. X      if (*arg != '-') break;  /* Exit the loop if it's not an option */
  134. X      i++;
  135. X      arg++;
  136. X
  137. X      while (*arg) {
  138. X         switch(*arg++) {
  139. X        case 'n':
  140. X        case 'N':
  141. X           NextMode = 1;
  142. X#ifdef HAVE_QUEUED
  143. X           DontQueue = 1;
  144. X#endif
  145. X           break;
  146. X
  147. X        case 'r':
  148. X        case 'R':
  149. X           RunDisabled = 1;
  150. X           break;
  151. X
  152. X        case 'o':
  153. X        case 'O':
  154. X           IgnoreOnce = 1;
  155. X           break;
  156. X
  157. X        case 't':
  158. X        case 'T':
  159. X           InfiniteDelta = 1;
  160. X           break;
  161. X
  162. X        case 'e':
  163. X        case 'E':
  164. X           ErrFp = stdout;
  165. X           break;
  166. X
  167. X        case 'h':
  168. X        case 'H':
  169. X           Hush = 1;
  170. X           break;
  171. X
  172. X#ifdef HAVE_QUEUED
  173. X        case 'z':
  174. X        case 'Z':
  175. X           DontFork = 1;
  176. X           PARSENUM(Daemon, arg);
  177. X           if (Daemon<5) Daemon=5;
  178. X           else if (Daemon>60) Daemon=60;
  179. X           break;
  180. X
  181. X        case 'a':
  182. X        case 'A':
  183. X           DontIssueAts = 1;
  184. X           break;
  185. X
  186. X        case 'q':
  187. X        case 'Q':
  188. X           DontQueue = 1;
  189. X           break;
  190. X
  191. X        case 'f':
  192. X        case 'F':
  193. X           DontFork = 1;
  194. X           break;
  195. X#endif
  196. X        case 'c':
  197. X        case 'C':
  198. X           DoCalendar = 1;
  199. X           if (*arg == '+') {
  200. X              arg++;
  201. X              PARSENUM(CalWeeks, arg);
  202. X          if (!CalWeeks) CalWeeks = 1;
  203. X               } else {
  204. X                 PARSENUM(CalMonths, arg);
  205. X              if (!CalMonths) CalMonths = 1;
  206. X               }
  207. X           break;
  208. X
  209. X        case 's':
  210. X        case 'S':
  211. X           DoSimpleCalendar = 1;
  212. X           PARSENUM(CalMonths, arg);
  213. X           if (!CalMonths) CalMonths = 1;
  214. X           break;
  215. X
  216. X        case 'w':
  217. X        case 'W':
  218. X           PARSENUM(CalWidth, arg);
  219. X           if (CalWidth < 80) CalWidth = 80;
  220. X           break;
  221. X
  222. X        case 'd':
  223. X        case 'D':
  224. X           while (*arg) {
  225. X              switch(*arg++) {
  226. X             case 'e': case 'E': DebugFlag |= DB_ECHO_LINE; break;
  227. X             case 'x': case 'X': DebugFlag |= DB_PRTEXPR;   break;
  228. X             case 't': case 'T': DebugFlag |= DB_PRTTRIG;   break;
  229. X             case 'v': case 'V': DebugFlag |= DB_DUMP_VARS; break;
  230. X             case 'l': case 'L': DebugFlag |= DB_PRTLINE;   break;
  231. X             default:
  232. X                fprintf(ErrFp, "Unknown debug flag '%c'\n", *(arg-1));
  233. X          }
  234. X               }
  235. X           break;
  236. X
  237. X        case 'v':
  238. X        case 'V':
  239. X           DebugFlag |= DB_PRTLINE;
  240. X           ShowAllErrors = 1;
  241. X           break;
  242. X
  243. X        case 'b':
  244. X        case 'B':
  245. X           PARSENUM(ScFormat, arg);
  246. X           if (ScFormat<0 || ScFormat>2) ScFormat=SC_AMPM;
  247. X           break;
  248. X
  249. X        case 'x':
  250. X        case 'X':
  251. X           PARSENUM(MaxSatIter, arg);
  252. X           if (MaxSatIter < 10) MaxSatIter=10;
  253. X           break;
  254. X
  255. X        default:
  256. X           fprintf(ErrFp, "Unknown option '%c'\n", *(arg-1));
  257. X     }
  258. X
  259. X      }
  260. X   }
  261. X
  262. X
  263. X   /* Get the filename. */
  264. X   if (i >= argc) {
  265. X      Usage();
  266. X      exit(1);
  267. X   }
  268. X   InitialFile = argv[i];
  269. X   i++;
  270. X
  271. X   /* Get the date, if any */
  272. X   if (i < argc) {
  273. X      while (i < argc) {
  274. X         arg = argv[i++];
  275. X         FindToken(arg, &tok);
  276. X     switch (tok.type) {
  277. X        case T_Month:
  278. X           if (m != NO_MON) Usage();
  279. X           else m = tok.val;
  280. X           break;
  281. X
  282. X        case T_Day:
  283. X           if (d != NO_DAY) Usage();
  284. X           else d = tok.val;
  285. X           break;
  286. X
  287. X        case T_Year:
  288. X           if (y != NO_YR) Usage();
  289. X           else y = tok.val;
  290. X           break;
  291. X
  292. X        default: Usage();
  293. X         }
  294. X      }
  295. X
  296. X/* Must supply date in the form:  day, mon, yr OR mon, yr */
  297. X      if (m == NO_MON || y == NO_YR) Usage();
  298. X      if (d == NO_DAY) d=1;
  299. X      if (d > DaysInMonth(m, y)) {
  300. X         fprintf(ErrFp, BadDate);
  301. X     Usage();
  302. X      }
  303. X      JulianToday = Julian(y, m, d);
  304. X      if (JulianToday == -1) {
  305. X         fprintf(ErrFp, BadDate);
  306. X     Usage();
  307. X      }
  308. X      CurYear = y;
  309. X      CurMon = m;
  310. X      CurDay = d;
  311. X      if (JulianToday != RealToday) IgnoreOnce = 1;
  312. X   }
  313. X/* Set JulFirst */
  314. X   JulFirst = Julian(CurYear, 0, 1);
  315. X   FirstYear = CurYear;
  316. X}
  317. X
  318. X/***************************************************************/
  319. X/*                                                             */
  320. X/*  Usage                                                      */
  321. X/*                                                             */
  322. X/*  Print the usage info.                                      */
  323. X/*                                                             */
  324. X/***************************************************************/
  325. X#ifdef HAVE_PROTOS
  326. XPUBLIC void Usage(void)
  327. X#else
  328. Xvoid Usage()
  329. X#endif
  330. X{
  331. X   fprintf(ErrFp, "\nREMIND %s Copyright 1992 by David F. Skoll\n\n", VERSION);
  332. X   fprintf(ErrFp, "Usage: remind [options] filename [date]\n\n");
  333. X   fprintf(ErrFp, "Options:\n");
  334. X   fprintf(ErrFp, " -n     Output next occurrence of reminders in simple format\n");
  335. X   fprintf(ErrFp, " -r     Disable RUN directives\n");
  336. X   fprintf(ErrFp, " -c[n]  Produce a calendar for n (default 1) months\n");
  337. X   fprintf(ErrFp, " -c+[n] Produce a calendar for n (default 1) weeks\n");
  338. X   fprintf(ErrFp, " -w[n]  Specify width (default 80) of calendar output\n");
  339. X   fprintf(ErrFp, " -s[n]  Produce 'simple calendar' for n (1) months\n");
  340. X   fprintf(ErrFp, " -v     Verbose mode\n");
  341. X   fprintf(ErrFp, " -o     Ignore ONCE directives\n");
  342. X   fprintf(ErrFp, " -t     Trigger all future reminders regardless of delta\n");
  343. X   fprintf(ErrFp, " -h     'Hush' mode - be very quiet\n");
  344. X#ifdef HAVE_QUEUED
  345. X   fprintf(ErrFp, " -a     Don't trigger timed reminders immediately - just queue them\n");
  346. X   fprintf(ErrFp, " -q     Don't queue timed reminders\n");
  347. X   fprintf(ErrFp, " -f     Trigger timed reminders by staying in foreground\n");
  348. X   fprintf(ErrFp, " -z[n]  Enter daemon mode, waking every n (5) minutes.\n");
  349. X#endif
  350. X   fprintf(ErrFp, " -d...  Debug: e=echo x=expr-eval t=trig v=dumpvars l=showline\n");
  351. X   fprintf(ErrFp, " -e     Divert messages normally sent to stderr to stdout\n");
  352. X   fprintf(ErrFp, " -b[n]  Time format for cal: 0=am/pm, 1=24hr, 2=none\n");
  353. X   fprintf(ErrFp, " -x[n]  Iteration limit for SATISFY clause (def=150)\n");
  354. X   exit(1);
  355. X}
  356. SHAR_EOF
  357. $TOUCH -am 1109141292 init.c &&
  358. chmod 0600 init.c ||
  359. echo "restore of init.c failed"
  360. set `wc -c init.c`;Wc_c=$1
  361. if test "$Wc_c" != "9425"; then
  362.     echo original size 9425, current size $Wc_c
  363. fi
  364. fi
  365. # ============= main.c ==============
  366. if test X"$1" != X"-c" -a -f 'main.c'; then
  367.     echo "File already exists: skipping 'main.c'"
  368. else
  369. echo "x - extracting main.c (Text)"
  370. sed 's/^X//' << 'SHAR_EOF' > main.c &&
  371. X/***************************************************************/
  372. X/*                                                             */
  373. X/*  MAIN.C                                                     */
  374. X/*                                                             */
  375. X/*  Main program loop, as well as miscellaneous conversion     */
  376. X/*  routines, etc.                                             */
  377. X/*                                                             */
  378. X/*  This file is part of REMIND.                               */
  379. X/*  Copyright (C) 1992 by David F. Skoll.                      */
  380. X/*                                                             */
  381. X/***************************************************************/
  382. X#include "config.h"
  383. X#ifdef HAVE_STDLIB_H
  384. X#include <stdlib.h>
  385. X#endif
  386. X#ifdef HAVE_MALLOC_H
  387. X#include <malloc.h>
  388. X#endif
  389. X#include <stdio.h>
  390. X#include <string.h>
  391. X#ifdef HAVE_STDARG
  392. X#include <stdarg.h>
  393. X#else
  394. X#include <varargs.h>
  395. X#endif
  396. X#include <ctype.h>
  397. X
  398. X#ifdef __MSDOS__
  399. X#include <dos.h>
  400. X#endif
  401. X
  402. X
  403. X#ifndef __MSDOS__
  404. X#include <sys/types.h>
  405. X#ifdef SYSV
  406. X#include <time.h>
  407. X#else
  408. X#include <sys/time.h>
  409. X#endif
  410. X#endif /* ifndef __MSDOS__ */
  411. X
  412. X#include "types.h"
  413. X#include "protos.h"
  414. X#include "expr.h"
  415. X#include "globals.h"
  416. X#include "err.h"
  417. X
  418. XPRIVATE void DoReminders ARGS ((void));
  419. X
  420. Xstatic char TPushBuffer[TOKSIZE+1]; /* Buffer for pushing back a token. */
  421. Xstatic char *TokenPushed = NULL;
  422. X
  423. X
  424. X/***************************************************************/
  425. X/***************************************************************/
  426. X/**                                                           **/
  427. X/**  Main Program Loop                                        **/
  428. X/**                                                           **/
  429. X/***************************************************************/
  430. X/***************************************************************/
  431. X#ifdef HAVE_PROTOS
  432. XPUBLIC int main(int argc, char *argv[])
  433. X#else
  434. Xint main(argc, argv)
  435. Xint argc;
  436. Xchar *argv[];
  437. X#endif
  438. X{
  439. X#ifdef HAVE_QUEUED
  440. X   int pid;
  441. X#endif
  442. X
  443. X/* The very first thing to do is to set up ErrFp to be stderr */
  444. X   ErrFp = stderr;
  445. X   
  446. X/* Set up global vars */
  447. X   ArgC = argc;
  448. X   ArgV = argv;
  449. X
  450. X   InitRemind(argc, argv);
  451. X   if(DoCalendar || DoSimpleCalendar) {
  452. X      ProduceCalendar();
  453. X      return 0;
  454. X   }
  455. X
  456. X   /* Not doing a calendar.  Do the regular remind loop */
  457. X   DoReminders();
  458. X
  459. X   if (DebugFlag & DB_DUMP_VARS) DumpVarTable();
  460. X
  461. X   if (!Hush) {
  462. X      if (DestroyOmitContexts())
  463. X    Eprint("Warning: PUSH-OMIT-CONTEXT without matching POP-OMIT-CONTEXT.");
  464. X#ifdef HAVE_QUEUED
  465. X      if (!Daemon && !NextMode && !NumTriggered && !NumQueued) printf("No reminders.\n");
  466. X   else
  467. X      if (!Daemon && !NextMode && !NumTriggered) printf("%d reminder%s queued for later today.\n",
  468. X         NumQueued, (NumQueued == 1) ? "" : "s");
  469. X#else
  470. X      if (!NextMode && !NumTriggered) printf("No reminders.\n");
  471. X#endif
  472. X   }
  473. X
  474. X   /* If it's MS-DOS, reset the file access date */
  475. X#ifdef __MSDOS__
  476. X   if (RealToday == JulianToday) SetAccessDate(InitialFile, RealToday);
  477. X#endif
  478. X
  479. X   /* If there are any background reminders queued up, handle them */
  480. X#ifdef HAVE_QUEUED
  481. X   if (NumQueued || Daemon) {
  482. X
  483. X      if (DontFork) {
  484. X     HandleQueuedReminders();
  485. X     return 0;
  486. X      } else {
  487. X     pid = fork();
  488. X     if (pid == 0) {
  489. X        HandleQueuedReminders();
  490. X        return 0;
  491. X     }
  492. X     if (pid == -1) {
  493. X        fprintf(ErrFp, "Couldn't fork to do queued reminders.\n");
  494. X        return 1;
  495. X     }
  496. X      }
  497. X   }
  498. X#endif
  499. X
  500. X   return 0;
  501. X}
  502. X
  503. X/***************************************************************/
  504. X/*                                                             */
  505. X/*  DoReminders                                                */
  506. X/*                                                             */
  507. X/*  The normal case - we're not doing a calendar.              */
  508. X/*                                                             */
  509. X/***************************************************************/
  510. X#ifdef HAVE_PROTOS
  511. XPRIVATE void DoReminders(void)
  512. X#else
  513. Xstatic void DoReminders()
  514. X#endif
  515. X{
  516. X   int r;
  517. X   Token tok;
  518. X   char *s;
  519. X   Parser p;
  520. X
  521. X   FileAccessDate = GetAccessDate(InitialFile);
  522. X
  523. X   if (FileAccessDate < 0) {
  524. X      fprintf(ErrFp, "remind: Can't access file '%s'.\n", InitialFile);
  525. X      exit(1);
  526. X   }
  527. X
  528. X   r=OpenFile(InitialFile);
  529. X   if (r) {
  530. X      fprintf(ErrFp, "Can't read %s: %s\n", InitialFile, ErrMsg[r]);
  531. X      exit(1);
  532. X   }
  533. X
  534. X   while(1) {
  535. X      r = ReadLine();
  536. X      if (r == E_EOF) return;
  537. X      if (r) {
  538. X     Eprint("Error reading file: %s", ErrMsg[r]);
  539. X     exit(1);
  540. X      }
  541. X      s = FindInitialToken(&tok, CurLine);
  542. X
  543. X      /* Should we ignore it? */
  544. X      if (NumIfs &&
  545. X          tok.type != T_If &&
  546. X          tok.type != T_Else &&
  547. X          tok.type != T_EndIf &&
  548. X          tok.type != T_IfTrig &&
  549. X          ShouldIgnoreLine())
  550. X      {
  551. X          /*** IGNORE THE LINE ***/
  552. X      }
  553. X      else {
  554. X         /* Create a parser to parse the line */
  555. X         CreateParser(s, &p);
  556. X         switch(tok.type) {
  557. X
  558. X            case T_Empty:
  559. X        case T_Comment:
  560. X           break;
  561. X
  562. X        case T_Rem:     r=DoRem(&p);     break;
  563. X        case T_ErrMsg:  r=DoErrMsg(&p);  break;
  564. X        case T_If:      r=DoIf(&p);      break;
  565. X        case T_IfTrig:  r=DoIfTrig(&p);  break;
  566. X        case T_Else:    r=DoElse(&p);    break;
  567. X        case T_EndIf:   r=DoEndif(&p);   break;
  568. X        case T_Include: r=DoInclude(&p); break;
  569. X        case T_Exit:    exit(99);        break;
  570. X        case T_Set:     r=DoSet(&p);     break;
  571. X        case T_Fset:    r=DoFset(&p);    break;
  572. X        case T_UnSet:   r=DoUnset(&p);   break;
  573. X        case T_Clr:     r=DoClear(&p);   break;
  574. X            case T_Debug:   r=DoDebug(&p);   break;
  575. X        case T_Dumpvars: r=DoDump(&p);   break;
  576. X        case T_Banner:  r=DoBanner(&p);  break;
  577. X        case T_Omit:    r=DoOmit(&p);
  578. X                       if (r == E_PARSE_AS_REM) {
  579. X                   DestroyParser(&p);
  580. X                   CreateParser(s, &p);
  581. X                   r=DoRem(&p);
  582. X                }
  583. X                    break;
  584. X        case T_Pop:     r=PopOmitContext(&p);     break;
  585. X        case T_Preserve: r=DoPreserve(&p);  break;
  586. X        case T_Push:    r=PushOmitContext(&p);    break;
  587. X        case T_RemType: if (tok.val == RUN_TYPE) {
  588. X                               r=DoRun(&p);
  589. X                               break;
  590. X                 } else {
  591. X                    CreateParser(CurLine, &p);
  592. X                r=DoRem(&p);
  593. X                break;
  594. X                 }
  595. X                 
  596. X
  597. X     /* If we don't recognize the command, do a REM by default */
  598. X     /* Note:  Since the parser hasn't been used yet, we don't */
  599. X     /* need to destroy it here. */
  600. X
  601. X        default:        CreateParser(CurLine, &p); r=DoRem(&p); break;
  602. X         }
  603. X         if (r && (!Hush || r != E_RUN_DISABLED)) Eprint("%s", ErrMsg[r]);
  604. X
  605. X         /* Destroy the parser - free up resources it may be tying up */
  606. X         DestroyParser(&p);
  607. X      }
  608. X   }
  609. X}
  610. X
  611. X/***************************************************************/
  612. X/*                                                             */
  613. X/*  Julian                                                     */
  614. X/*                                                             */
  615. X/*  Given day, month, year, return Julian date in days since   */
  616. X/*  1 January 1990.                                            */
  617. X/*                                                             */
  618. X/***************************************************************/
  619. X#ifdef HAVE_PROTOS
  620. XPUBLIC int Julian(int year, int month, int day)
  621. X#else
  622. Xint Julian(year, month, day)
  623. Xint day, month, year;
  624. X#endif
  625. X{
  626. X   register int jul, iy;
  627. X
  628. X   if (year < BASE) return -1;
  629. X
  630. X   if (JulFirst == -1 || year < FirstYear) {
  631. X      jul = 0;
  632. X      for (iy = BASE; iy < year; iy++) jul += DaysInYear(iy);
  633. X   } else {
  634. X      jul = JulFirst;
  635. X      for (iy = FirstYear; iy < year; iy++) jul += DaysInYear(iy);
  636. X   }
  637. X
  638. X   return jul + MonthIndex[IsLeapYear(year)][month] + day - 1;
  639. X}
  640. X
  641. X/***************************************************************/
  642. X/*                                                             */
  643. X/*  FromJulian                                                 */
  644. X/*                                                             */
  645. X/*  Convert a Julian date to year, month, day.                 */
  646. X/*                                                             */
  647. X/***************************************************************/
  648. X#ifdef HAVE_PROTOS
  649. XPUBLIC void FromJulian(int jul, int *y, int *m, int *d)
  650. X#else
  651. Xvoid FromJulian(jul, y, m, d)
  652. Xint jul;
  653. Xint *y, *m, *d;
  654. X#endif
  655. X{
  656. X   register int t;
  657. X
  658. X   if (jul >= JulFirst && JulFirst != -1) {
  659. X      *y = FirstYear;
  660. X      jul -= JulFirst;
  661. X   } else *y = BASE;
  662. X
  663. X   *m = 0;
  664. X
  665. X   t = DaysInYear(*y);
  666. X   while (jul >= t) {
  667. X      jul -= t;
  668. X      (*y)++;
  669. X      t = DaysInYear(*y);
  670. X   }
  671. X
  672. X   t = DaysInMonth(*m, *y);
  673. X   while (jul >= t) {
  674. X      jul -= t;
  675. X      (*m)++;
  676. X      t = DaysInMonth(*m, *y);
  677. X   }
  678. X   *d = jul + 1;
  679. X   return;
  680. X}
  681. X
  682. X/***************************************************************/
  683. X/*                                                             */
  684. X/*  ParseChar                                                  */
  685. X/*                                                             */
  686. X/*  Parse a character from a parse pointer.  If peek is non-   */
  687. X/*  zero, then just peek ahead; don't advance pointer.         */
  688. X/*                                                             */
  689. X/***************************************************************/
  690. X#ifdef HAVE_PROTOS
  691. XPUBLIC int ParseChar(ParsePtr p, int *err, int peek)
  692. X#else
  693. Xint ParseChar(p, err, peek)
  694. XParsePtr p;
  695. Xint *err;
  696. Xint peek;
  697. X#endif
  698. X{
  699. X   Value val;
  700. X   int r;
  701. X
  702. X   *err = 0;
  703. X   if (TokenPushed && *TokenPushed)
  704. X      if (peek) return *TokenPushed;
  705. X      else      return *TokenPushed++;
  706. X
  707. X   while(1) {
  708. X      if (p->isnested) {
  709. X     if (*(p->epos))
  710. X        if (peek) return *(p->epos);
  711. X        else      return *(p->epos++);
  712. X     free(p->etext);  /* End of substituted expression */
  713. X     p->etext = NULL;
  714. X     p->epos = NULL;
  715. X     p->isnested = 0;
  716. X      }
  717. X      if (!*(p->pos)) {
  718. X     return 0;
  719. X      }
  720. X      if (*p->pos != BEG_OF_EXPR || !p->allownested)
  721. X     if (peek) return *(p->pos);
  722. X     else      return *(p->pos++);
  723. X      p->pos++;
  724. X      r = EvalExpr(&(p->pos), &val);
  725. X      if (r) {
  726. X     *err = r;
  727. X     DestroyParser(p);
  728. X     return 0;
  729. X      }
  730. X      if (*p->pos != END_OF_EXPR) {
  731. X     *err = E_MISS_END;
  732. X     DestroyParser(p);
  733. X     DestroyValue(&val);
  734. X     return 0;
  735. X      }
  736. X      p->pos++;
  737. X      r = DoCoerce(STR_TYPE, &val);
  738. X      if (r) { *err = r; return 0; }
  739. X      p->etext = val.v.str;
  740. X      val.type = ERR_TYPE; /* So it's not accidentally destroyed! */
  741. X      p->isnested = 1;
  742. X      p->epos = p->etext;
  743. X   }
  744. X}
  745. X
  746. X/***************************************************************/
  747. X/*                                                             */
  748. X/*  ParseNonSpaceChar                                          */
  749. X/*                                                             */
  750. X/*  Parse the next non-space character.                        */
  751. X/*                                                             */
  752. X/***************************************************************/
  753. X#ifdef HAVE_PROTOS
  754. XPUBLIC int ParseNonSpaceChar(ParsePtr p, int *err, int peek)
  755. X#else
  756. Xint ParseNonSpaceChar(p, err, peek)
  757. XParsePtr p;
  758. Xint *err;
  759. Xint peek;
  760. X#endif
  761. X{
  762. X   int ch;
  763. X
  764. X   ch = ParseChar(p, err, 1);
  765. X   if (*err) return 0;
  766. X
  767. X   while (isspace(ch)) {
  768. X      ParseChar(p, err, 0);   /* Guaranteed to work */
  769. X      ch = ParseChar(p, err, 1);
  770. X      if (*err) return 0;
  771. X   }
  772. X   if (!peek) ch = ParseChar(p, err, 0);  /* Guaranteed to work */
  773. X   return ch;
  774. X}
  775. X
  776. X/***************************************************************/
  777. X/*                                                             */
  778. X/*  ParseToken                                                 */
  779. X/*                                                             */
  780. X/*  Parse a token delimited by whitespace.                     */
  781. X/*                                                             */
  782. X/***************************************************************/
  783. X#ifdef HAVE_PROTOS
  784. XPUBLIC int ParseToken(ParsePtr p, char *out)
  785. X#else
  786. Xint ParseToken(p, out)
  787. XParsePtr p;
  788. Xchar *out;
  789. X#endif
  790. X{
  791. X   int c, err;
  792. X   int len = 0;
  793. X   
  794. X   *out = 0;
  795. X
  796. X   c = ParseChar(p, &err, 0);
  797. X   if (err) return err;
  798. X   while (c && isspace(c)) {
  799. X      c = ParseChar(p, &err, 0);
  800. X      if (err) return err;
  801. X   }
  802. X   if (!c) return OK;
  803. X   *out++ = c;
  804. X   len++;
  805. X
  806. X   while (c && !isspace(c)) {
  807. X      c = ParseChar(p, &err, 0);
  808. X      if (err) return err;
  809. X      if (len < TOKSIZE && c && !isspace(c)) {
  810. X         *out++ = c;
  811. X     len++;
  812. X      }
  813. X   }
  814. X   *out = 0;
  815. X   return OK;
  816. X}
  817. X
  818. X/***************************************************************/
  819. X/*                                                             */
  820. X/*  ParseIdentifier                                            */
  821. X/*                                                             */
  822. X/*  Parse a valid identifier - ie, alpha or underscore         */
  823. X/*  followed by alphanum.  Return E_BAD_ID if identifier is    */
  824. X/*  invalid.                                                   */
  825. X/*                                                             */
  826. X/***************************************************************/
  827. X#ifdef HAVE_PROTOS
  828. XPUBLIC int ParseIdentifier(ParsePtr p, char *out)
  829. X#else
  830. Xint ParseIdentifier(p, out)
  831. XParsePtr p;
  832. Xchar *out;
  833. X#endif
  834. X{
  835. X   int c, err;
  836. X   int len = 0;
  837. X   
  838. X   *out = 0;
  839. X
  840. X   c = ParseChar(p, &err, 0);
  841. X   if (err) return err;
  842. X   while (c && isspace(c)) {
  843. X      c = ParseChar(p, &err, 0);
  844. X      if (err) return err;
  845. X   }
  846. X   if (!c) return E_EOLN;
  847. X   if (c != '_' && !isalpha(c)) return E_BAD_ID;
  848. X   *out++ = c;
  849. X   *out = 0;
  850. X   len++;
  851. X
  852. X   while (1) {
  853. X      c = ParseChar(p, &err, 1);
  854. X      if (err) return err;
  855. X      if (c != '_' && !isalnum(c)) return OK;
  856. X
  857. X      if (len < TOKSIZE) {
  858. X     c = ParseChar(p, &err, 0);  /* Guaranteed to work */
  859. X     *out++ = c;
  860. X     *out = 0;
  861. X     len++;
  862. X      }
  863. X   }
  864. X}
  865. X/***************************************************************/
  866. X/*                                                             */
  867. X/* EvaluateExpr                                                */
  868. X/*                                                             */
  869. X/* We are expecting an expression here.  Evaluate it and       */
  870. X/* return the value.                                           */
  871. X/*                                                             */
  872. X/***************************************************************/
  873. X#ifdef HAVE_PROTOS
  874. XPUBLIC int EvaluateExpr(ParsePtr p, Value *v)
  875. X#else
  876. Xint EvaluateExpr(p, v)
  877. XParsePtr p;
  878. XValue *v;
  879. X#endif
  880. X{
  881. X
  882. X   int bracketed = 0;
  883. X   int r;
  884. X
  885. X   if (p->isnested) return E_PARSE_ERR;  /* Can't nest expressions */
  886. X   while (isspace(*p->pos)) (p->pos)++;
  887. X   if (!p->pos) return E_PARSE_ERR;      /* Missing expression */
  888. X   if (*p->pos == BEG_OF_EXPR) {
  889. X      (p->pos)++;
  890. X      bracketed = 1;
  891. X   }
  892. X   r = EvalExpr(&(p->pos), v);
  893. X   if (r) return r;
  894. X   if (bracketed) {
  895. X      if (*p->pos != END_OF_EXPR) return E_MISS_END;
  896. X      (p->pos)++;
  897. X   }
  898. X   return OK;
  899. X}
  900. X
  901. X/***************************************************************/
  902. X/*                                                             */
  903. X/*  Eprint - print an error message.                           */
  904. X/*                                                             */
  905. X/***************************************************************/
  906. X#ifdef HAVE_STDARG
  907. X#ifdef HAVE_PROTOS
  908. XPUBLIC void Eprint(const char *fmt, ...)
  909. X#else
  910. Xvoid Eprint(fmt)
  911. Xchar *fmt;
  912. X#endif
  913. X#else
  914. X/*VARARGS0*/
  915. Xvoid Eprint(va_alist)
  916. Xva_dcl
  917. X#endif
  918. X{
  919. X   va_list argptr;
  920. X#ifndef HAVE_STDARG
  921. X   char *fmt;
  922. X#endif
  923. X   
  924. X   /* Check if more than one error msg. from this line */
  925. X   if (!FreshLine && !ShowAllErrors) return;
  926. X
  927. X   if (FreshLine) {
  928. X      FreshLine = 0;
  929. X      (void) fprintf(ErrFp, "%s(%d): ", FileName, LineNo);
  930. X      if (DebugFlag & DB_PRTLINE) OutputLine(ErrFp);
  931. X   } else fprintf(ErrFp, "       ");
  932. X
  933. X#ifdef HAVE_STDARG
  934. X   va_start(argptr, fmt);
  935. X#else
  936. X   va_start(argptr);
  937. X   fmt = va_arg(argptr, char *);
  938. X#endif
  939. X   (void) vfprintf(ErrFp, fmt, argptr);
  940. X   (void) fputc('\n', ErrFp);
  941. X#ifndef HAVE_STDARG
  942. X   va_end(argptr)
  943. X#endif
  944. X   return;
  945. X}
  946. X
  947. X/***************************************************************/
  948. X/*                                                             */
  949. X/*  OutputLine                                                 */
  950. X/*                                                             */
  951. X/*  Output a line from memory buffer to a file pointer.  This  */
  952. X/*  simply involves escaping newlines.                         */
  953. X/*                                                             */
  954. X/***************************************************************/
  955. X#ifdef HAVE_PROTOS
  956. XPUBLIC void OutputLine(FILE *fp)
  957. X#else
  958. Xvoid OutputLine(fp)
  959. XFILE *fp;
  960. X#endif
  961. X{
  962. X   register char *s = CurLine;
  963. X   while (*s) {
  964. X      if (*s == '\n') putc('\\', fp);
  965. X      putc(*s, fp);
  966. X      s++;
  967. X   }
  968. X   if (*(s-1) != '\n') putc('\n', fp);
  969. X}
  970. X
  971. X/***************************************************************/
  972. X/*                                                             */
  973. X/*  CreateParser                                               */
  974. X/*                                                             */
  975. X/*  Create a parser given a string buffer                      */
  976. X/*                                                             */
  977. X/***************************************************************/
  978. X#ifdef HAVE_PROTOS
  979. XPUBLIC void CreateParser(char *s, ParsePtr p)
  980. X#else
  981. Xvoid CreateParser(s, p)
  982. Xchar *s;
  983. XParsePtr p;
  984. X#endif
  985. X{
  986. X   p->text = s;
  987. X   p->pos = s;
  988. X   p->isnested = 0;
  989. X   p->epos = NULL;
  990. X   p->etext = NULL;
  991. X   p->allownested = 1;
  992. X   TokenPushed = NULL;
  993. X}
  994. X
  995. X/***************************************************************/
  996. X/*                                                             */
  997. X/*  DestroyParser                                              */
  998. X/*                                                             */
  999. X/*  Destroy a parser, freeing up resources used.               */
  1000. X/*                                                             */
  1001. X/***************************************************************/
  1002. X#ifdef HAVE_PROTOS
  1003. XPUBLIC void DestroyParser(ParsePtr p)
  1004. X#else
  1005. Xvoid DestroyParser(p)
  1006. XParsePtr p;
  1007. X#endif
  1008. X{
  1009. X   if (p->isnested && p->etext) {
  1010. X      free(p->etext);
  1011. X      p->etext = NULL;
  1012. X      p->isnested = 0;
  1013. X   }
  1014. X}
  1015. X
  1016. X/***************************************************************/
  1017. X/*                                                             */
  1018. X/*  PushToken - one level of token pushback.  This is          */
  1019. X/*  GLOBAL, not on a per-parser basis.                         */
  1020. X/*                                                             */
  1021. X/***************************************************************/
  1022. X#ifdef HAVE_PROTOS
  1023. XPUBLIC void PushToken(const char *tok)
  1024. X#else
  1025. Xvoid PushToken(tok)
  1026. Xchar *tok;
  1027. X#endif
  1028. X{
  1029. X   TokenPushed = TPushBuffer;
  1030. X   strcpy(TPushBuffer, tok);
  1031. X   strcat(TPushBuffer, " ");  /* Separate the pushed token from the next
  1032. X                         token */
  1033. X   
  1034. X}
  1035. X
  1036. X/***************************************************************/
  1037. X/*                                                             */
  1038. X/*  SystemTime                                                 */
  1039. X/*                                                             */
  1040. X/*  Return the system time in seconds past midnight            */
  1041. X/*                                                             */
  1042. X/***************************************************************/
  1043. X#ifdef HAVE_PROTOS
  1044. XPUBLIC long SystemTime(void)
  1045. X#else
  1046. Xlong SystemTime()
  1047. X#endif
  1048. X{
  1049. X#ifdef __MSDOS__
  1050. X#ifdef __TURBOC__
  1051. X/* Get time in Turbo C */
  1052. X
  1053. X   struct time t;
  1054. X
  1055. X   gettime(&t);
  1056. X   return (long) t.ti_hour * 3600L + (long) t.ti_min * 60L +
  1057. X      (long) t.ti_sec;
  1058. X
  1059. X#else
  1060. X/* Get time in Microsoft C */
  1061. X   struct dostime_t tloc;
  1062. X   _dos_gettime(&tloc);
  1063. X   return (long) tloc.hour * 3600L + (long) tloc.minute * 60L +
  1064. X      (long) tloc.second;
  1065. X
  1066. X#endif
  1067. X#else
  1068. X/* Get time in Unix */
  1069. X  time_t tloc;
  1070. X  struct tm *t;
  1071. X
  1072. X   (void) time(&tloc);
  1073. X   t = localtime(&tloc);
  1074. X   return (long) t->tm_hour * 3600L + (long) t->tm_min * 60L +
  1075. X      (long) t->tm_sec;
  1076. X#endif
  1077. X}
  1078. X/***************************************************************/
  1079. X/*                                                             */
  1080. X/*  SystemDate                                                 */
  1081. X/*                                                             */
  1082. X/*  Obtains today's date.  Returns Julian date or -1 for       */
  1083. X/*  failure.  (Failure happens if sys date is before BASE      */
  1084. X/*  year.)                                                     */
  1085. X/*                                                             */
  1086. X/***************************************************************/
  1087. X#ifdef HAVE_PROTOS
  1088. XPUBLIC int SystemDate(int *y, int *m, int *d)
  1089. X#else
  1090. Xint SystemDate(y, m, d)
  1091. Xint *d;
  1092. Xint *m;
  1093. Xint *y;
  1094. X#endif
  1095. X{
  1096. X#ifdef __MSDOS__
  1097. X#ifdef __TURBOC__
  1098. X/* Get today's date in Turbo C */
  1099. X   struct date da;
  1100. X
  1101. X   getdate(&da);
  1102. X   *y = da.da_year;
  1103. X   *m = da.da_mon - 1;
  1104. X   *d = da.da_day;
  1105. X#else
  1106. X/* Get today's date in Microsoft C */
  1107. X   struct dosdate_t buf;
  1108. X
  1109. X   _dos_getdate(&buf);
  1110. X
  1111. X   *d = buf.day;
  1112. X   *m = buf.month - 1;
  1113. X   *y = buf.year;
  1114. X#endif
  1115. X#else
  1116. X/* Get today's date in UNIX */
  1117. X  time_t tloc;
  1118. X  struct tm *t;
  1119. X
  1120. X   (void) time(&tloc);
  1121. X   t = localtime(&tloc);
  1122. X
  1123. X   *d = t->tm_mday;
  1124. X   *m = t->tm_mon;
  1125. X   *y = t->tm_year + 1900;
  1126. X#endif
  1127. X   return Julian(*y, *m, *d);
  1128. X}
  1129. X
  1130. X
  1131. X/***************************************************************/
  1132. X/*                                                             */
  1133. X/*  DoIf - handle the IF command.                              */
  1134. X/*                                                             */
  1135. X/***************************************************************/
  1136. X#ifdef HAVE_PROTOS
  1137. XPUBLIC int DoIf(ParsePtr p)
  1138. X#else
  1139. Xint DoIf(p)
  1140. XParsePtr p;
  1141. X#endif
  1142. X{
  1143. X   Value v;
  1144. X   int r;
  1145. X   unsigned syndrome;
  1146. X
  1147. X   if (NumIfs >= IF_NEST) return E_NESTED_IF;
  1148. X
  1149. X   if (ShouldIgnoreLine()) syndrome = IF_TRUE | BEFORE_ELSE;
  1150. X   else {
  1151. X      if (r = EvaluateExpr(p, &v)) {
  1152. X         syndrome = IF_TRUE | BEFORE_ELSE;
  1153. X     Eprint("%s", ErrMsg[r]);
  1154. X      } else 
  1155. X         if ( (v.type != STR_TYPE && v.v.val) ||
  1156. X              (v.type == STR_TYPE && strcmp(v.v.str, "")) )
  1157. X            syndrome = IF_TRUE | BEFORE_ELSE;
  1158. X         else
  1159. X            syndrome = IF_FALSE | BEFORE_ELSE;
  1160. X   }
  1161. X
  1162. X   NumIfs++;
  1163. X   IfFlags &= ~(IF_MASK << (2*NumIfs - 2));
  1164. X   IfFlags |= syndrome << (2 * NumIfs - 2);
  1165. X   if (ShouldIgnoreLine()) return OK;
  1166. X   return VerifyEoln(p);
  1167. X}
  1168. X
  1169. X
  1170. X/***************************************************************/
  1171. X/*                                                             */
  1172. X/*  DoElse - handle the ELSE command.                          */
  1173. X/*                                                             */
  1174. X/***************************************************************/
  1175. X#ifdef HAVE_PROTOS
  1176. XPUBLIC int DoElse(ParsePtr p)
  1177. X#else
  1178. Xint DoElse(p)
  1179. XParsePtr p;
  1180. X#endif
  1181. X{
  1182. X   unsigned syndrome;
  1183. X
  1184. X   if (!NumIfs) return E_ELSE_NO_IF;
  1185. X
  1186. X   syndrome = IfFlags >> (2 * NumIfs - 2);
  1187. X
  1188. X   if ((syndrome & IF_ELSE_MASK) == AFTER_ELSE) return E_ELSE_NO_IF;
  1189. X
  1190. X   IfFlags |= AFTER_ELSE << (2 * NumIfs - 2);
  1191. X   return VerifyEoln(p);
  1192. X}
  1193. X
  1194. X/***************************************************************/
  1195. X/*                                                             */
  1196. X/*  DoEndif - handle the Endif command.                        */
  1197. X/*                                                             */
  1198. X/***************************************************************/
  1199. X#ifdef HAVE_PROTOS
  1200. XPUBLIC int DoEndif(ParsePtr p)
  1201. X#else
  1202. Xint DoEndif(p)
  1203. XParsePtr p;
  1204. X#endif
  1205. X{
  1206. X   if (!NumIfs) return E_ENDIF_NO_IF;
  1207. X   NumIfs--;
  1208. X   return VerifyEoln(p);
  1209. X}
  1210. X
  1211. X/***************************************************************/
  1212. X/*                                                             */
  1213. X/*  DoIfTrig                                                   */
  1214. X/*                                                             */
  1215. X/*  Handle the IFTRIG command.                                 */
  1216. X/*                                                             */
  1217. X/***************************************************************/
  1218. X#ifdef HAVE_PROTOS
  1219. XPUBLIC int DoIfTrig(ParsePtr p)
  1220. X#else
  1221. Xint DoIfTrig(p)
  1222. XParsePtr p;
  1223. X#endif
  1224. X{
  1225. X   int r;
  1226. X   unsigned syndrome;
  1227. X   Trigger trig;
  1228. X   TimeTrig tim;
  1229. X   int jul;
  1230. X
  1231. X
  1232. X   if (NumIfs >= IF_NEST) return E_NESTED_IF;
  1233. X   if (ShouldIgnoreLine()) syndrome = IF_TRUE | BEFORE_ELSE;
  1234. X   else {
  1235. X      if (r=ParseRem(p, &trig, &tim)) return r;
  1236. X      if (trig.typ != NO_TYPE) return E_PARSE_ERR;
  1237. X      jul = ComputeTrigger(JulianToday, &trig, &r);
  1238. X      if (r) syndrome = IF_TRUE | BEFORE_ELSE;
  1239. X      else {
  1240. X         if (ShouldTriggerReminder(&trig, &tim, jul))
  1241. X        syndrome = IF_TRUE | BEFORE_ELSE;
  1242. X     else
  1243. X        syndrome = IF_FALSE | BEFORE_ELSE;
  1244. X      }
  1245. X   }
  1246. X   NumIfs++;
  1247. X   IfFlags &= ~(IF_MASK << (2*NumIfs - 2));
  1248. X   IfFlags |= syndrome << (2 * NumIfs - 2);
  1249. X   return OK;
  1250. X}
  1251. X
  1252. X       
  1253. X/***************************************************************/
  1254. X/*                                                             */
  1255. X/*  ShouldIgnoreLine - given the current state of the IF       */
  1256. X/*  stack, should we ignore the current line?                  */
  1257. X/*                                                             */
  1258. X/***************************************************************/
  1259. X#ifdef HAVE_PROTOS
  1260. XPUBLIC int ShouldIgnoreLine(void)
  1261. X#else
  1262. Xint ShouldIgnoreLine()
  1263. X#endif
  1264. X{
  1265. X   register int i, syndrome;
  1266. X
  1267. X/* Algorithm - go from outer to inner, and if any should be ignored, then
  1268. X   ignore the whole. */
  1269. X
  1270. X   for (i=0; i<NumIfs; i++) {
  1271. X      syndrome = (IfFlags >> (i*2)) & IF_MASK;
  1272. X      if (syndrome == IF_TRUE+AFTER_ELSE ||
  1273. X          syndrome == IF_FALSE+BEFORE_ELSE) return 1;
  1274. X   }
  1275. X   return 0;
  1276. X}
  1277. X
  1278. X/***************************************************************/
  1279. X/*                                                             */
  1280. X/*  VerifyEoln                                                 */
  1281. X/*                                                             */
  1282. X/*  Verify that current line contains no more tokens.          */
  1283. X/*                                                             */
  1284. X/***************************************************************/
  1285. X#ifdef HAVE_PROTOS
  1286. XPUBLIC int VerifyEoln(ParsePtr p)
  1287. X#else
  1288. Xint VerifyEoln(p)
  1289. XParsePtr p;
  1290. X#endif
  1291. X{
  1292. X   int r;
  1293. X
  1294. X   if (r = ParseToken(p, TokBuffer)) return r;
  1295. X   if (*TokBuffer && (*TokBuffer != '#') && (*TokBuffer != ';')) {
  1296. X      Eprint("Expecting end-of-line, found '%s'", TokBuffer);
  1297. X      return E_EXTRANEOUS_TOKEN;
  1298. X   }
  1299. X   return OK;
  1300. X}
  1301. X
  1302. X/***************************************************************/
  1303. X/*                                                             */
  1304. X/*  DoDebug                                                    */
  1305. X/*                                                             */
  1306. X/*  Set the debug options under program control.               */
  1307. X/*                                                             */
  1308. X/***************************************************************/
  1309. X#ifdef HAVE_PROTOS
  1310. XPUBLIC int DoDebug(ParsePtr p)
  1311. X#else
  1312. Xint DoDebug(p)
  1313. XParsePtr p;
  1314. X#endif
  1315. X{
  1316. X   int err;
  1317. X   int ch;
  1318. X   int val=1;     
  1319. X
  1320. X   while(1) {
  1321. X      ch = ParseChar(p, &err, 0);
  1322. X      if (err) return err;
  1323. X      switch(ch) {
  1324. X         case '#':
  1325. X     case ';':
  1326. X     case 0:
  1327. X        return OK;
  1328. X
  1329. X     case ' ':
  1330. X     case '\t':
  1331. X        break;
  1332. X
  1333. X     case '+':
  1334. X        val = 1;
  1335. X        break;
  1336. X
  1337. X     case '-':
  1338. X        val = 0;
  1339. X        break;
  1340. X      case 'e':
  1341. X      case 'E':
  1342. X        if (val) DebugFlag |=  DB_ECHO_LINE;
  1343. X        else     DebugFlag &= ~DB_ECHO_LINE;
  1344. X        break;
  1345. X
  1346. X      case 'x':
  1347. X      case 'X':
  1348. X        if (val) DebugFlag |=  DB_PRTEXPR;
  1349. X        else     DebugFlag &= ~DB_PRTEXPR;
  1350. X        break;
  1351. X
  1352. X      case 't':
  1353. X      case 'T':
  1354. X        if (val) DebugFlag |=  DB_PRTTRIG;
  1355. X        else     DebugFlag &= ~DB_PRTTRIG;
  1356. X        break;
  1357. X
  1358. X      case 'v':
  1359. X      case 'V':
  1360. X        if (val) DebugFlag |=  DB_DUMP_VARS;
  1361. X        else     DebugFlag &= ~DB_DUMP_VARS;
  1362. X        break;
  1363. X
  1364. X      case 'l':
  1365. X      case 'L':
  1366. X        if (val) DebugFlag |=  DB_PRTLINE;
  1367. X        else     DebugFlag &= ~DB_PRTLINE;
  1368. X        break;
  1369. X
  1370. X      }
  1371. X   }
  1372. X}
  1373. X
  1374. X/***************************************************************/
  1375. X/*                                                             */
  1376. X/*  DoBanner                                                   */
  1377. X/*                                                             */
  1378. X/*  Set the banner to be printed just before the first         */
  1379. X/*  reminder is issued.                                        */
  1380. X/*                                                             */
  1381. X/***************************************************************/
  1382. X#ifdef HAVE_PROTOS
  1383. XPUBLIC int DoBanner(ParsePtr p)
  1384. X#else
  1385. Xint DoBanner(p)
  1386. XParsePtr p;
  1387. X#endif
  1388. X{
  1389. X   int err;
  1390. X   int c;
  1391. X   char buf[LINELEN];   /* So we don't mess up the banner if an error occurs */
  1392. X   char *s;
  1393. X
  1394. X   c = ParseChar(p, &err, 0);
  1395. X   if (err) return err;
  1396. X   while (isspace(c)) {
  1397. X      c = ParseChar(p, &err, 0);
  1398. X      if (err) return err;
  1399. X   }
  1400. X   if (!c) return E_EOLN;
  1401. X   s = buf;
  1402. X
  1403. X   while(c) {
  1404. X      *s++ = c;
  1405. X      c = ParseChar(p, &err, 0);
  1406. X      if (err) return err;
  1407. X   }
  1408. X   *s++ = 0;
  1409. X   strcpy(Banner, buf);
  1410. X   return OK;
  1411. X}
  1412. X
  1413. X/***************************************************************/
  1414. X/*                                                             */
  1415. X/*  DoRun                                                      */
  1416. X/*                                                             */
  1417. X/*  Enable or disable the RUN command under program control    */
  1418. X/*                                                             */
  1419. X/*                                                             */
  1420. X/***************************************************************/
  1421. X#ifdef HAVE_PROTOS
  1422. XPUBLIC int DoRun(ParsePtr p)
  1423. X#else
  1424. Xint DoRun(p)
  1425. XParsePtr p;
  1426. X#endif
  1427. X{
  1428. X   int r;
  1429. X
  1430. X   if (!TopLevel())
  1431. X      return OK; /* Silently ignore RUN command in included file */
  1432. X
  1433. X   if (r=ParseToken(p, TokBuffer)) return r;
  1434. X
  1435. X   if (StriEq(TokBuffer, "ON"))
  1436. X      RunDisabled &= ~RUN_SCRIPT;
  1437. X   else if (StriEq(TokBuffer, "OFF"))
  1438. X      RunDisabled |= RUN_SCRIPT;
  1439. X   else return E_PARSE_ERR;
  1440. X
  1441. X   return VerifyEoln(p);
  1442. X}
  1443. X
  1444. X/***************************************************************/
  1445. X/*                                                             */
  1446. X/*  DoErrMsg                                                   */
  1447. X/*                                                             */
  1448. X/*  Issue an error message under program control.              */
  1449. X/*                                                             */
  1450. X/***************************************************************/
  1451. X#ifdef HAVE_PROTOS
  1452. XPUBLIC int DoErrMsg(ParsePtr p)
  1453. X#else
  1454. Xint DoErrMsg(p)
  1455. XParsePtr p;
  1456. X#endif
  1457. X{
  1458. X   TimeTrig tt;
  1459. X   Trigger t;
  1460. X   int r;
  1461. X   char *s;
  1462. X
  1463. X   t.typ = MSG_TYPE;
  1464. X   tt.ttime = SystemTime() / 60;
  1465. X   if (r=DoSubst(p, SubstBuffer, &t, &tt, JulianToday, NORMAL_MODE)) return r;
  1466. X   s = SubstBuffer;
  1467. X   while (isspace(*s)) s++;
  1468. X   fprintf(ErrFp, "%s\n", s);
  1469. X   return OK;
  1470. X}
  1471. X
  1472. SHAR_EOF
  1473. $TOUCH -am 1109141292 main.c &&
  1474. chmod 0600 main.c ||
  1475. echo "restore of main.c failed"
  1476. set `wc -c main.c`;Wc_c=$1
  1477. if test "$Wc_c" != "30576"; then
  1478.     echo original size 30576, current size $Wc_c
  1479. fi
  1480. fi
  1481. echo "End of part 7, continue with part 8"
  1482. exit 0
  1483.  
  1484. exit 0 # Just in case...
  1485.