home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2027 < prev    next >
Internet Message Format  |  1990-12-28  |  31KB

  1. From: dfs@doe.carleton.ca (David F. Skoll)
  2. Newsgroups: alt.sources
  3. Subject: REMIND 2.0 02/03
  4. Message-ID: <dfs.657486181@yar>
  5. Date: 1 Nov 90 19:03:01 GMT
  6.  
  7. ------------ CUT HERE ---
  8. #!/bin/sh
  9. # This is part 02 of Remind 2.0
  10. if touch 2>&1 | fgrep 'amc' > /dev/null
  11.  then TOUCH=touch
  12.  else TOUCH=true
  13. fi
  14. # ============= main.c ==============
  15. if test X"$1" != X"-c" -a -f 'main.c'; then
  16.     echo "File already exists: skipping 'main.c'"
  17. else
  18. sed 's/^X//' << 'SHAR_EOF' > main.c &&
  19. X/***************************************************************/
  20. X/*                                                             */
  21. X/*  REMIND.C - version 2.0                                     */
  22. X/*                                                             */
  23. X/*  By David Skoll - 22 September 1990                         */
  24. X/*                                                             */
  25. X/*  (C) 1990 by David Skoll - all rights reserved              */
  26. X/*                                                             */
  27. X/***************************************************************/
  28. X
  29. X#include <stdio.h>
  30. X#include <string.h>
  31. X#include <ctype.h>
  32. X#ifndef UNIX
  33. X#include <stdlib.h>
  34. X#include <dos.h>
  35. X#include <stdarg.h>
  36. X#else UNIX
  37. X#include <varargs.h>
  38. X#include <sys/types.h>
  39. X#include <sys/time.h>
  40. X#endif UNIX
  41. X#include "defines.h"
  42. X#include "protos.h"
  43. X
  44. X
  45. X/* List of months */
  46. Xchar *MonthName[] = {
  47. X   "January", "February", "March", "April", "May", "June",
  48. X   "July", "August", "September", "October", "November", "December"
  49. X};
  50. X
  51. X/* List of weekdays */
  52. Xchar *DayName[] = {
  53. X   "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"
  54. X};   
  55. X               
  56. X/* List of recognized tokens */
  57. X
  58. XToken keywd[] = {
  59. X   { "BANNER",    Banner_t, 0 },
  60. X   { "OMIT",      Omit_t,   0 },
  61. X   { "REM",       Rem_t,    0 },
  62. X   { "January",   Month_t,  0 },
  63. X   { "February",  Month_t,  1 },
  64. X   { "March",     Month_t,  2 },
  65. X   { "April",     Month_t,  3 },
  66. X   { "May",       Month_t,  4 },
  67. X   { "June",      Month_t,  5 },
  68. X   { "July",      Month_t,  6 },
  69. X   { "August",    Month_t,  7 },
  70. X   { "September", Month_t,  8 },
  71. X   { "October",   Month_t,  9 },
  72. X   { "November",  Month_t,  10 },
  73. X   { "December",  Month_t,  11 },
  74. X   { "Monday",    WkDay_t,  0  },
  75. X   { "Tuesday",   WkDay_t,  1  },
  76. X   { "Wednesday", WkDay_t,  2  },
  77. X   { "Thursday",  WkDay_t,  3  },
  78. X   { "Friday",    WkDay_t,  4  },
  79. X   { "Saturday",  WkDay_t,  5  },
  80. X   { "Sunday",    WkDay_t,  6  },
  81. X   { "MSG",       Msg_t,    0 },
  82. X   { "RUN",       Run_t,    0 },
  83. X   { "ONCE",      Once_t,   0 },
  84. X   { "INCLUDE",   Include_t, 0}
  85. X};
  86. X
  87. X/* List of days in month - Feb MUST be 29 for CheckDate to work. */
  88. Xint MonthDays[] = {
  89. X   31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  90. X};
  91. X
  92. X/* Index of the first day of each month.  First array is non-leap-year;
  93. X   second is leap-year. */
  94. Xint MonthIndex[2][12] = {
  95. X   { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 },
  96. X   { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }
  97. X};
  98. X
  99. X/* Global ommissions array */
  100. Xint FullOmitArray[FOMITSIZE];
  101. X
  102. X/* Global partial omissions array */
  103. Xint PartOmitArray[POMITSIZE];
  104. X
  105. X/* Define the working buffers */
  106. Xchar Line[256], WorkBuf[256];
  107. Xstatic char temp[256];
  108. Xint Fresh;  /* True if the contents of Line are fresh */
  109. X
  110. X/* Global variables */
  111. Xint Purge, Debug, Verbose, IgRun, IgOnce;
  112. Xint LastRun;
  113. Xchar FileName[200];
  114. Xint CurLine;
  115. Xchar Banner[200] = "Reminders for %w, %d%s %m, %y%o:";
  116. Xint NumEmitted, NumRem;
  117. Xint NumFullOmit, NumPartOmit;
  118. Xint JulianToday, RealToday;
  119. Xint CurYear, CurMon, CurDay;
  120. X
  121. Xstatic int JulFirst; /* Julian date of 1 Jan Current_year */
  122. X#ifndef UNIX
  123. Xint int_comp(int *a, int *b) { return *a - *b; }
  124. X#else UNIX
  125. Xint int_comp(a, b) 
  126. X   int *a;
  127. X   int *b;
  128. X{ return *a - *b; }
  129. X#endif UNIX
  130. X
  131. X/***************************************************************/
  132. X/*                                                             */
  133. X/*  int MoveBack(...)                                          */
  134. X/*                                                             */
  135. X/*  Move back by specified number of days, skipping holidays   */
  136. X/*                                                             */
  137. X/***************************************************************/
  138. X#ifndef UNIX
  139. Xint MoveBack (int jul, int back, int d, int m, int y, int omit)
  140. X#else UNIX
  141. Xint MoveBack (jul, back, d, m, y, omit)
  142. X     int jul;
  143. X     int back;
  144. X     int d;
  145. X     int m;
  146. X     int y;
  147. X     int omit;
  148. X#endif UNIX
  149. X{
  150. X   int temp;
  151. X
  152. X   if (!NumFullOmit && !NumPartOmit && !omit) return jul - back;
  153. X   while (back) {
  154. X      jul--;
  155. X      if (omit & 1 << (jul % 7)) continue; /* Omitted due to weekday */
  156. X
  157. X      /* Omit if in fully-specified omit list */
  158. X      if (NumFullOmit && bsearch(&jul, FullOmitArray, NumFullOmit, sizeof(int), int_comp)) continue;
  159. X
  160. X      if (NumPartOmit) {
  161. X     d--;
  162. X     if (d == 0) {
  163. X        m--;
  164. X        if (m < 0) {
  165. X           y--;
  166. X           m = 11;
  167. X        }
  168. X        d = DaysInMonth(m, y);
  169. X     }
  170. X     temp = (m << 5) + d;
  171. X     if (bsearch(&temp, PartOmitArray, NumPartOmit, sizeof(int), int_comp)) continue;
  172. X      }
  173. X      back--;
  174. X   }
  175. X   return jul;
  176. X}
  177. X
  178. X/***************************************************************/
  179. X/*                                                             */
  180. X/*  int ProcessLine()                                          */
  181. X/*                                                             */
  182. X/*  Process the line in the "Line" buffer.                     */
  183. X/*                                                             */
  184. X/***************************************************************/
  185. X#ifndef UNIX
  186. Xint ProcessLine(void)
  187. X#else UNIX
  188. Xint ProcessLine()
  189. X#endif UNIX
  190. X{
  191. X   char *s = Line;
  192. X   Token tok;
  193. X   int i;
  194. X
  195. X   while (isspace(*s)) s++;
  196. X
  197. X   /* Skip comments and blank lines */
  198. X   if (*s == '#' || *s == 0) {
  199. X      if (Purge && TopLevel()) puts(Line);
  200. X      return 0;
  201. X   }
  202. X
  203. X   tok = ParseToken(&s);
  204. X   switch(tok.type) {
  205. X      case Banner_t: DoBanner(&s);
  206. X             if (Purge && TopLevel()) puts(Line);
  207. X             break;
  208. X
  209. X      case Omit_t:   i = DoGlobalOmit(&s);
  210. X             if (Purge && TopLevel())
  211. X            if (i < 0) Eprint("Purged '%s'\n", Line);
  212. X            else       puts(Line);
  213. X             break;
  214. X
  215. X      case Rem_t:    i = DoRem(&s);
  216. X             if (Purge && TopLevel())
  217. X            if (i < 0) Eprint("Purged '%s'\n", Line);
  218. X            else       puts(Line);
  219. X             NumRem++;
  220. X             if (i>0) NumEmitted++;
  221. X             break;
  222. X
  223. X      case Include_t: if (Purge && TopLevel()) puts(Line);
  224. X              DoInclude(&s);
  225. X              break;
  226. X               
  227. X
  228. X      default:       if (Purge && TopLevel()) puts(Line);
  229. X             Eprint("Unknown command '%s'\n", tok.str);
  230. X   }
  231. X   return 0;
  232. X}
  233. X
  234. X/***************************************************************/
  235. X/*                                                             */
  236. X#ifndef UNIX
  237. X/*  void Eprint(const char *f, ...)                            */
  238. X#else UNIX
  239. X/*  void Eprint(va_alist)                                      */
  240. X#endif UNIX
  241. X/*                                                             */
  242. X/*  Prints an error message.                                   */
  243. X/*                                                             */
  244. X/***************************************************************/
  245. X#ifndef UNIX
  246. Xvoid Eprint(const char *f, ...)
  247. X#else UNIX
  248. X/*VARARGS0*/
  249. Xvoid Eprint(va_alist)
  250. Xva_dcl
  251. X#endif UNIX
  252. X{
  253. X#ifndef UNIX
  254. X   va_list args;
  255. X#else UNIX
  256. X  va_list args;
  257. X  char *f;
  258. X#endif UNIX
  259. X
  260. X#ifndef UNIX
  261. X   if (Verbose & Fresh) {
  262. X#else UNIX
  263. X  if (Verbose & Fresh) {
  264. X#endif UNIX
  265. X      fprintf(stderr, "\n--- %s\n", Line);
  266. X      Fresh = 0;
  267. X   }
  268. X   if (Verbose) fprintf(stderr, "--- ");
  269. X   fprintf(stderr, "%s(%d): ", FileName, CurLine);
  270. X#ifndef UNIX
  271. X   va_start(args, f);
  272. X#else UNIX
  273. X   va_start(args);
  274. X   f = va_arg(args, char *);
  275. X#endif UNIX
  276. X   vfprintf(stderr, f, args);
  277. X#ifdef UNIX
  278. X   va_end(args);
  279. X#endif UNIX
  280. X}
  281. X
  282. X
  283. X/***************************************************************/
  284. X/*                                                             */
  285. X/*  int DoBanner(char **s)                                     */
  286. X/*                                                             */
  287. X/*  Sets the "Reminders for..." banner.                        */
  288. X/*                                                             */
  289. X/***************************************************************/
  290. X#ifndef UNIX
  291. Xint DoBanner(char **s)
  292. X#else UNIX
  293. Xint DoBanner(s)
  294. X     char **s;
  295. X#endif UNIX
  296. X{
  297. X   if (Purge) return 0;
  298. X   while (isspace(**s)) (*s)++;
  299. X   strcpy(Banner, *s);
  300. X   if (! *Banner)
  301. X   {
  302. X      if (Debug) Eprint("Empty banner.\n");
  303. X      strcpy(Banner, "Reminders for %d %m, %y%o:");
  304. X   }
  305. X   if (NumRem && Debug) Eprint("Warning: Banner after reminder.\n");
  306. X   return 0;
  307. X}
  308. X
  309. X/***************************************************************/
  310. X/*                                                             */
  311. X/* int CheckDate(int d, int m, int y)                          */
  312. X/*                                                             */
  313. X/* Checks that a date is valid - returns 0 for OK, 1 for BAD.  */
  314. X/*                                                             */
  315. X/* If y=-1, just checks that month & day are valid, giving     */
  316. X/* benefit of the doubt for February 29.                       */
  317. X/*                                                             */
  318. X/* No point in checking if month is valid - months are named   */
  319. X/* and thus a month out of range can never be entered into     */
  320. X/* the system.                                                 */
  321. X/*                                                             */
  322. X/***************************************************************/
  323. X#ifndef UNIX
  324. Xint CheckDate(int d, int m, int y)
  325. X#else UNIX
  326. Xint CheckDate(d, m, y)
  327. X     int d;
  328. X     int m;
  329. X     int y;
  330. X#endif UNIX
  331. X{
  332. X   if (y == -1)
  333. X      if (d > 0 && d <= MonthDays[m]) return 0; else return 1;
  334. X   else
  335. X      if (y < BASE || y > BASE + 85) return 1;
  336. X      else if (d > 0 && d <= DaysInMonth(m, y)) return 0; else return 1;
  337. X}
  338. X
  339. X
  340. X/***************************************************************/
  341. X/*                                                             */
  342. X/*  int DoGlobalOmit(char **s)                                 */
  343. X/*                                                             */
  344. X/*  Add an entry to the global ommissions array.  Either       */
  345. X/*  a fully-specified date, or a mm-yy type date.              */
  346. X/*  Return 0 if OK, -1 if date is in past, 1 if problem.       */
  347. X/*                                                             */
  348. X/***************************************************************/
  349. X#ifndef UNIX
  350. Xint DoGlobalOmit(char **s)
  351. X#else UNIX
  352. Xint DoGlobalOmit(s)
  353. X     char **s;
  354. X#endif UNIX
  355. X{
  356. X   int d = -1, m = -1, y = -1;
  357. X   int omit;
  358. X   int *ptr;
  359. X   Token tok;
  360. X
  361. X   tok.type = Unknown_t;
  362. X   while(tok.type != Eol_t) {
  363. X      tok = ParseToken(s);
  364. X      switch (tok.type) {
  365. X     case Year_t:  y = tok.val; break;
  366. X     case Month_t: m = tok.val; break;
  367. X     case Day_t:   d = tok.val; break;
  368. X     case Eol_t:   break;
  369. X     default:      Eprint("Invalid token '%s' for OMIT command.\n", tok.str);
  370. X               return 1;
  371. X      }
  372. X   }
  373. X
  374. X   if (d == -1 || m == -1 || CheckDate(d, m, y)) {
  375. X      Eprint("Invalid date specification.\n");
  376. X      return 1;
  377. X   }
  378. X
  379. X   if (y == -1) { /* Only mm-dd specified */
  380. X      if (NumPartOmit == POMITSIZE) {
  381. X     Eprint("Too many partially-specified OMITs.\n");
  382. X     return 1;
  383. X      }
  384. X      omit = (m << 5) + d;
  385. X      ptr = PartOmitArray + NumPartOmit;
  386. X      NumPartOmit++;
  387. X      while (ptr > PartOmitArray && *(ptr-1) > omit) {
  388. X     *ptr = *(ptr-1);
  389. X     ptr--;
  390. X      }
  391. X      *ptr = omit;
  392. X
  393. X      /* Check if the bonehead already has it - if so, delete it */
  394. X      if (ptr > PartOmitArray && *(ptr-1) == *ptr) {
  395. X     if (Debug) Eprint("Duplicated partially-specified OMIT.\n");
  396. X     NumPartOmit--;
  397. X     while (ptr < NumPartOmit+PartOmitArray) {
  398. X        *ptr = *(ptr + 1);
  399. X        ptr++;
  400. X     }
  401. X      }
  402. X   } else { /* All three specified */
  403. X      if (NumFullOmit == FOMITSIZE) {
  404. X     Eprint("Too many fully-specified OMITs.\n");
  405. X     return 1;
  406. X      }
  407. X      omit = Julian(d, m, y);
  408. X      if (omit < JulianToday) {
  409. X     if (Debug) Eprint("Omit has expired.\n");
  410. X     return -1;
  411. X      }
  412. X
  413. X      ptr = FullOmitArray + NumFullOmit;
  414. X      NumFullOmit++;
  415. X      while (ptr > FullOmitArray && *(ptr-1) > omit) {
  416. X     *ptr = *(ptr-1);
  417. X     ptr--;
  418. X      }
  419. X      *ptr = omit;
  420. X
  421. X      /* Check if the bonehead already has it - if so, delete it */
  422. X      if (ptr > FullOmitArray && *(ptr-1) == *ptr) {
  423. X     if (Debug) Eprint("Duplicated fully-specified OMIT.\n");
  424. X     NumFullOmit--;
  425. X     while (ptr < NumFullOmit+FullOmitArray) {
  426. X        *ptr = *(ptr + 1);
  427. X        ptr++;
  428. X     }
  429. X      }
  430. X   }
  431. X   return 0;
  432. X}
  433. X
  434. X/***************************************************************/
  435. X/*                                                             */
  436. X/*  int strnicmp(char *s1, char*s1, int n)                     */
  437. X/*                                                             */
  438. X/*  Compares first n chars of string ignoring case.            */
  439. X/*                                                             */
  440. X/***************************************************************/
  441. X#ifndef UNIX
  442. Xint strncmpi(char *s1, char *s2, int n)
  443. X#else UNIX
  444. Xint strncmpi(s1, s2, n)
  445. X     char *s1;
  446. X     char *s2;
  447. X     int n;
  448. X#endif UNIX
  449. X{
  450. X   register int u1, u2;
  451. X   while (n)
  452. X   {
  453. X      if (!*s1 || !*s2) return upper(*s1) - upper(*s2);
  454. X      u1 = upper(*s1);
  455. X      u2 = upper(*s2);
  456. X      if (u1 != u2) return (u1 - u2);
  457. X      n--;
  458. X      s1++;
  459. X      s2++;
  460. X   }
  461. X   return 0;
  462. X}
  463. X
  464. X/***************************************************************/
  465. X/*                                                             */
  466. X/*  ParseToken(char **s);                                      */
  467. X/*                                                             */
  468. X/*  Parse the next token and adjust the character pointer.     */
  469. X/*                                                             */
  470. X/***************************************************************/
  471. X#ifndef UNIX
  472. XToken ParseToken(char **s)
  473. X#else UNIX
  474. XToken ParseToken(s)
  475. X     char **s;
  476. X#endif UNIX
  477. X{
  478. X
  479. X   Token tok;
  480. X   char *t = temp;
  481. X   int i;
  482. X   int len;
  483. X
  484. X   *t = 0;
  485. X   tok.str = temp;
  486. X   
  487. X   /* Skip blank space */
  488. X   while (isspace(**s)) (*s)++;
  489. X
  490. X   /* End of line ? */
  491. X   if (**s == 0) {
  492. X      tok.type = Eol_t;
  493. X      tok.val = 0;
  494. X      return tok;
  495. X   }
  496. X
  497. X   /* Grab a space-delimited token */
  498. X   while (**s != 0 && !isspace(**s)) {
  499. X      *t++ = **s;
  500. X      (*s)++;
  501. X   }
  502. X   *t = 0;
  503. X   len = t - temp;
  504. X
  505. X   /* Check if it's a built-in token */
  506. X   for (i=0; i < sizeof(keywd)/sizeof(keywd[0]); i++)
  507. X      if (len >= 3 && !strncmpi(temp, keywd[i].str, len)) return keywd[i];
  508. X
  509. X   tok.type = Unknown_t;
  510. X
  511. X   /* If it's a comment, ignore the rest of the line */
  512. X   if (*(tok.str) == '#') {
  513. X      tok.type = Eol_t;
  514. X      return tok;
  515. X   }
  516. X
  517. X   /* Check if it's a number (optional +/- ahead of number */
  518. X   t = temp;
  519. X   if (isdigit(*t)) {
  520. X      while (*++t) if (!isdigit(*t)) return tok;
  521. X   }
  522. X   else if (*t == '+' || *t == '-') {
  523. X      if (!isdigit(*++t)) return tok;
  524. X      while (*++t) if (!isdigit(*t)) return tok;
  525. X   }
  526. X   else return tok;
  527. X
  528. X   /* OK, here we have a number - either a pure number, a delta or a
  529. X      backward look */
  530. X
  531. X   if (*temp == '+') {
  532. X      tok.type = Delta_t;
  533. X      tok.val = atoi(temp + 1);
  534. X   }
  535. X   else if (*temp == '-') {
  536. X      tok.type = Back_t;
  537. X      tok.val = atoi(temp + 1);
  538. X   }
  539. X   else {
  540. X      tok.val = atoi(temp);
  541. X      if (tok.val > 0 && tok.val <= 31) tok.type = Day_t;
  542. X      else if (tok.val >= 100) tok.type = Year_t;
  543. X      else {
  544. X     tok.type = Year_t;
  545. X     tok.val += 1900;
  546. X      }
  547. X   }
  548. X   return tok;
  549. X}
  550. X
  551. X/***************************************************************/
  552. X/*                                                             */
  553. X/*  int FromJulian(int jul, int *d, int *m, int *y)            */
  554. X/*                                                             */
  555. X/*  Convert a date from Julian to normal form.  Returns        */
  556. X/*  0 if conversion ok, -1 otherwise.                          */
  557. X/*                                                             */
  558. X/***************************************************************/
  559. X#ifndef UNIX
  560. Xint FromJulian(int jul, int *d, int *m, int *y)
  561. X#else UNIX
  562. Xint FromJulian(jul, d, m, y)
  563. X     int jul;
  564. X     int *d;
  565. X     int *m;
  566. X     int *y;
  567. X#endif UNIX
  568. X{
  569. X   int t;
  570. X
  571. X   if (jul < 0) return 1;
  572. X
  573. X   if (jul >= JulFirst && JulFirst != -1) {
  574. X      *y = CurYear;
  575. X      jul -= JulFirst;
  576. X   } else *y = BASE;
  577. X
  578. X   *m = 0;
  579. X
  580. X   t = DaysInYear(*y);
  581. X   while (jul >= t) {
  582. X      jul -= t;
  583. X      (*y)++;
  584. X      t = DaysInYear(*y);
  585. X   }
  586. X
  587. X   t = DaysInMonth(*m, *y);
  588. X   while (jul >= t) {
  589. X      jul -= t;
  590. X      (*m)++;
  591. X      t = DaysInMonth(*m, *y);
  592. X   }
  593. X   *d = jul + 1;
  594. X   return 0;
  595. X}
  596. X
  597. X/***************************************************************/
  598. X/*                                                             */
  599. X/*  int Julian(d, m, y)                                        */
  600. X/*                                                             */
  601. X/*  Converts a date to the number of days after Jan 1 1990.    */
  602. X/*  Returns -1 if date is before Jan 1 1990.                   */
  603. X/*                                                             */
  604. X/***************************************************************/
  605. X#ifndef UNIX
  606. Xint Julian(int d, int m, int y)
  607. X#else UNIX
  608. Xint Julian(d, m, y)
  609. X     int d;
  610. X     int m;
  611. X     int y;
  612. X#endif UNIX
  613. X{
  614. X   int iy;
  615. X   int jul = 0;
  616. X
  617. X   if (y < BASE) return -1;
  618. X   if (JulFirst == -1 || y < CurYear) 
  619. X      for (iy = BASE; iy < y; iy++) jul += DaysInYear(iy);
  620. X   else {
  621. X      jul = JulFirst;
  622. X      for (iy = CurYear; iy < y; iy++) jul += DaysInYear(iy);
  623. X   }
  624. X      
  625. X   return jul + MonthIndex[IsLeapYear(y)][m] + d - 1;
  626. X}
  627. X
  628. X/***************************************************************/
  629. X/*                                                             */
  630. X/*  int FindTodaysDate(int *d, int *m, int *y)                 */
  631. X/*                                                             */
  632. X/*  Obtains today's date.  Returns Julian date or -1 for       */
  633. X/*  failure.                                                   */
  634. X/*                                                             */
  635. X/***************************************************************/
  636. X#ifndef UNIX
  637. Xint FindTodaysDate(int *d, int *m, int *y)
  638. X#else UNIX
  639. Xint FindTodaysDate(d, m, y)
  640. X     int *d;
  641. X     int *m;
  642. X     int *y;
  643. X#endif UNIX
  644. X{
  645. X#ifndef UNIX
  646. X   struct dosdate_t buf;
  647. X
  648. X   _dos_getdate(&buf);
  649. X
  650. X   *d = buf.day;
  651. X   *m = buf.month - 1;
  652. X   *y = buf.year;
  653. X#else UNIX
  654. X  time_t tloc;
  655. X  struct tm *t;
  656. X  
  657. X   (void) time(&tloc);
  658. X   t = localtime(&tloc);
  659. X       
  660. X   *d = t->tm_mday;
  661. X   *m = t->tm_mon;
  662. X   *y = t->tm_year + 1900;
  663. X   
  664. X#endif UNIX
  665. X   if (CheckDate(*d, *m, *y)) return -1;
  666. X   return Julian(*d, *m, *y);
  667. X}
  668. X
  669. X#ifndef UNIX
  670. Xint main(int argc, char *argv[])
  671. X#else UNIX
  672. Xint main(argc, argv)
  673. X     int argc;
  674. X     char *argv[];
  675. X#endif UNIX
  676. X{
  677. X
  678. X   NumEmitted = 0;
  679. X   NumRem = 0;
  680. X   JulFirst = -1;  /* Initialize JulFirst so it's not used by Julian */
  681. X   
  682. X   JulianToday = FindTodaysDate(&CurDay, &CurMon, &CurYear);
  683. X   if (JulianToday < 0) {
  684. X      fprintf(stderr, "remind: System date is illegal - Ensure that year is at least %d.\n", BASE);
  685. X      exit(1);
  686. X   }
  687. X   
  688. X   RealToday = JulianToday;
  689. X   
  690. X   initialize(argc, argv);
  691. X
  692. X   JulFirst = Julian(1, 0, CurYear);  /* Do expensive computation once */
  693. X   
  694. X   while (1) {
  695. X      if (ReadLine()) break;
  696. X      ProcessLine();
  697. X   }
  698. X   if (NumEmitted == 0 && !Purge && !Debug) printf("No reminders.\n");
  699. X   return 0;
  700. X}
  701. X#ifndef UNIX
  702. X
  703. X#endif UNIX
  704. SHAR_EOF
  705. $TOUCH -am 1024164690 main.c &&
  706. chmod 0600 main.c ||
  707. echo "restore of main.c failed"
  708. set `wc -c main.c`;Wc_c=$1
  709. if test "$Wc_c" != "18810"; then
  710.     echo original size 18810, current size $Wc_c
  711. fi
  712. fi
  713. # ============= nextdate.c ==============
  714. if test X"$1" != X"-c" -a -f 'nextdate.c'; then
  715.     echo "File already exists: skipping 'nextdate.c'"
  716. else
  717. sed 's/^X//' << 'SHAR_EOF' > nextdate.c &&
  718. X#include "defines.h"
  719. X#include "globals.h"
  720. X#include "protos.h"
  721. X
  722. X/***************************************************************/
  723. X/*                                                             */
  724. X/*  int TryNextDate(int *retday, int *retmon, int *retyr,      */
  725. X/*                  int startday, int startmon, int startyr,   */
  726. X/*                  int conday, int conmon, int conyr,         */
  727. X/*                  int wkday, int cons, int inc)              */
  728. X/*                                                             */
  729. X/*  This function tries to find the next date satisfying       */
  730. X/*  the given constraints.  Returns                            */
  731. X/*  0 for success.  Returns non-zero if a constraint would     */
  732. X/*  be violated.  Note that if DAY and WEEKDAY are both        */
  733. X/*  constrained, then MONTH and YEAR may be violated.          */
  734. X/*  Otherwise, all constraints are honoured.                   */
  735. X/*  The starting point for the search is thisday, etc.         */
  736. X/*                                                             */
  737. X/*  If inc is non-zero, then the search begins from the day    */
  738. X/*  after the specified date.  Note that this function assumes */
  739. X/*  that the given date is valid.                              */
  740. X/*                                                             */
  741. X/***************************************************************/
  742. X#ifndef UNIX
  743. Xint TryNextDate(int *retday, int *retmon, int *retyr,
  744. X        int d, int m, int y,
  745. X        int conday, int conmon, int conyr,
  746. X        int wkday, int cons, int inc)
  747. X#else UNIX
  748. Xint TryNextDate(retday, retmon, retyr, d, m, y, conday, conmon, conyr,
  749. X                wkday, cons, inc)
  750. X     int *retday, *retmon, *retyr, d, m, y, conday, conmon, conyr, wkday, cons, inc;
  751. X     
  752. X#endif UNIX
  753. X
  754. X{
  755. X   int jul, jul2;
  756. X   int dd = d, mm = m, yy = y;
  757. X
  758. X   if (inc)
  759. X   {
  760. X      d++;
  761. X      if (d > DaysInMonth(m, y)) {
  762. X     m++; d = 1;
  763. X     if (m > 11) {
  764. X        y++; m = 0;
  765. X     }
  766. X      }
  767. X   }
  768. X
  769. X
  770. X   switch (cons & 15) {
  771. X
  772. X      case 0:  /* No constraints - just use the start date */
  773. X     *retday = d;
  774. X     *retmon = m;
  775. X     *retyr  = y;
  776. X     return 0;
  777. X
  778. X      case 1: /* Day constrained to be d */
  779. X     *retday = conday;
  780. X     if (d > conday) {
  781. X        m++;
  782. X        if (m > 11) {y++; m=0;}
  783. X     }
  784. X     while (conday > DaysInMonth(m, y)) {
  785. X        m++;
  786. X        if (m > 11) {y++; m=0;}
  787. X     }
  788. X     *retmon = m;
  789. X     *retyr = y;
  790. X     return 0;
  791. X
  792. X      case 2: /* Month constrained to be m */
  793. X     *retmon = conmon;
  794. X     if (m > conmon) {y++; d = 1;}
  795. X     else if (m < conmon) d = 1;
  796. X     *retday = d;
  797. X     *retyr = y;
  798. X     return 0;
  799. X
  800. X      case 3: /* Month and day constrained */
  801. X     *retmon = conmon;
  802. X     *retday = conday;
  803. X     if (m > conmon || (m == conmon && d > conday)) y++;
  804. X     while (conday > DaysInMonth(conmon, y)) y++;
  805. X     *retyr = y;
  806. X     return 0;
  807. X
  808. X      case 4: /* Year alone constrained */
  809. X     if (y > conyr) return 1;
  810. X     *retyr = conyr;
  811. X     if (y < conyr) {
  812. X        *retmon = 0;
  813. X        *retday = 1;
  814. X     }
  815. X     else {
  816. X        *retmon = m;
  817. X        *retday = d;
  818. X     }
  819. X     return 0;
  820. X
  821. X      case 5: /* Year and day constrained */
  822. X     if (y > conyr) return 1;
  823. X     *retyr = conyr;
  824. X     *retday = conday;
  825. X     if (y < conyr) {
  826. X        *retmon = 0;
  827. X        return 0;
  828. X     }
  829. X     if (d > conday) {
  830. X       m++;
  831. X       if (m > 11) return 1;
  832. X     }
  833. X     while (conday > DaysInMonth(m, y)) {
  834. X        m++;
  835. X        if (m > 11) return 1;
  836. X     }
  837. X     *retmon = m;
  838. X     return 0;
  839. X
  840. X      case 6: /* Year and month constrained */
  841. X     if (y > conyr || (y == conyr && m > conmon)) return 1;
  842. X     *retyr = conyr;
  843. X     *retmon = conmon;
  844. X     if (y < conyr || (y == conyr && m < conmon)) {
  845. X        *retday = 1;
  846. X        return 0;
  847. X     }
  848. X     *retday = d;
  849. X     return 0;
  850. X
  851. X      case 7: /* Year, month and day constrained */
  852. X     if (y > conyr || (y == conyr && m > conmon) ||
  853. X         (y == conyr && m == conmon && d > conday)) return 1;
  854. X     *retday = conday;
  855. X     *retmon = conmon;
  856. X     *retyr = conyr;
  857. X     return 0;
  858. X
  859. X      case 8: /* Only the weekday constrained.  Let's go to Julian mode */
  860. X     jul = Julian(d, m, y);
  861. X     while (!(wkday & (1 << (jul % 7)))) jul++;
  862. X     FromJulian(jul, retday, retmon, retyr);
  863. X     return 0;
  864. X
  865. X      case 9: /* GASP! day and weekday constrained .. bleah! */
  866. X     /* First, try last month. */
  867. X     jul2 = Julian(d, m, y);
  868. X     if (m != 0 || y != BASE)
  869. X     {
  870. X        mm--;
  871. X        if (mm < 0) {yy--; mm = 11;}
  872. X
  873. X        /* If there are fewer days in month than required, it
  874. X           can't possibly match.  */
  875. X        if (conday <= DaysInMonth(mm, yy)) {
  876. X           jul = Julian(conday, mm, yy);
  877. X           while (!(wkday & (1 << (jul % 7)))) jul++;
  878. X           if (jul >= jul2) { /* SUCCESS! */
  879. X          FromJulian(jul, retday, retmon, retyr);
  880. X          return 0;
  881. X           }
  882. X        }
  883. X     }
  884. X     /* Didn't work - try this month */
  885. X     if (conday <= DaysInMonth(m, y)) {
  886. X        jul = Julian(conday, m, y);
  887. X        while (!(wkday & (1 << (jul % 7)))) jul++;
  888. X        if (jul >= jul2) { /* SUCCESS! */
  889. X           FromJulian(jul, retday, retmon, retyr);
  890. X           return 0;
  891. X        }
  892. X     }
  893. X     /* Argh!  Try next available month */
  894. X     mm = m;
  895. X     yy = y;
  896. X     do {
  897. X        mm++;
  898. X        if (mm > 11) {mm = 0; yy++;}
  899. X     } while (conday > DaysInMonth(mm, yy));
  900. X     jul = Julian(conday, mm, yy);
  901. X     while (!(wkday & (1 << (jul % 7)))) jul++;
  902. X     FromJulian(jul, retday, retmon, retyr);
  903. X     return 0;
  904. X
  905. X      case 10: /* Month and Weekday constrained */
  906. X     if (m < conmon) {
  907. X        jul = Julian(1, conmon, y);
  908. X        while (!(wkday & (1 << (jul % 7)))) jul++;
  909. X        FromJulian(jul, retday, retmon, retyr);
  910. X        return 0;
  911. X     } else if (m == conmon) {
  912. X        jul = Julian(d, conmon, y);
  913. X        while (!(wkday & (1 << (jul % 7)))) jul++;
  914. X        FromJulian(jul, retday, retmon, retyr);
  915. X        if (*retmon != conmon) {
  916. X           jul = Julian(1, conmon, y+1);
  917. X           while (!(wkday & (1 << (jul % 7)))) jul++;
  918. X           FromJulian(jul, retday, retmon, retyr);
  919. X        }
  920. X        return 0;
  921. X     } else { /* m > conmon */
  922. X        jul = Julian(1, conmon, y+1);
  923. X        while (!(wkday & (1 << (jul % 7)))) jul++;
  924. X        FromJulian(jul, retday, retmon, retyr);
  925. X        return 0;
  926. X     }
  927. X
  928. X      case 11: /* Day, Month and Weekday constrained */
  929. X     jul2 = Julian(d, m, y);
  930. X
  931. X     /* Blip up to next valid year */
  932. X     while (conday > DaysInMonth(m, y)) y++;
  933. X
  934. X     /* Try this year */
  935. X     jul = Julian(conday, conmon, y);
  936. X     while (!(wkday & (1 << (jul % 7)))) jul++;
  937. X     if (jul >= jul2) {
  938. X        FromJulian(jul, retday, retmon, retyr);
  939. X        return 0;
  940. X     }
  941. X
  942. X     /* Must be next year */
  943. X     jul = Julian(conday, conmon, y+1);
  944. X     while (!(wkday & (1 << (jul % 7)))) jul++;
  945. X     FromJulian(jul, retday, retmon, retyr);
  946. X     return 0;
  947. X
  948. X      case 12: /* Weekday and year specified */
  949. X     if (y > conyr) return 1;
  950. X     if (y == conyr) {mm = m; dd = d;} else {mm = 0; dd = 1;}
  951. X     jul = Julian(dd, mm, conyr);
  952. X     while (!(wkday & (1 << (jul % 7)))) jul++;
  953. X     FromJulian(jul, retday, retmon, retyr);
  954. X     return 0;
  955. X
  956. X      case 13: /* Weekday, year and day specified */
  957. X     if (y > conyr+1 || (y > conyr && m>0)) return 1;
  958. X     jul2 = Julian(d, m, y);
  959. X     if (y > conyr ) {
  960. X        jul = Julian(conday, 11, conyr);
  961. X        while (!(wkday & (1 << (jul % 7)))) jul++;
  962. X        if (jul >= jul2) {
  963. X           FromJulian(jul, retday, retmon, retyr);
  964. X           return 0;
  965. X        }
  966. X     } else if (y < conyr) {
  967. X        jul = Julian(conday, 0, conyr);
  968. X        while (!(wkday & (1 << (jul % 7)))) jul++;
  969. X        FromJulian(jul, retday, retmon, retyr);
  970. X        return 0;
  971. X     }
  972. X     else {
  973. X        /* Try last month */
  974. X        if (m > 0) {
  975. X           mm = m - 1;
  976. X           while (conday > DaysInMonth(mm, y)) mm--;
  977. X           jul = Julian(conday, mm, y);
  978. X           while (!(wkday & (1 << (jul % 7)))) jul++;
  979. X           if (jul >= jul2) {
  980. X          FromJulian(jul, retday, retmon, retyr);
  981. X          return 0;
  982. X           }
  983. X        }
  984. X        /* Try this month */
  985. X        if (conday <= DaysInMonth(m,y)) {
  986. X           jul = Julian(conday, m, y);
  987. X           while (!(wkday & (1 << (jul % 7)))) jul++;
  988. X           if (jul >= jul2) {
  989. X          FromJulian(jul, retday, retmon, retyr);
  990. X          return 0;
  991. X           }
  992. X        }
  993. X        /* Try next month */
  994. X        if (m == 11) return 1;
  995. X        m++;
  996. X        while (conday > DaysInMonth(m, y)) m++;
  997. X        jul = Julian(conday, m, y);
  998. X        while (!(wkday & (1 << (jul % 7)))) jul++;
  999. X        FromJulian(jul, retday, retmon, retyr);
  1000. X        return 0;
  1001. X     }
  1002. X
  1003. X      case 14:  /* Weekday, Month and Year specified */
  1004. X     if (y > conyr || (y == conyr && m > conmon)) return 1;
  1005. X     if (conyr > y || (conyr == y && conmon > m)) {
  1006. X        jul = Julian(1, conmon, conyr);
  1007. X        while (!(wkday & (1 << (jul % 7)))) jul++;
  1008. X        FromJulian(jul, retday, retmon, retyr);
  1009. X        return 0;
  1010. X     } else {
  1011. X        jul = Julian(d, m, y);
  1012. X        while (!(wkday & (1 << (jul % 7)))) jul++;
  1013. X        FromJulian(jul, retday, retmon, retyr);
  1014. X        if (*retmon == conmon) return 0; else return 1;
  1015. X
  1016. X     }
  1017. X
  1018. X      case 15: /* Weekday, day, month and year specified */
  1019. X     jul2 = Julian(d, m, y);
  1020. X     jul = Julian(conday, conmon, conyr);
  1021. X     while (!(wkday & (1 << (jul % 7)))) jul++;
  1022. X     if (jul < jul2) return 1;
  1023. X     FromJulian(jul, retday, retmon, retyr);
  1024. X     return 0;
  1025. X   }
  1026. X}
  1027. X#ifndef UNIX
  1028. X
  1029. X#endif UNIX
  1030. SHAR_EOF
  1031. $TOUCH -am 1024164690 nextdate.c &&
  1032. chmod 0600 nextdate.c ||
  1033. echo "restore of nextdate.c failed"
  1034. set `wc -c nextdate.c`;Wc_c=$1
  1035. if test "$Wc_c" != "8674"; then
  1036.     echo original size 8674, current size $Wc_c
  1037. fi
  1038. fi
  1039. # ============= protos.h ==============
  1040. if test X"$1" != X"-c" -a -f 'protos.h'; then
  1041.     echo "File already exists: skipping 'protos.h'"
  1042. else
  1043. sed 's/^X//' << 'SHAR_EOF' > protos.h &&
  1044. X
  1045. X/* Function Prototypes go here */
  1046. X
  1047. X#ifndef UNIX
  1048. Xint   CheckDate   (int d,   int m,  int y);
  1049. Xint   DoBanner    (char **s);
  1050. Xint   DoGlobalOmit(char **s);
  1051. Xvoid  DoInclude   (char **s);
  1052. Xint   DoRem       (char **s);
  1053. Xint   DoSubst     (char *src, char *dst, int d, int m, int y, int jul, enum Token_t t);
  1054. Xvoid  Eprint(const char *f, ...);
  1055. Xint   FindTodaysDate(int *d, int *m, int *y);
  1056. Xint   FromJulian  (int jul, int *d, int *m, int *y);
  1057. Xvoid  initialize  (int argc, char *argv[]);
  1058. Xint   int_comp    (int *, int *);
  1059. Xint   Julian      (int d,   int m,  int y);
  1060. Xint   MoveBack    (int jul, int back, int d, int m, int y, int omit);
  1061. Xvoid  OpenFile    (char *s);
  1062. XToken ParseToken  (char **s);
  1063. Xint   ProcessLine (void);
  1064. Xint   ReadLine    (void);
  1065. Xint   TopLevel    (void);
  1066. Xint   TryNextDate(int *retday, int *retmon, int *retyr,
  1067. X          int startday, int startmon, int startyr,
  1068. X          int conday, int conmon, int conyr,
  1069. X          int wkday, int cons, int inc);
  1070. X
  1071. X#else UNIX
  1072. Xint   CheckDate   ();
  1073. Xint   DoBanner    ();
  1074. Xint   DoGlobalOmit();
  1075. Xvoid  DoInclude   ();
  1076. Xint   DoRem       ();
  1077. Xint   DoSubst     ();
  1078. Xvoid  Eprint();
  1079. Xint   FindTodaysDate();
  1080. Xint   FromJulian  ();
  1081. Xvoid  initialize  ();
  1082. Xint   int_comp    ();
  1083. Xint   Julian      ();
  1084. Xint   MoveBack    ();
  1085. Xvoid  OpenFile    ();
  1086. XToken ParseToken  ();
  1087. Xint   ProcessLine ();
  1088. Xint   ReadLine    ();
  1089. Xint   TopLevel    ();
  1090. Xint   TryNextDate ();
  1091. X#endif UNIX
  1092. SHAR_EOF
  1093. $TOUCH -am 1024164690 protos.h &&
  1094. chmod 0600 protos.h ||
  1095. echo "restore of protos.h failed"
  1096. set `wc -c protos.h`;Wc_c=$1
  1097. if test "$Wc_c" != "1377"; then
  1098.     echo original size 1377, current size $Wc_c
  1099. fi
  1100. fi
  1101. echo "End of part 2, continue with part 3"
  1102. exit 0
  1103.