home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #26 / NN_1992_26.iso / spool / comp / sources / misc / 4069 < prev    next >
Encoding:
Text File  |  1992-11-09  |  42.2 KB  |  1,492 lines

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