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

  1. From: dfs@doe.carleton.ca (David F. Skoll)
  2. Newsgroups: alt.sources
  3. Subject: REMIND 2.2 02/05
  4. Message-ID: <dfs.658781209@yar>
  5. Date: 16 Nov 90 18:46:49 GMT
  6.  
  7. #!/bin/sh
  8. # This is part 02 of Remind-2.2
  9. if touch 2>&1 | fgrep 'amc' > /dev/null
  10.  then TOUCH=touch
  11.  else TOUCH=true
  12. fi
  13. # ============= dorem.c ==============
  14. if test X"$1" != X"-c" -a -f 'dorem.c'; then
  15.     echo "File already exists: skipping 'dorem.c'"
  16. else
  17. echo "x - extracting dorem.c (Text)"
  18. sed 's/^X//' << 'SHAR_EOF' > dorem.c &&
  19. X#include <stdio.h>
  20. X#ifndef UNIX
  21. X#include <stdlib.h>
  22. X#include <string.h>
  23. X#endif
  24. X#include <ctype.h>
  25. X#include "defines.h"
  26. X#include "globals.h"
  27. X#include "protos.h"
  28. X
  29. X/***************************************************************/
  30. X/*                                                             */
  31. X/*  int DoRem(char **s)                                        */
  32. X/*                                                             */
  33. X/*  Process a reminder.  Return 0 if reminder not emitted,     */
  34. X/*  positive if emitted, or negative if in the past and        */
  35. X/*  will never be emitted.                                     */
  36. X/*                                                             */
  37. X/***************************************************************/
  38. X#ifndef UNIX
  39. Xint DoRem(char **s)
  40. X#else
  41. Xint DoRem(s)
  42. Xchar **s;
  43. X     
  44. X#endif
  45. X{
  46. X   int d, m, y, wd, cons, delta, back, omit, done, jul, once, repeat;
  47. X   int tim, tdelta, trep;
  48. X   int d2, m2, y2;
  49. X   Token tok;
  50. X   int trigger;
  51. X
  52. X   d = m = y = back = delta = tim = tdelta = trep = -1;
  53. X   repeat = cons = wd = omit = once = 0;
  54. X
  55. X
  56. X   done = 0;
  57. X   while (!done) {
  58. X      tok = ParseToken(s);
  59. X      switch (tok.type) {
  60. X     case Eol_t:
  61. X        Eprint("Missing MSG or RUN in reminder.\n");
  62. X        return 0;
  63. X
  64. X         case At_t:
  65. X     case Omit_t:
  66. X     case Run_t:
  67. X     case Msg_t: done = 1; break;
  68. X
  69. X     case Unknown_t:
  70. X        Eprint("Unknown token %s in reminder.\n", tok.str);
  71. X        return 0;
  72. X
  73. X         case Repeat_t:
  74. X            if (repeat) {
  75. X               Eprint("Repeat factor specified twice.\n");
  76. X               return 0;
  77. X            }
  78. X            repeat = tok.val;
  79. X            if (repeat <= 0) {
  80. X               Eprint("Invalid value for repeat factor: %d\n", repeat);
  81. X               return 0;
  82. X            }
  83. X            break;
  84. X
  85. X     case Banner_t:
  86. X        Eprint("BANNER can't be used here.\n");
  87. X        return 0;
  88. X
  89. X     case WkDay_t:
  90. X        if (wd & (1 << tok.val)) {
  91. X           Eprint("%s duplicated.\n", tok.str);
  92. X           return 0;
  93. X        }
  94. X        wd |= 1 << tok.val;
  95. X        cons |= WKDAY_M;
  96. X        break;
  97. X
  98. X     case Year_t:
  99. X        if (y != -1) {
  100. X           Eprint("Year specified twice.\n");
  101. X           return 0;
  102. X        }
  103. X        y = tok.val;
  104. X        cons |= YEAR_M;
  105. X        break;
  106. X
  107. X     case Month_t:
  108. X        if (m != -1) {
  109. X           Eprint("Month specified twice.\n");
  110. X           return 0;
  111. X        }
  112. X        m = tok.val;
  113. X        cons |= MONTH_M;
  114. X        break;
  115. X
  116. X     case Day_t:
  117. X        if (d != -1) {
  118. X           Eprint("Day specified twice.\n");
  119. X           return 0;
  120. X        }
  121. X        d = tok.val;
  122. X        cons |= DAY_M;
  123. X        break;
  124. X
  125. X     case Delta_t:
  126. X        if (delta != -1) {
  127. X           Eprint("Delta specified twice.\n");
  128. X           return 0;
  129. X        }
  130. X        delta = tok.val;
  131. X        break;
  132. X
  133. X     case Back_t:
  134. X        if (back != -1) {
  135. X           Eprint("Back specified twice.\n");
  136. X           return 0;
  137. X        }
  138. X        back = tok.val;
  139. X        break;
  140. X
  141. X     case Once_t:
  142. X        if (once) {
  143. X           Eprint("ONCE specified twice.  (How's that for an error message??)\n");
  144. X           return 0;
  145. X        }
  146. X        once = 1;
  147. X        break;
  148. X
  149. X     default:
  150. X        Eprint("Can't use token %s here.\n", tok.str);
  151. X        return 0;
  152. X      }
  153. X   }
  154. X   if (tok.type == Omit_t) {
  155. X      done = 0;
  156. X      while (!done) {
  157. X     tok = ParseToken(s);
  158. X     switch(tok.type) {
  159. X
  160. X            case At_t:
  161. X        case Msg_t:
  162. X        case Run_t: done = 1; break;
  163. X
  164. X        case Eol_t:
  165. X           Eprint("Missing MSG or RUN in reminder.\n");
  166. X           return 0;
  167. X
  168. X        case WkDay_t:
  169. X           if (omit & (1 << tok.val)) {
  170. X          Eprint("%s duplicated.\n", tok.str);
  171. X          return 0;
  172. X           }
  173. X           omit |= 1 << tok.val;
  174. X           break;
  175. X
  176. X        default:
  177. X           Eprint("Only weekdays are valid after a local OMIT.\n");
  178. X           return 0;
  179. X           }
  180. X       }
  181. X   }
  182. X   if (tok.type == At_t) {
  183. X      done = 0;
  184. X      while (!done) {
  185. X         tok = ParseToken(s);
  186. X         switch(tok.type) {
  187. X
  188. X            case Msg_t:
  189. X            case Run_t: done = 1; break;
  190. X
  191. X            case Time_t:
  192. X               if (tim != -1) {
  193. X              Eprint("Time specified twice.\n");
  194. X                 return 0;
  195. X           }
  196. X           else tim = tok.val;
  197. X               break;
  198. X  
  199. X           case Repeat_t:
  200. X               if (trep != -1) {
  201. X                  Eprint("Time repeat factor specified twice.\n");
  202. X                  return 0;
  203. X               }
  204. X               trep = tok.val;
  205. X               if (trep <= 0) {
  206. X                  Eprint("Invalid value for timerepeat factor: %d\n", repeat);
  207. X                  return 0;
  208. X               }
  209. X               break;
  210. X
  211. X            case Delta_t:
  212. X           if (tdelta != -1) {
  213. X              Eprint("Time delta specified twice.\n");
  214. X                  return 0;
  215. X           }
  216. X           tdelta = tok.val;
  217. X           break;
  218. X        
  219. X        default: Eprint("Can't use token %s in an AT.\n", tok.str);
  220. X                     return 0;
  221. X         }
  222. X      }
  223. X   }
  224. X
  225. X
  226. X   if (repeat && (d == -1 || m == -1 || y == -1)) {
  227. X      Eprint("Can't use repeat counter unless you fully specify the date.\n");
  228. X      return 0;
  229. X   }
  230. X   
  231. X   if (d != -1 && m != -1 && CheckDate(d, m, y)) {
  232. X      Eprint("Illegal date specification.\n");
  233. X      return 0;
  234. X   }
  235. X   if (y != -1 && (y < BASE || y > BASE + 85)) {
  236. X      Eprint("Illegal date specification.\n");
  237. X      return 0;
  238. X   }
  239. X
  240. X   /* Print some helpful stuff if debugging */
  241. X   if (Debug) {
  242. X      if (back > 7) Eprint("Warning: 'back' > 7 could slow execution severely.\n");
  243. X      if (delta > 30 && (omit || NumFullOmit || NumPartOmit))
  244. X     Eprint("Warning: 'delta' > 30 with OMITs could slow execution severely.\n");
  245. X   }
  246. X
  247. X   if (omit == 127) {
  248. X      Eprint("Can't omit every day!\n");
  249. X      return 0;
  250. X   } 
  251. X
  252. X   if (IgOnce) once = 0; 
  253. X   
  254. X   /* Check if we can quickly determine reminder is not to be emitted */
  255. X   if (once && !Debug && !Purge && (LastRun == JulianToday)) return 0;
  256. X
  257. X   /* Tweak the back and delta values to their defaults */
  258. X   if (back == -1) back = 0;
  259. X   if (delta == -1) delta = 0;
  260. X
  261. X   jul = GetTriggerDate(d, m, y, wd, cons, back, repeat, omit);
  262. X   if (Calendar) {
  263. X      if (jul == JulianToday && tok.type == Msg_t) {
  264. X         while (isspace(**s)) (*s)++;
  265. X         strcpy(WorkBuf, *s);
  266. X         CalTime = tim;
  267. X     return 1;
  268. X      } else return 0;
  269. X   }
  270. X     
  271. X   if (jul == -1) {
  272. X      if (Debug) Eprint("Reminder has expired.\n");
  273. X      return -1;
  274. X   }
  275. X   FromJulian(jul, &d2, &m2, &y2);
  276. X
  277. X   /* Figure out if the reminder should be triggered */
  278. X   
  279. X   trigger = MoveBack(jul, delta, d2, m2, y2, omit);
  280. X
  281. X   if(Debug) {
  282. X      Eprint("%sTrigger date: %s, %d %s, %d.\n", 
  283. X              (trigger <= JulianToday ? "*" : ""), DayName[jul % 7], 
  284. X          d2, MonthName[m2], y2);
  285. X      return 0;
  286. X   }
  287. X   if (Purge || (once && (LastRun == JulianToday))) return 0;
  288. X
  289. X   while (isspace(**s)) (*s)++;
  290. X
  291. X   if (trigger <= JulianToday && !(tok.type == Run_t && IgRun)) { 
  292. X      /* Trigger a reminder */
  293. X#ifdef UNIX
  294. X      if (QueueAts && (jul == JulianToday) && (tim != -1)) {
  295. X         DoAt(tim, tdelta, trep, *s, tok.type);
  296. X      }
  297. X      if (!PrintAts && (jul == JulianToday) && tim != -1) return 0;
  298. X#endif
  299. X      if (tok.type == Msg_t) {
  300. X         if (NumEmitted == 0) {
  301. X            NumEmitted++;
  302. X            DoSubst(Banner, WorkBuf, CurDay, CurMon, CurYear, 
  303. X                    JulianToday, Msg_t, (int) (SystemTime()/ 60));
  304. X            printf("%s\n", WorkBuf);
  305. X         }
  306. X         DoSubst(*s, WorkBuf, d2, m2, y2, jul, tok.type, tim);
  307. X         printf("%s\n", WorkBuf);
  308. X      }
  309. X      else if (tok.type == Run_t) {
  310. X         DoSubst(*s, WorkBuf, d2, m2, y2, jul, tok.type, tim);
  311. X         system(WorkBuf);
  312. X      }
  313. X      else Eprint("Error: Invalid token type %d\n", tok.type);
  314. X      return 1;
  315. X   } else return 0;
  316. X
  317. X}
  318. X
  319. X/***************************************************************/
  320. X/*                                                             */
  321. X/* GetTriggerDate                                              */
  322. X/*                                                             */
  323. X/* Gets the trigger date for a reminder, returns the julian    */
  324. X/* date, or -1 if the reminder has expired.                    */
  325. X/*                                                             */
  326. X/***************************************************************/
  327. X#ifndef UNIX
  328. Xint GetTriggerDate(int d, int m, int y, int wd, int cons, int back, int repeat, int omit)
  329. X#else
  330. Xint GetTriggerDate(d, m, y, wd, cons, back, repeat, omit)
  331. Xint d, m, y, wd, cons, back, repeat, omit;
  332. X#endif
  333. X{
  334. X   int i, d2, m2, y2, jul;
  335. X
  336. X   i = TryNextDate(&d2, &m2, &y2, CurDay, CurMon, CurYear,
  337. X           d, m, y, wd, cons, 0);
  338. X
  339. X   if (i && !repeat) return -1;
  340. X
  341. X   jul = Julian(d2, m2, y2);
  342. X   if (repeat) {
  343. X      if (back) jul = MoveBack(jul, back, d2, m2, y2, omit);
  344. X
  345. X      if (jul < JulianToday) {
  346. X         jul += ((JulianToday - jul) / repeat) * repeat;
  347. X         if (jul < JulianToday) jul += repeat;
  348. X      }
  349. X      return jul;
  350. X
  351. X   } else {
  352. X      if (back) {
  353. X         jul = MoveBack(jul, back, d2, m2, y2, omit);
  354. X         while (jul < JulianToday) {
  355. X            i = TryNextDate(&d2, &m2, &y2, d2, m2, y2,
  356. X             d, m, y, wd, cons, 1);
  357. X        if (i) return -1;
  358. X            jul = Julian(d2, m2, y2);
  359. X        jul = MoveBack(jul, back, d2, m2, y2, omit);
  360. X         }
  361. X         
  362. X      }
  363. X   return jul;
  364. X   }
  365. X}
  366. SHAR_EOF
  367. $TOUCH -am 1115094090 dorem.c &&
  368. chmod 0600 dorem.c ||
  369. echo "restore of dorem.c failed"
  370. set `wc -c dorem.c`;Wc_c=$1
  371. if test "$Wc_c" != "8966"; then
  372.     echo original size 8966, current size $Wc_c
  373. fi
  374. fi
  375. # ============= dosubst.c ==============
  376. if test X"$1" != X"-c" -a -f 'dosubst.c'; then
  377.     echo "File already exists: skipping 'dosubst.c'"
  378. else
  379. echo "x - extracting dosubst.c (Text)"
  380. sed 's/^X//' << 'SHAR_EOF' > dosubst.c &&
  381. X#include <ctype.h>
  382. X#include <stdio.h>
  383. X#ifndef UNIX
  384. X#include <string.h>
  385. X#endif
  386. X#include "defines.h"
  387. X#include "globals.h"
  388. X#include "protos.h"
  389. X
  390. X#define ABS(x) ( ((x) < 0) ? (-(x)) : (x))
  391. X
  392. X/***************************************************************/
  393. X/*                                                             */
  394. X/*  DOSUBST.C                                                  */
  395. X/*                                                             */
  396. X/*  Performs line substitution for reminders.                  */
  397. X/*                                                             */
  398. X/***************************************************************/
  399. X
  400. Xstatic char TODAY[] = "today";
  401. Xstatic char TOMORROW[] = "tomorrow";
  402. X
  403. X#ifndef UNIX
  404. Xint DoSubst(char *src, char *dst, int d, int m, int y, int jul, enum Token_t t, int tim)
  405. X#else
  406. Xint DoSubst(src, dst, d, m, y, jul, t, tim)
  407. X     char *src;
  408. X     char *dst;
  409. X     int d;
  410. X     int m;
  411. X     int y;
  412. X     int jul;
  413. X     enum Token_t t;
  414. X     int tim;
  415. X#endif
  416. X{
  417. X   int diff = jul - JulianToday;
  418. X   char c;
  419. X   char *od;
  420. X   int wkday = jul % 7;
  421. X   char *plu, *pm;
  422. X   int curtim = (int) (SystemTime() / 60);
  423. X   int done;
  424. X   int h;
  425. X   int hh;
  426. X   int min;
  427. X   int tdiff;
  428. X   int adiff, mdiff, hdiff;
  429. X   char *mplu, *hplu, *when;
  430. X   
  431. X   if (tim == -1) tim = curtim;
  432. X   tdiff = tim - curtim;
  433. X   adiff = ABS(tdiff);
  434. X   mdiff = adiff % 60;
  435. X   hdiff = adiff / 60;
  436. X   mplu = (mdiff == 1 ? "" : "s");
  437. X   hplu = (hdiff == 1 ? "" : "s");
  438. X   when = (tdiff < 0 ? "ago" : "from now");
  439. X   
  440. X   h = tim / 60;
  441. X   min = tim % 60;
  442. X
  443. X   if (h >= 12) pm = "pm"; else pm = "am";
  444. X   if (h == 12) hh = 12; else hh = h % 12;
  445. X
  446. X   *dst = 0;
  447. X   
  448. X   switch(d) {
  449. X      case 1:
  450. X      case 21:
  451. X      case 31: plu = "st"; break;
  452. X      
  453. X      case 2:
  454. X      case 22: plu = "nd"; break;
  455. X      
  456. X      case 3:
  457. X      case 23: plu = "rd"; break;
  458. X      
  459. X      default: plu = "th"; break;
  460. X   }
  461. X      
  462. X   
  463. X   while (c = *src++) {
  464. X     if (c == '\n') continue;
  465. X     else if (c != '%') { *dst++ = c; *dst = 0; }
  466. X     else {
  467. X         od = dst;
  468. X         c = *src++;
  469. X     done = 0;
  470. X         if (diff <= 1) {
  471. X            switch(upper(c)) {
  472. X               case 'A':
  473. X               case 'B':
  474. X           case 'C':
  475. X           case 'E':
  476. X           case 'F':
  477. X           case 'G':
  478. X           case 'H':
  479. X           case 'I':
  480. X           case 'J':
  481. X           case 'K':
  482. X           case 'L':
  483. X           case 'U':
  484. X           case 'V': sprintf(dst, "%s", (diff ? TOMORROW : TODAY));
  485. X                 dst += strlen(dst);
  486. X                 done = 1;
  487. X                  break;
  488. X             
  489. X               default: done = 0;
  490. X            }
  491. X     }         
  492. X     
  493. X     if (!done) switch(upper(c)) {
  494. X        case 0: *dst = 0; return 0;
  495. X        
  496. X           case 'A':
  497. X               sprintf(dst, "on %s, %d %s, %d", DayName[wkday], d,
  498. X                      MonthName[m], y);
  499. X               dst += strlen(dst);
  500. X           break;
  501. X           
  502. X        case 'B':
  503. X               sprintf(dst, "in %d days' time", diff);
  504. X           dst += strlen(dst);
  505. X               break;
  506. X           
  507. X        case 'C':
  508. X               sprintf(dst, "on %s", DayName[wkday]);
  509. X               dst += strlen(dst);
  510. X           break;
  511. X           
  512. X        case 'D':
  513. X           sprintf(dst, "%d", d);
  514. X           dst += strlen(dst);
  515. X               break;
  516. X           
  517. X        case 'E':
  518. X           sprintf(dst, "on %02d/%02d/%04d", d, m+1, y);
  519. X           dst += strlen(dst);
  520. X               break;
  521. X           
  522. X        case 'F':
  523. X           sprintf(dst, "on %02d/%02d/%04d", m+1, d, y);
  524. X           dst += strlen(dst);
  525. X               break;
  526. X
  527. X        case 'G':
  528. X               sprintf(dst, "on %s, %d %s", DayName[wkday], d, MonthName[m]);
  529. X           dst += strlen(dst);
  530. X               break;
  531. X           
  532. X        case 'H':
  533. X               sprintf(dst, "on %02d/%02d", d, m+1);
  534. X           dst += strlen(dst);
  535. X               break;
  536. X
  537. X        case 'I':
  538. X               sprintf(dst, "on %02d/%02d", m+1, d);
  539. X           dst += strlen(dst);
  540. X               break;
  541. X           
  542. X        case 'J':
  543. X               sprintf(dst, "on %s, %s %d%s, %d", DayName[wkday],
  544. X                      MonthName[m], d, plu, y);
  545. X               dst += strlen(dst);
  546. X               break;
  547. X        
  548. X        case 'K':
  549. X           sprintf(dst, "on %s, %s %d%s", DayName[wkday],
  550. X                          MonthName[m], d, plu);
  551. X           dst += strlen(dst);
  552. X               break;
  553. X                         
  554. X            case 'L':
  555. X           sprintf(dst, "on %04d/%02d/%02d", y, m+1, d);
  556. X           dst += strlen(dst);
  557. X               break;
  558. X           
  559. X        case 'M':
  560. X           sprintf(dst, "%s", MonthName[m]);
  561. X           dst += strlen(dst);
  562. X               break;
  563. X           
  564. X        case 'N':
  565. X           sprintf(dst, "%d", m+1);
  566. X           dst += strlen(dst);
  567. X               break;
  568. X
  569. X        case 'O':
  570. X               if (RealToday == JulianToday) sprintf(dst, " (today)");
  571. X               dst += strlen(dst);
  572. X               break;
  573. X           
  574. X        case 'P':
  575. X           sprintf(dst, (diff == 1 ? "" : "s"));
  576. X           dst += strlen(dst);
  577. X               break;
  578. X           
  579. X        case 'Q':
  580. X           sprintf(dst, (diff == 1 ? "'s" : "s'"));
  581. X           dst += strlen(dst);
  582. X               break;
  583. X           
  584. X        case 'R':
  585. X           sprintf(dst, "%02d", d);
  586. X           dst += strlen(dst);
  587. X               break;
  588. X           
  589. X        case 'S':
  590. X           sprintf(dst, plu);
  591. X           dst += strlen(dst);
  592. X               break;
  593. X           
  594. X        case 'T':
  595. X           sprintf(dst, "%02d", m+1);
  596. X           dst += strlen(dst);
  597. X               break;
  598. X           
  599. X        case 'U':
  600. X           sprintf(dst, "on %s, %d%s %s, %d", DayName[wkday], d,
  601. X                          plu, MonthName[m], y);
  602. X           dst += strlen(dst);
  603. X               break;
  604. X           
  605. X        case 'V':
  606. X           sprintf(dst, "on %s, %d%s %s", DayName[wkday], d, plu,
  607. X                          MonthName[m]);
  608. X           dst += strlen(dst);
  609. X               break;
  610. X           
  611. X        case 'W':
  612. X           sprintf(dst, DayName[wkday]);
  613. X           dst += strlen(dst);
  614. X               break;
  615. X           
  616. X        case 'X':
  617. X           sprintf(dst, "%d", diff);
  618. X           dst += strlen(dst);
  619. X               break;
  620. X           
  621. X        case 'Y':
  622. X           sprintf(dst, "%d", y);
  623. X           dst += strlen(dst);
  624. X               break;
  625. X           
  626. X        case 'Z':
  627. X           sprintf(dst, "%d", y % 100);
  628. X           dst += strlen(dst);
  629. X               break;
  630. X
  631. X        case '1':
  632. X               if (tdiff == 0) 
  633. X                  sprintf(dst, "now");
  634. X               else if (hdiff == 0) 
  635. X              sprintf(dst, "%d minute%s %s", mdiff, mplu, when);
  636. X           else if (mdiff == 0)
  637. X              sprintf(dst, "%d hour%s %s", hdiff, hplu, when);
  638. X               else
  639. X              sprintf(dst, "%d hour%s and %d minute%s %s", hdiff, hplu, mdiff, mplu, when);
  640. X           dst += strlen(dst);
  641. X               break;
  642. X
  643. X            case '2':
  644. X               sprintf(dst, "at %d:%02d%s", hh, min, pm);
  645. X           dst += strlen(dst);
  646. X           break;
  647. X
  648. X        case '3': sprintf(dst, "at %02d:%02d", h, min);
  649. X           dst += strlen(dst);
  650. X           break;
  651. X
  652. X        case '4': sprintf(dst, "%d", tdiff);
  653. X           dst += strlen(dst);
  654. X           break;
  655. X           
  656. X        case '5': sprintf(dst, "%d", adiff);
  657. X           dst += strlen(dst);
  658. X           break;
  659. X
  660. X            case '6': sprintf(dst, when);
  661. X           dst += strlen(dst);
  662. X           break;
  663. X
  664. X        case '7': sprintf(dst, "%d", hdiff);
  665. X           dst += strlen(dst);
  666. X           break;
  667. X
  668. X        case '8': sprintf(dst, "%d", mdiff);
  669. X           dst += strlen(dst);
  670. X           break;
  671. X
  672. X        case '9': sprintf(dst, mplu);
  673. X           dst += strlen(dst);
  674. X           break;
  675. X
  676. X        case '0': sprintf(dst, hplu);
  677. X           dst += strlen(dst);
  678. X           break;
  679. X
  680. X            case '!': sprintf(dst, (tdiff >= 0 ? "is" : "was"));
  681. X           dst += strlen(dst);
  682. X           break;
  683. X        
  684. X            case '_': *dst++ = '\n'; *dst = 0;
  685. X           break;
  686. X
  687. X        case '\"': break;  /* Ignore the %" marker */
  688. X            default:
  689. X           *dst++ = c;
  690. X           *dst = 0;
  691. X     }
  692. X     if (isupper(c)) *od = upper(*od);
  693. X      }
  694. X   }
  695. X   if (t == Msg_t) *dst++ = '\n';
  696. X   *dst = 0;
  697. X   return 0;
  698. X}   
  699. SHAR_EOF
  700. $TOUCH -am 1116095790 dosubst.c &&
  701. chmod 0600 dosubst.c ||
  702. echo "restore of dosubst.c failed"
  703. set `wc -c dosubst.c`;Wc_c=$1
  704. if test "$Wc_c" != "7683"; then
  705.     echo original size 7683, current size $Wc_c
  706. fi
  707. fi
  708. # ============= files.c ==============
  709. if test X"$1" != X"-c" -a -f 'files.c'; then
  710.     echo "File already exists: skipping 'files.c'"
  711. else
  712. echo "x - extracting files.c (Text)"
  713. sed 's/^X//' << 'SHAR_EOF' > files.c &&
  714. X#include <stdio.h>
  715. X#ifndef UNIX
  716. X#include <stdlib.h>
  717. X#endif
  718. X#include <string.h>
  719. X#include <malloc.h>
  720. X#ifndef UNIX
  721. X#include <dos.h>
  722. X#endif
  723. X#include <fcntl.h>
  724. X#ifdef UNIX
  725. X#include <sys/types.h>
  726. X#include <sys/stat.h>
  727. X#include <time.h>
  728. X#endif
  729. X#include "defines.h"
  730. X#include "globals.h"
  731. X#include "protos.h"
  732. X
  733. X#ifndef UNIX
  734. Xstatic int PopFile(void);
  735. X#else
  736. Xstatic int PopFile();
  737. X#endif
  738. X
  739. X/***************************************************************/
  740. X/*                                                             */
  741. X/*  FILES.C                                                    */
  742. X/*                                                             */
  743. X/*  All the routines for opening initial file, getting         */
  744. X/*  and settting initial file's date, closing files,           */
  745. X/*  handling INCLUDE commands, etc.                            */
  746. X/*                                                             */
  747. X/***************************************************************/
  748. X
  749. X/* Define the structure for saving info about a file */
  750. Xtypedef struct {
  751. X   long offset;
  752. X   int  curline;
  753. X   char *name;
  754. X} FileSave;
  755. X
  756. X#define MAXINCLUDE 10
  757. X/* Set up array of MAXINCLUDE file save areas */
  758. Xstatic FileSave stack[MAXINCLUDE];
  759. Xstatic int      SP;
  760. X
  761. Xstatic FILE *fp;
  762. X
  763. X/***************************************************************/
  764. X/*                                                             */
  765. X/*  OpenFile                                                   */
  766. X/*                                                             */
  767. X/*  Open the named file, initialize stack, get file date.      */
  768. X/*  If there's a problem, print an error msg and die.          */
  769. X/*                                                             */
  770. X/***************************************************************/
  771. X#ifndef UNIX
  772. Xvoid OpenFile(char *s)
  773. X#else
  774. Xvoid OpenFile(s)
  775. X     char *s;
  776. X     
  777. X#endif
  778. X{
  779. X   unsigned date, time;
  780. X#ifndef UNIX
  781. X   unsigned handle;
  782. X#endif
  783. X   int d, m, y;
  784. X#ifndef UNIX
  785. X   
  786. X   /* Get the file's modification date */
  787. X   if(_dos_open(s, O_RDONLY, &handle)) {
  788. X      fprintf(stderr, "remind: Can't open %s.\n", s);
  789. X      exit(1);
  790. X#else
  791. X   struct stat t;
  792. X   struct tm *t1;
  793. X      
  794. X   /* Get the file's access date */
  795. X   if (stat(s, &t)) {
  796. X     fprintf(stderr, "remind: Can't find file %s.\n", s);
  797. X     exit(1);
  798. X#endif
  799. X   }
  800. X#ifndef UNIX
  801. X   _dos_getftime(handle, &date, &time);
  802. X   d = date & 0x1F;
  803. X   m = (date >> 5) & 0xF;
  804. X   y = (date >> 9) + 1980;
  805. X#else
  806. X   t1 = localtime(&(t.st_atime));
  807. X#endif
  808. X   
  809. X#ifndef UNIX
  810. X   if (y < BASE) LastRun = 0; else LastRun = Julian(d, m-1, y);
  811. X   _dos_close(handle);
  812. X#else
  813. X   y = t1->tm_year + 1900;
  814. X   m = t1->tm_mon;
  815. X   d = t1->tm_mday;
  816. X   
  817. X   if (y < BASE) LastRun = 0; else LastRun = Julian(d, m, y);
  818. X#endif
  819. X   fp = fopen(s, "r");
  820. X   if (fp == NULL) {
  821. X      fprintf(stderr, "remind: Can't open %s.\n", s);
  822. X      exit(1);
  823. X   }
  824. X   
  825. X   CurLine = 0;
  826. X   strcpy(FileName, s);
  827. X   SP = 0;
  828. X   
  829. X   return;
  830. X}   
  831. X
  832. X/***************************************************************/
  833. X/*                                                             */
  834. X/*  DoInclude                                                  */
  835. X/*                                                             */
  836. X/*  Push the state of the current file and open a new file.    */
  837. X/*                                                             */
  838. X/***************************************************************/
  839. X#ifndef UNIX
  840. Xvoid DoInclude(char **s)
  841. X#else
  842. Xvoid DoInclude(s)
  843. X     char **s;
  844. X     
  845. X#endif
  846. X{
  847. X   Token tok;
  848. X   tok = ParseToken(s);
  849. X   
  850. X   /* First, check if there's room on the stack */
  851. X   if (SP == MAXINCLUDE) {
  852. X      Eprint("Too many levels of INCLUDE\n");
  853. X      return;
  854. X   }
  855. X   
  856. X   /* Save current data */
  857. X#ifndef UNIX
  858. X   stack[SP].offset = ftell(fp) - 1L;
  859. X#else
  860. X   stack[SP].offset = ftell(fp);
  861. X#endif
  862. X   stack[SP].curline = CurLine;
  863. X   stack[SP].name = (char *) malloc(strlen(FileName)+1);
  864. X   if (stack[SP].name == NULL) {
  865. X      Eprint("Out of memory for INCLUDE\n");
  866. X      return;
  867. X   }
  868. X   strcpy(stack[SP].name, FileName);
  869. X   
  870. X   SP++;
  871. X   
  872. X   /* Close the current file */
  873. X   fclose(fp);
  874. X   
  875. X   /* Open the new file */
  876. X   fp = fopen(tok.str, "r");
  877. X   if (fp == NULL) {
  878. X      Eprint("Can't open %s for INCLUDE\n", tok.str);
  879. X      PopFile();
  880. X      return;
  881. X   }
  882. X   if (Debug || Purge) {
  883. X      Eprint("INCLUDING file %s\n", tok.str);
  884. X   }
  885. X   
  886. X   /* Set the global variables */
  887. X   CurLine = 0;
  888. X   strcpy(FileName, tok.str);
  889. X   return;
  890. X}
  891. X
  892. X/***************************************************************/
  893. X/*                                                             */
  894. X/*  PopFile                                                    */
  895. X/*                                                             */
  896. X/*  Pop to the previous file, if there is one.  Return 0 for   */
  897. X/*  OK, non-zero for no more files.  If we can't pop back      */
  898. X/*  to a file, print an error message and die.                 */
  899. X/*                                                             */
  900. X/***************************************************************/
  901. X#ifndef UNIX
  902. Xstatic int PopFile(void)
  903. X#else
  904. Xstatic int PopFile()
  905. X#endif
  906. X{
  907. X#ifndef UNIX
  908. X   unsigned handle, date, time;
  909. X   struct dostime_t t;
  910. X#endif
  911. X
  912. X   if (fp) fclose(fp);
  913. X#ifndef UNIX
  914. X   if (!SP) {
  915. X      if (!Debug && !Purge && (JulianToday == RealToday)) {
  916. X         if (_dos_open(FileName, O_RDONLY, &handle)) {
  917. X            fprintf(stderr, "Could not reset date of %s", FileName);
  918. X            return 1;
  919. X         }
  920. X     _dos_gettime(&t);
  921. X     date = CurDay;
  922. X     date |= (CurMon + 1) << 5;
  923. X     date |= (CurYear - 1980) << 9;
  924. X     time = t.second / 2;
  925. X     time |= t.minute << 5;
  926. X     time |= t.hour << 11;
  927. X     _dos_setftime(handle, date, time);
  928. X      }
  929. X      return 1;
  930. X   }
  931. X      
  932. X#else
  933. X   if (!SP) return -1;
  934. X         
  935. X#endif
  936. X   SP--;
  937. X   fp = fopen(stack[SP].name, "r");
  938. X   if (fp == NULL) {
  939. X      Eprint("Argh! Can't return to %s from INCLUDE file %s", stack[SP].name, FileName);
  940. X      exit(1);
  941. X   }
  942. X#ifndef UNIX
  943. X   if (fseek(fp, stack[SP].offset, SEEK_SET)) {
  944. X#else
  945. X   if (fseek(fp, stack[SP].offset, 0)) {
  946. X#endif
  947. X      Eprint("Argh! Can't fseek %s after returning from INCLUDE file %s", stack[SP].name, FileName);
  948. X      exit(1);
  949. X   }
  950. X   
  951. X   if (Debug || Purge) {
  952. X      Eprint("Returning to file %s\n", stack[SP].name);
  953. X   }
  954. X   CurLine = stack[SP].curline;
  955. X   strcpy(FileName, stack[SP].name);
  956. X   free(stack[SP].name);
  957. X   return 0;
  958. X}
  959. X/***************************************************************/
  960. X/*                                                             */
  961. X/*  ReadLine                                                   */
  962. X/*                                                             */
  963. X/*  Reads a line from the file.  If EOF, pops to previous file */
  964. X/*  if there was one.  Returns 0 if more input, non-zero       */
  965. X/*  if no more input.  Updates CurLine.                        */
  966. X/*                                                             */
  967. X/***************************************************************/
  968. Xint ReadLine()
  969. X{
  970. X   int done = 0;
  971. X   int len;
  972. X   
  973. X   Fresh = 1;
  974. X   while (!done) {
  975. X      CurLine++;
  976. X      if (fgets(Line, 512, fp) == NULL) {
  977. X         if (ferror(fp)) Eprint("Error reading %s", FileName);
  978. X     if (PopFile()) return 1;
  979. X      } else {
  980. X         len = strlen(Line);
  981. X         /* Remove the newline */
  982. X         if (*Line && (*(Line + len-1)=='\n')) {
  983. X            *(Line + strlen(Line)-1) = 0;
  984. X            len--;
  985. X         }
  986. X         done = 1;
  987. X         while(*Line && (*(Line + len-1) == '\\') && len<512) {
  988. X         *(Line + len-1) = '\n';
  989. X            if (fgets(Line+len, 512-len,fp) == NULL) {
  990. X               *(Line + len) = 0;
  991. X             break;
  992. X        }
  993. X
  994. X        CurLine++;
  995. X        len = strlen(Line);
  996. X            /* Remove the newline */
  997. X            if (*Line && (*(Line + len-1)=='\n')) {
  998. X               *(Line + strlen(Line)-1) = 0;
  999. X               len--;
  1000. X            }
  1001. X         }
  1002. X      }     
  1003. X   }
  1004. X   return 0;
  1005. X}
  1006. X
  1007. X/***************************************************************/
  1008. X/*                                                             */
  1009. X/*  TopLevel - Returns 1 if current file is top level, 0       */
  1010. X/*  if it is INCLUDEd.                                         */
  1011. X/*                                                             */
  1012. X/***************************************************************/
  1013. X#ifndef UNIX
  1014. Xint TopLevel(void) { return (SP == 0); }
  1015. X#else
  1016. Xint TopLevel()
  1017. X{
  1018. X  return (SP == 0);
  1019. X}
  1020. X#endif
  1021. SHAR_EOF
  1022. $TOUCH -am 1115093990 files.c &&
  1023. chmod 0600 files.c ||
  1024. echo "restore of files.c failed"
  1025. set `wc -c files.c`;Wc_c=$1
  1026. if test "$Wc_c" != "8338"; then
  1027.     echo original size 8338, current size $Wc_c
  1028. fi
  1029. fi
  1030. # ============= globals.h ==============
  1031. if test X"$1" != X"-c" -a -f 'globals.h'; then
  1032.     echo "File already exists: skipping 'globals.h'"
  1033. else
  1034. echo "x - extracting globals.h (Text)"
  1035. sed 's/^X//' << 'SHAR_EOF' > globals.h &&
  1036. X/***************************************************************/
  1037. X/*                                                             */
  1038. X/*  GLOBALS.H                                                  */
  1039. X/*                                                             */
  1040. X/*  Global variables for REMIND.                               */
  1041. X/*                                                             */
  1042. X/*  By David Skoll - 30 Sept. 1990                             */
  1043. X/*                                                             */
  1044. X/***************************************************************/
  1045. X
  1046. Xextern char *MonthName[];
  1047. Xextern char *DayName[];
  1048. Xextern Token keywd[];
  1049. Xextern int   MonthDays[];
  1050. Xextern int   MonthIndex[2][12];
  1051. Xextern int   FullOmitArray[];
  1052. Xextern int   PartOmitArray[];
  1053. Xextern char  Line[];
  1054. Xextern char  WorkBuf[];
  1055. Xextern char  TmpBuf[];
  1056. Xextern int   Fresh;
  1057. Xextern int   Purge;
  1058. Xextern int   Debug;
  1059. Xextern int   Verbose;
  1060. Xextern char  FileName[];
  1061. Xextern int   CurLine;
  1062. Xextern int   NumEmitted;
  1063. Xextern int   NumRem;
  1064. Xextern int   NumFullOmit;
  1065. Xextern int   NumPartOmit;
  1066. Xextern int   JulianToday;
  1067. Xextern int   LastRun;
  1068. Xextern int   CurYear;
  1069. Xextern int   CurMon;
  1070. Xextern int   CurDay;
  1071. Xextern char  Banner[];
  1072. Xextern int   RealToday;
  1073. Xextern int   IgRun;
  1074. Xextern int   IgOnce;
  1075. Xextern int   NumAtsQueued;
  1076. Xextern int   QueueAts;
  1077. Xextern int   PrintAts;
  1078. Xextern int   Calendar;
  1079. Xextern int   CalTime;
  1080. Xextern int   CalWidth;
  1081. Xextern int   SimpleCalendar;
  1082. SHAR_EOF
  1083. $TOUCH -am 1115094990 globals.h &&
  1084. chmod 0600 globals.h ||
  1085. echo "restore of globals.h failed"
  1086. set `wc -c globals.h`;Wc_c=$1
  1087. if test "$Wc_c" != "1450"; then
  1088.     echo original size 1450, current size $Wc_c
  1089. fi
  1090. fi
  1091. # ============= init.c ==============
  1092. if test X"$1" != X"-c" -a -f 'init.c'; then
  1093.     echo "File already exists: skipping 'init.c'"
  1094. else
  1095. echo "x - extracting init.c (Text)"
  1096. sed 's/^X//' << 'SHAR_EOF' > init.c &&
  1097. X#include <stdio.h>
  1098. X#ifndef UNIX
  1099. X#include <stdlib.h>
  1100. X#endif
  1101. X#include <string.h>
  1102. X#include "defines.h"
  1103. X#include "globals.h"
  1104. X#include "protos.h"
  1105. X
  1106. X#define PATCHLEVEL 0
  1107. X
  1108. Xstatic char DPMsg[] = "Debug and Purge options conflict - Purge chosen.\n";
  1109. Xstatic char DPCMsg[] = "Calendar overrides Debug and Purge options.\n";
  1110. X/***************************************************************/
  1111. X/*                                                             */
  1112. X/*  void initialize(int argc, char *argv[])                    */
  1113. X/*                                                             */
  1114. X/*  Reads command line options, sets appropriate flags         */
  1115. X/*  and FileName.  Also exits with error if invoked            */
  1116. X/*  incorrectly.                                               */
  1117. X/*                                                             */
  1118. X/***************************************************************/
  1119. X#ifndef UNIX
  1120. Xvoid initialize(int argc, char *argv[])
  1121. X#else
  1122. Xvoid initialize(argc, argv)
  1123. X     int argc;
  1124. X     char *argv[];
  1125. X#endif
  1126. X{
  1127. X   int i;
  1128. X   char *s;
  1129. X   int d, m, y, t;
  1130. X   Token tok;
  1131. X
  1132. X   Debug    = 0;
  1133. X   Purge    = 0;
  1134. X   Verbose  = 0;
  1135. X   IgOnce   = 0;
  1136. X   IgRun    = 0;
  1137. X   Calendar = 0;
  1138. X   PrintAts = 1;
  1139. X   QueueAts = 1;
  1140. X   CalWidth = 10;
  1141. X   SimpleCalendar = 0;
  1142. X
  1143. X   if(argc == 1) {
  1144. X     fprintf(stderr, "\nREMIND 2.2 Patch Level %d (C) 1990 by David Skoll.\n\n", PATCHLEVEL);
  1145. X#ifdef UNIX
  1146. X     fprintf(stderr, "Usage: remind [-d | -p | -c# [-w# | -s]] [-voraq] filename [date]\n\n");
  1147. X#else
  1148. X     fprintf(stderr, "Usage: remind [-d | -p | -c# [-w# | -s]] [-vor] filename [date]\n\n");
  1149. X#endif
  1150. X     fprintf(stderr, "-d   Debug reminder file\n-p   Purge reminder file\n");
  1151. X     fprintf(stderr, "-c#  Produce calendar for # months\n");
  1152. X     fprintf(stderr, "-w#  Make calendar # columns wide\n");
  1153. X     fprintf(stderr, "-s   Produce simple calendar listing\n");
  1154. X     fprintf(stderr, "-v   Verbose messages\n-o   Ignore ONCE directives\n");
  1155. X     fprintf(stderr, "-r   Ignore RUN directives\n");
  1156. X#ifdef UNIX
  1157. X     fprintf(stderr, "-a   Do not trigger current AT reminders in foreground\n");
  1158. X     fprintf(stderr, "-q   Do not queue current AT reminders\n\n");
  1159. X#endif
  1160. X     exit(1);
  1161. X   }
  1162. X
  1163. X   i = 1;
  1164. X   s = argv[i];
  1165. X
  1166. X   /* Process options */
  1167. X   while (*s == '-') {
  1168. X      while (*++s) {
  1169. X         switch(upper(*s)) {
  1170. X
  1171. X            case 'P':  Purge = 1;
  1172. X             if (Calendar) {
  1173. X                Debug = Purge = 0;
  1174. X            fprintf(stderr, DPCMsg);
  1175. X                 }
  1176. X                     if (Debug) {
  1177. X                        Debug = 0;
  1178. X                        fprintf(stderr, DPMsg);
  1179. X                     }
  1180. X             break;
  1181. X             
  1182. X            case 'D': Debug = 1;
  1183. X             if (Calendar) {
  1184. X                Debug = Purge = 0;
  1185. X            fprintf(stderr, DPCMsg);
  1186. X                 }
  1187. X                  if (Purge) {
  1188. X                 Debug = 0;
  1189. X             fprintf(stderr, DPMsg);
  1190. X              }
  1191. X              break;
  1192. X
  1193. X            case 'C': Calendar = 1;
  1194. X             if (Debug || Purge) {
  1195. X                Debug = Purge = 0;
  1196. X            fprintf(stderr, DPCMsg);
  1197. X                 }
  1198. X                     t = atoi(s + 1);
  1199. X             if (t > 0 && t <= 12) Calendar = t;
  1200. X                     /* Skip remaining chars on this option */
  1201. X                 while (*++s) ;
  1202. X                 s--;
  1203. X             break;
  1204. X
  1205. X        case 'W': CalWidth = (atoi(s+1)-9)/7;
  1206. X                 if (CalWidth < 10) CalWidth = 10;
  1207. X             if (CalWidth > 40) CalWidth = 40;
  1208. X                 while (*++s) ;
  1209. X                 s--;
  1210. X             break;
  1211. X
  1212. X            case 'S': SimpleCalendar = 1; break;
  1213. X
  1214. X        case 'V': Verbose = 1; break;
  1215. X
  1216. X        case 'O': IgOnce = 1; break;
  1217. X
  1218. X        case 'R': IgRun = 1; break;
  1219. X#ifdef UNIX
  1220. X        case 'A': PrintAts = 0; break;
  1221. X
  1222. X            case 'Q': QueueAts = 0; break;          
  1223. X#endif        
  1224. X        default: fprintf(stderr, "Unknown option '%c' ignored.\n", *s);
  1225. X     }                  
  1226. X      }
  1227. X      i++;
  1228. X      if (i >= argc) {
  1229. X    fprintf(stderr, "Missing filename - type 'remind' for usage information.\n");
  1230. X     exit(1);
  1231. X      }
  1232. X      s = argv[i];
  1233. X   }     
  1234. X   
  1235. X   /* Set FileName */
  1236. X   strcpy(FileName, argv[i++]);
  1237. X   
  1238. X   /* Get date, if supplied */
  1239. X   if (i < argc) {
  1240. X      *WorkBuf = 0;
  1241. X      while (i < argc) {
  1242. X         strcat(WorkBuf, argv[i++]);
  1243. X     strcat(WorkBuf, " ");
  1244. X      }
  1245. X      /* Parse the date */
  1246. X      d = m = y = -1;
  1247. X      tok.type = Unknown_t;
  1248. X      s = WorkBuf;
  1249. X      while (tok.type != Eol_t) {
  1250. X         tok = ParseToken(&s);
  1251. X     switch(tok.type) {
  1252. X        
  1253. X        case Eol_t: break;
  1254. X        
  1255. X        case Year_t: if (y == -1) 
  1256. X                        y = tok.val;
  1257. X             else {
  1258. X                fprintf(stderr, "Year specified twice!\n");
  1259. X                exit(1);
  1260. X             }
  1261. X             break;
  1262. X             
  1263. X        case Month_t: if (m == -1) 
  1264. X                        m = tok.val;
  1265. X             else {
  1266. X                fprintf(stderr, "Month specified twice!\n");
  1267. X                exit(1);
  1268. X             }
  1269. X             break;
  1270. X             
  1271. X        case Day_t: if (d == -1) 
  1272. X                        d = tok.val;
  1273. X             else {
  1274. X                fprintf(stderr, "Day specified twice!\n");
  1275. X                exit(1);
  1276. X             }
  1277. X             break;
  1278. X       
  1279. X            default: fprintf(stderr, "Illegal token %s on command line.\n", tok.str);
  1280. X                 exit(1);
  1281. X   
  1282. X         }
  1283. X      } 
  1284. X      
  1285. X      if (d == -1 || m == -1 || y == -1) {
  1286. X         fprintf(stderr, "Date on command line must be fully specified.\n");
  1287. X     exit(1);
  1288. X      }
  1289. X      if (CheckDate(d, m, y)) {
  1290. X         fprintf(stderr, "Illegal date on command line.\n");
  1291. X     exit(1);
  1292. X      }
  1293. X      
  1294. X      CurDay = d;
  1295. X      CurMon = m;
  1296. X      CurYear = y;
  1297. X      JulianToday = Julian(d, m, y);
  1298. X   }
  1299. X   OpenFile(FileName);
  1300. X   if (Debug) {
  1301. X      FromJulian(LastRun, &d, &m, &y);
  1302. X#ifndef UNIX
  1303. X      fprintf(stderr, "\nFile %s last modified on %s, %d %s, %d\n", FileName,
  1304. X#else
  1305. X      fprintf(stderr, "\nFile %s last accessed on %s, %d %s, %d\n", FileName,
  1306. X#endif
  1307. X                       DayName[LastRun % 7], d, MonthName[m], y);
  1308. X   }           
  1309. X   return;
  1310. X}
  1311. SHAR_EOF
  1312. $TOUCH -am 1116094290 init.c &&
  1313. chmod 0600 init.c ||
  1314. echo "restore of init.c failed"
  1315. set `wc -c init.c`;Wc_c=$1
  1316. if test "$Wc_c" != "5675"; then
  1317.     echo original size 5675, current size $Wc_c
  1318. fi
  1319. fi
  1320. echo "End of part 2, continue with part 3"
  1321. exit 0
  1322.