home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume36 / remind / patch04b < prev    next >
Encoding:
Text File  |  1993-03-06  |  60.7 KB  |  1,853 lines

  1. Newsgroups: comp.sources.misc
  2. From: <dfs@doe.carleton.ca> (David F. Skoll)
  3. Subject: v36i002:  remind - A replacement for calendar, Patch04b/3
  4. Message-ID: <1993Mar8.040340.21098@sparky.imd.sterling.com>
  5. X-Md4-Signature: 9563706f417c7a25c12f8e8ef10f4ad1
  6. Date: Mon, 8 Mar 1993 04:03:40 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: <dfs@doe.carleton.ca> (David F. Skoll)
  10. Posting-number: Volume 36, Issue 2
  11. Archive-name: remind/patch04b
  12. Environment: UNIX, MS-DOS
  13. Patch-To: remind: Volume 33, Issue 58-69
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then feed it
  17. # into a shell via "sh file" or similar.  To overwrite existing files,
  18. # type "sh file -c".
  19. # Contents:  patch.04.B
  20. # Wrapped by kent@sparky on Sun Mar  7 21:51:01 1993
  21. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  22. echo If this archive is complete, you will see the following message:
  23. echo '          "shar: End of archive 2 (of 3)."'
  24. if test -f 'patch.04.B' -a "${1}" != "-c" ; then 
  25.   echo shar: Will not clobber existing file \"'patch.04.B'\"
  26. else
  27.   echo shar: Extracting \"'patch.04.B'\" \(58300 characters\)
  28.   sed "s/^X//" >'patch.04.B' <<'END_OF_FILE'
  29. X***************
  30. X*** 81,85 ****
  31. X--- 93,103 ----
  32. X  
  33. X  /* Define any overrides here, such as L_ORDINAL_OVERRIDE, L_A_OVER, etc.
  34. X     See the file dosubst.c for more info. */
  35. X+ #define L_AMPM_OVERRIDE(ampm, hour)    ampm = (hour < 12) ? (hour<5) ? " nachts" : " vormittags" : (hour > 17) ? " abends" : " nachmittags";
  36. X+ #define L_ORDINAL_OVERRIDE        plu = ".";
  37. X+ #define L_A_OVER            sprintf(s, "%s %s, den %d. %s %d", L_ON, DayName[jul%7], d, MonthName[m], y);
  38. X+ #define    L_G_OVER            sprintf(s, "%s %s, den %d. %s", L_ON, DayName[jul%7], d, MonthName[m]);
  39. X+ #define L_U_OVER            L_A_OVER
  40. X+ #define L_V_OVER            L_G_OVER
  41. X  
  42. X  #endif /* L_IN_DOSUBST */
  43. X*** ../patch3/globals.h    Thu Jan 21 16:02:55 1993
  44. X--- ./globals.h    Mon Mar  1 16:56:30 1993
  45. X***************
  46. X*** 36,41 ****
  47. X--- 36,42 ----
  48. X  EXTERN  char    LineBuffer[LINELEN];
  49. X  EXTERN  char    SubstBuffer[LINELEN];
  50. X  EXTERN  char    TokBuffer[TOKSIZE+1];
  51. X+ EXTERN  INIT(   char    *MsgCommand, NULL);
  52. X  EXTERN  INIT(    char    ShowAllErrors, 0);
  53. X  EXTERN  INIT(    int     DebugFlag, 0);
  54. X  EXTERN  INIT(   char    DoCalendar, 0);
  55. X***************
  56. X*** 50,55 ****
  57. X--- 51,59 ----
  58. X  EXTERN  INIT(   char    RunDisabled, 0);
  59. X  EXTERN  INIT(   char    IgnoreOnce, 0);
  60. X  EXTERN  INIT(   char    Banner[LINELEN], L_BANNER);
  61. X+ EXTERN  INIT(   char    SortByTime, 0);
  62. X+ EXTERN  INIT(   char    SortByDate, 0);
  63. X+ 
  64. X  EXTERN    char    *InitialFile;
  65. X  EXTERN    int    FileAccessDate;
  66. X  
  67. X*** ../patch3/init.c    Mon Feb  8 14:41:06 1993
  68. X--- ./init.c    Mon Mar  1 17:37:26 1993
  69. X***************
  70. X*** 62,67 ****
  71. X--- 62,68 ----
  72. X   *  -bn      = Time format for cal (0, 1, or 2)
  73. X   *  -xn      = Max. number of iterations for SATISFY
  74. X   *  -uname   = Run as user 'name' - only valid when run by root.
  75. X+  *  -kcmd    = Run 'cmd' for MSG-type reminders instead of printing to stdout
  76. X   *
  77. X   **************************************************************/
  78. X  
  79. X***************
  80. X*** 156,161 ****
  81. X--- 157,178 ----
  82. X             Hush = 1;
  83. X             break;
  84. X  
  85. X+         case 'g':
  86. X+         case 'G':
  87. X+            SortByDate = SORT_ASCEND;
  88. X+            SortByTime = SORT_ASCEND;
  89. X+            if (*arg) {
  90. X+               if (*arg == 'D' || *arg == 'd')
  91. X+              SortByDate = SORT_DESCEND;
  92. X+           arg++;
  93. X+                }
  94. X+            if (*arg) {
  95. X+               if (*arg == 'D' || *arg == 'd')
  96. X+              SortByTime = SORT_DESCEND;
  97. X+           arg++;
  98. X+                }
  99. X+            break;
  100. X+ 
  101. X  #if defined(UNIX) && defined(WANT_U_OPTION)
  102. X          case 'u':
  103. X          case 'U':
  104. X***************
  105. X*** 269,274 ****
  106. X--- 286,297 ----
  107. X             if (MaxSatIter < 10) MaxSatIter=10;
  108. X             break;
  109. X  
  110. X+         case 'k':
  111. X+         case 'K':
  112. X+            MsgCommand = arg;
  113. X+            while (*arg) arg++;  /* Chew up remaining chars in this arg */
  114. X+            break;
  115. X+ 
  116. X          default:
  117. X             fprintf(ErrFp, "Unknown option '%c'\n", *(arg-1));
  118. X       }
  119. X***************
  120. X*** 345,352 ****
  121. X  void Usage()
  122. X  #endif
  123. X  {
  124. X!    fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992, 1993 by David F. Skoll\n\n", VERSION, L_LANGNAME);
  125. X!    fprintf(ErrFp, "        Usage: remind [options] filename [date]\n");
  126. X     fprintf(ErrFp, "Options:\n");
  127. X     fprintf(ErrFp, " -n     Output next occurrence of reminders in simple format\n");
  128. X     fprintf(ErrFp, " -r     Disable RUN directives\n");
  129. X--- 368,375 ----
  130. X  void Usage()
  131. X  #endif
  132. X  {
  133. X!    fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992, 1993 by David F. Skoll\n", VERSION, L_LANGNAME);
  134. X!    fprintf(ErrFp, "Usage: remind [options] filename [date]\n");
  135. X     fprintf(ErrFp, "Options:\n");
  136. X     fprintf(ErrFp, " -n     Output next occurrence of reminders in simple format\n");
  137. X     fprintf(ErrFp, " -r     Disable RUN directives\n");
  138. X***************
  139. X*** 369,374 ****
  140. X--- 392,399 ----
  141. X     fprintf(ErrFp, " -e     Divert messages normally sent to stderr to stdout\n");
  142. X     fprintf(ErrFp, " -b[n]  Time format for cal: 0=am/pm, 1=24hr, 2=none\n");
  143. X     fprintf(ErrFp, " -x[n]  Iteration limit for SATISFY clause (def=150)\n");
  144. X+    fprintf(ErrFp, " -kcmd  Run 'cmd' for MSG-type reminders\n");
  145. X+    fprintf(ErrFp, " -g[d[d]] Sort reminders by date and time before issuing\n");
  146. X     exit(1);
  147. X  }
  148. X  
  149. X***************
  150. X*** 399,405 ****
  151. X  
  152. X     static char *NoEnvMem = "Remind: Out of memory for environment\n";
  153. X     struct passwd *pwent;
  154. X!    static char *home, *shell, *username;
  155. X  
  156. X     myuid = getuid();
  157. X     if (myuid) {
  158. X--- 424,430 ----
  159. X  
  160. X     static char *NoEnvMem = "Remind: Out of memory for environment\n";
  161. X     struct passwd *pwent;
  162. X!    static char *home, *shell, *username, *logname;
  163. X  
  164. X     myuid = getuid();
  165. X     if (myuid) {
  166. X***************
  167. X*** 441,453 ****
  168. X     putenv(shell);
  169. X  
  170. X     if (pwent->pw_uid) {
  171. X!       username = malloc(strlen(pwent->pw_dir) + 6);
  172. X        if (!username) {
  173. X           fprintf(ErrFp, NoEnvMem);
  174. X           exit(1);
  175. X        }
  176. X!       sprintf(username, "USER=%s", pwent->pw_dir);
  177. X        putenv(username);
  178. X     }
  179. X  }
  180. X  #endif /* UNIX && WANT_U_OPTION */
  181. X--- 466,485 ----
  182. X     putenv(shell);
  183. X  
  184. X     if (pwent->pw_uid) {
  185. X!       username = malloc(strlen(pwent->pw_name) + 6);
  186. X        if (!username) {
  187. X           fprintf(ErrFp, NoEnvMem);
  188. X           exit(1);
  189. X        }
  190. X!       sprintf(username, "USER=%s", pwent->pw_name);
  191. X        putenv(username);
  192. X+       logname= malloc(strlen(pwent->pw_name) + 9);
  193. X+       if (!logname) {
  194. X+          fprintf(ErrFp, NoEnvMem);
  195. X+          exit(1);
  196. X+       }
  197. X+       sprintf(logname, "LOGNAME=%s", pwent->pw_name);
  198. X+       putenv(logname);
  199. X     }
  200. X  }
  201. X  #endif /* UNIX && WANT_U_OPTION */
  202. X*** ../patch3/lang.h    Fri Jan 29 13:39:59 1993
  203. X--- ./lang.h    Mon Feb 15 13:45:00 1993
  204. X***************
  205. X*** 11,18 ****
  206. X  
  207. X  /* I'm chauvinistic and name each language with its English name... */
  208. X  
  209. X! #define ENGLISH    0
  210. X! #define GERMAN     1
  211. X  
  212. X  /* Add more languages here - but please e-mail dfs@doe.carleton.ca
  213. X     to have your favorite language assigned a number.  If you add a
  214. X--- 11,20 ----
  215. X  
  216. X  /* I'm chauvinistic and name each language with its English name... */
  217. X  
  218. X! #define ENGLISH    0 /* original by David Skoll */
  219. X! #define GERMAN     1 /* translated by Wolfgang Thronicke */
  220. X! #define DUTCH      2 /* translated by Willem Kasdorp */
  221. X! #define FINNISH    3 /* translated by Mikko Silvonen */
  222. X  
  223. X  /* Add more languages here - but please e-mail dfs@doe.carleton.ca
  224. X     to have your favorite language assigned a number.  If you add a
  225. X***************
  226. X*** 27,33 ****
  227. X--- 29,37 ----
  228. X   *       Define the language you want to use here                       *
  229. X   *                                                                      *
  230. X   ************************************************************************/
  231. X+ #ifndef LANG  /* Allow for definition on compiler command line */
  232. X  #define LANG ENGLISH
  233. X+ #endif
  234. X  
  235. X  /* If LANG is not defined, it defaults to English. */
  236. X  #ifndef LANG
  237. X***************
  238. X*** 40,45 ****
  239. X--- 44,53 ----
  240. X  #include "english.h"
  241. X  #elif LANG == GERMAN
  242. X  #include "german.h"
  243. X+ #elif LANG == DUTCH
  244. X+ #include "dutch.h"
  245. X+ #elif LANG == FINNISH
  246. X+ #include "finnish.h"
  247. X  
  248. X  /* If no sensible language, choose English.  I intended to use
  249. X     the #error directive here, but some C compilers barf. */
  250. X*** ../patch3/lnk.msc    Wed Dec 16 10:51:54 1992
  251. X--- ./lnk.msc    Thu Mar  4 10:44:28 1993
  252. X***************
  253. X*** 8,13 ****
  254. X--- 8,14 ----
  255. X  init.obj +
  256. X  main.obj +
  257. X  omit.obj +
  258. X+ sort.obj +
  259. X  token.obj +
  260. X  trigger.obj +
  261. X  userfns.obj +
  262. X*** ../patch3/lnk.tc    Wed Dec 16 10:51:54 1992
  263. X--- ./lnk.tc    Thu Mar  4 10:44:16 1993
  264. X***************
  265. X*** 9,14 ****
  266. X--- 9,15 ----
  267. X  init.obj
  268. X  main.obj
  269. X  omit.obj
  270. X+ sort.obj
  271. X  token.obj
  272. X  trigger.obj
  273. X  userfns.obj
  274. X*** ../patch3/main.c    Fri Feb  5 14:55:19 1993
  275. X--- ./main.c    Mon Mar  1 17:34:01 1993
  276. X***************
  277. X*** 112,117 ****
  278. X--- 112,120 ----
  279. X     if (RealToday == JulianToday) SetAccessDate(InitialFile, RealToday);
  280. X  #endif
  281. X  
  282. X+    /* If there are sorted reminders, handle them */
  283. X+    if (SortByDate) IssueSortedReminders();
  284. X+ 
  285. X     /* If there are any background reminders queued up, handle them */
  286. X  #ifdef HAVE_QUEUED
  287. X     if (NumQueued || Daemon) {
  288. X***************
  289. X*** 849,855 ****
  290. X     else {
  291. X        if ( (r=ParseRem(p, &trig, &tim)) ) return r;
  292. X        if (trig.typ != NO_TYPE) return E_PARSE_ERR;
  293. X!       jul = ComputeTrigger(JulianToday, &trig, &r);
  294. X        if (r) syndrome = IF_TRUE | BEFORE_ELSE;
  295. X        else {
  296. X           if (ShouldTriggerReminder(&trig, &tim, jul))
  297. X--- 852,858 ----
  298. X     else {
  299. X        if ( (r=ParseRem(p, &trig, &tim)) ) return r;
  300. X        if (trig.typ != NO_TYPE) return E_PARSE_ERR;
  301. X!       jul = ComputeTrigger(trig.scanfrom, &trig, &r);
  302. X        if (r) syndrome = IF_TRUE | BEFORE_ELSE;
  303. X        else {
  304. X           if (ShouldTriggerReminder(&trig, &tim, jul))
  305. X*** ../patch3/makefile.msc    Wed Dec 16 10:51:53 1992
  306. X--- ./makefile.msc    Thu Mar  4 10:46:02 1993
  307. X***************
  308. X*** 2,8 ****
  309. X  
  310. X  OBJS= calendar.obj dorem.obj dosubst.obj expr.obj files.obj funcs.obj \
  311. X  globals.obj init.obj main.obj omit.obj token.obj trigger.obj userfns.obj \
  312. X! utils.obj var.obj
  313. X  
  314. X  DEFINES= /D__MSDOS__ /D__MSC__
  315. X  
  316. X--- 2,8 ----
  317. X  
  318. X  OBJS= calendar.obj dorem.obj dosubst.obj expr.obj files.obj funcs.obj \
  319. X  globals.obj init.obj main.obj omit.obj token.obj trigger.obj userfns.obj \
  320. X! utils.obj var.obj sort.obj
  321. X  
  322. X  DEFINES= /D__MSDOS__ /D__MSC__
  323. X  
  324. X***************
  325. X*** 19,24 ****
  326. X--- 19,27 ----
  327. X  
  328. X  expr.obj: expr.c
  329. X      cl /c $(DEFINES) $(MODEL) /Foexpr.obj expr.c
  330. X+ 
  331. X+ sort.obj: sort.c
  332. X+     cl /c $(DEFINES) $(MODEL) /Fosort.obj sort.c
  333. X  
  334. X  files.obj: files.c
  335. X      cl /c $(DEFINES) $(MODEL) /Fofiles.obj files.c
  336. X*** ../patch3/makefile.os2    Tue Feb  2 14:36:47 1993
  337. X--- ./makefile.os2    Mon Mar  1 16:55:19 1993
  338. X***************
  339. X*** 25,44 ****
  340. X  # YOU SHOULDN'T EDIT ANYTHING BELOW HERE.  You may want to change some things
  341. X  # in config.h; then, you should be able to type 'make'.
  342. X  #-----------------------------------------------------------------------------
  343. X! VERSION= 03.00.03
  344. X  
  345. X! HDRS= config.h err.h expr.h globals.h protos.h types.h version.h lang.h
  346. X  
  347. X  STDHDRS= config.h types.h protos.h globals.h err.h lang.h
  348. X  
  349. X  SRCS= calendar.c dorem.c dosubst.c expr.c files.c funcs.c globals.c init.c \
  350. X! main.c omit.c token.c trigger.c userfns.c utils.c var.c
  351. X  
  352. X  MANIFEST= README.UNIX README.DOS COPYRIGHT $(HDRS) $(SRCS) Makefile rem rem.1 \
  353. X  remind.1 remind-all.csh remind-all.sh test.rem test-rem test.cmp makefile.tc \
  354. X  makefile.msc lnk.msc lnk.tc MANIFEST.UNX MANIFEST.DOS WHATSNEW.30 kall kall.1 \
  355. X  defs.rem README.OS2 makefile.os2 rem2ps.c rem2ps.h remind.def rem2ps.1 \
  356. X! lang.h english.h german.h tstlang.rem
  357. X  
  358. X  OBJS= $(SRCS:.c=$O)
  359. X  
  360. X--- 25,45 ----
  361. X  # YOU SHOULDN'T EDIT ANYTHING BELOW HERE.  You may want to change some things
  362. X  # in config.h; then, you should be able to type 'make'.
  363. X  #-----------------------------------------------------------------------------
  364. X! VERSION= 03.00.04
  365. X  
  366. X! HDRS= config.h err.h expr.h globals.h protos.h types.h version.h \
  367. X! lang.h english.h german.h dutch.h finish.h
  368. X  
  369. X  STDHDRS= config.h types.h protos.h globals.h err.h lang.h
  370. X  
  371. X  SRCS= calendar.c dorem.c dosubst.c expr.c files.c funcs.c globals.c init.c \
  372. X! main.c omit.c sort.c token.c trigger.c userfns.c utils.c var.c
  373. X  
  374. X  MANIFEST= README.UNIX README.DOS COPYRIGHT $(HDRS) $(SRCS) Makefile rem rem.1 \
  375. X  remind.1 remind-all.csh remind-all.sh test.rem test-rem test.cmp makefile.tc \
  376. X  makefile.msc lnk.msc lnk.tc MANIFEST.UNX MANIFEST.DOS WHATSNEW.30 kall kall.1 \
  377. X  defs.rem README.OS2 makefile.os2 rem2ps.c rem2ps.h remind.def rem2ps.1 \
  378. X! tstlang.rem
  379. X  
  380. X  OBJS= $(SRCS:.c=$O)
  381. X  
  382. X***************
  383. X*** 75,80 ****
  384. X--- 76,82 ----
  385. X  init$O: init.c $(STDHDRS) expr.h version.h
  386. X  main$O: main.c $(STDHDRS) expr.h
  387. X  omit$O: omit.c $(STDHDRS)
  388. X+ sort$O: sort.c $(STDHDRS)
  389. X  token$O: token.c $(STDHDRS)
  390. X  trigger$O: trigger.c $(STDHDRS) expr.h
  391. X  userfns$O: userfns.c $(STDHDRS) expr.h
  392. X*** ../patch3/makefile.tc    Tue Feb  2 14:36:38 1993
  393. X--- ./makefile.tc    Mon Mar  1 16:55:05 1993
  394. X***************
  395. X*** 1,23 ****
  396. X  # Makefile for REMIND for Turbo C for MSDOS
  397. X  
  398. X! VERSION= 03.00.03
  399. X  
  400. X! HDRS= config.h err.h expr.h globals.h protos.h types.h version.h lang.h
  401. X  
  402. X  STDHDRS= config.h types.h protos.h globals.h err.h lang.h
  403. X  
  404. X  SRCS= calendar.c dorem.c dosubst.c expr.c files.c funcs.c globals.c init.c \
  405. X! main.c omit.c token.c trigger.c userfns.c utils.c var.c
  406. X  
  407. X  OBJS=calendar.obj dorem.obj dosubst.obj expr.obj files.obj funcs.obj \
  408. X! globals.obj init.obj main.obj omit.obj token.obj trigger.obj \
  409. X  utils.obj userfns.obj var.obj
  410. X  
  411. X  MANIFEST= readme.uni readme.dos copyrigh $(HDRS) $(SRCS) makefile rem rem.1 \
  412. X  remind.1 remind-a.csh remind-a.sh test.rem test-rem test.cmp makefile.tc \
  413. X  makefile.msc lnk.msc lnk.tc manifest.dos manifest.unx whatsnew.30 kall kall.1 \
  414. X! defs.rem readme.os2 makefile.os2 rem2ps.c rem2ps.h remind.def rem2ps.1 \
  415. X! lang.h english.h german.h tstlang.rem
  416. X  
  417. X  all: remind.exe rem2ps.exe
  418. X  
  419. X--- 1,24 ----
  420. X  # Makefile for REMIND for Turbo C for MSDOS
  421. X  
  422. X! VERSION= 03.00.04
  423. X  
  424. X! HDRS= config.h err.h expr.h globals.h protos.h types.h version.h \
  425. X! lang.h english.h german.h dutch.h finnish.h
  426. X  
  427. X  STDHDRS= config.h types.h protos.h globals.h err.h lang.h
  428. X  
  429. X  SRCS= calendar.c dorem.c dosubst.c expr.c files.c funcs.c globals.c init.c \
  430. X! main.c omit.c sort.c token.c trigger.c userfns.c utils.c var.c
  431. X  
  432. X  OBJS=calendar.obj dorem.obj dosubst.obj expr.obj files.obj funcs.obj \
  433. X! globals.obj init.obj main.obj omit.obj sort.obj token.obj trigger.obj \
  434. X  utils.obj userfns.obj var.obj
  435. X  
  436. X  MANIFEST= readme.uni readme.dos copyrigh $(HDRS) $(SRCS) makefile rem rem.1 \
  437. X  remind.1 remind-a.csh remind-a.sh test.rem test-rem test.cmp makefile.tc \
  438. X  makefile.msc lnk.msc lnk.tc manifest.dos manifest.unx whatsnew.30 kall kall.1 \
  439. X! tstlang.rem defs.rem readme.os2 makefile.os2 rem2ps.c rem2ps.h remind.def \
  440. X! rem2ps.1
  441. X  
  442. X  all: remind.exe rem2ps.exe
  443. X  
  444. X***************
  445. X*** 51,56 ****
  446. X--- 52,59 ----
  447. X  main.obj: main.c $(STDHDRS) expr.h
  448. X  
  449. X  omit.obj: omit.c $(STDHDRS)
  450. X+ 
  451. X+ sort.obj: sort.c $(STDHDRS)
  452. X  
  453. X  token.obj: token.c $(STDHDRS)
  454. X  
  455. X*** ../patch3/omit.c    Fri Feb  5 14:56:03 1993
  456. X--- ./omit.c    Mon Mar  1 12:59:56 1993
  457. X***************
  458. X*** 33,40 ****
  459. X  static int NumFullOmits, NumPartialOmits;
  460. X  
  461. X  /* The structure for saving and restoring OMIT contexts */
  462. X! typedef struct _omitcontext {
  463. X!    struct _omitcontext *next;
  464. X     int numfull, numpart;
  465. X     int *fullsave;
  466. X     int *partsave;
  467. X--- 33,40 ----
  468. X  static int NumFullOmits, NumPartialOmits;
  469. X  
  470. X  /* The structure for saving and restoring OMIT contexts */
  471. X! typedef struct omitcontext {
  472. X!    struct omitcontext *next;
  473. X     int numfull, numpart;
  474. X     int *fullsave;
  475. X     int *partsave;
  476. X*** ../patch3/protos.h    Fri Jan  8 13:24:46 1993
  477. X--- ./protos.h    Tue Mar  2 16:20:16 1993
  478. X***************
  479. X*** 33,38 ****
  480. X--- 33,39 ----
  481. X  int TriggerReminder ARGS ((ParsePtr p, Trigger *t, TimeTrig *tim, int jul));
  482. X  int ShouldTriggerReminder ARGS ((Trigger *t, TimeTrig *tim, int jul));
  483. X  int DoSubst ARGS ((ParsePtr p, char *out, Trigger *t, TimeTrig *tt, int jul, int mode));
  484. X+ int DoSubstFromString ARGS ((char *source, char *dest, int jul, int tim));
  485. X  int EvalExpr ARGS ((char **e, Value *v));
  486. X  int PushValStack ARGS ((Value *val));
  487. X  int PopValStack ARGS ((Value *val));
  488. X***************
  489. X*** 111,113 ****
  490. X--- 112,119 ----
  491. X  int DoSatRemind ARGS ((Trigger *trig, TimeTrig *tim, ParsePtr p));
  492. X  int ParseNonSpaceChar ARGS ((ParsePtr p, int *err, int peek));
  493. X  int HashVal ARGS ((const char *str));
  494. X+ int DateOK ARGS ((int y, int m, int d));
  495. X+ Operator *FindFunc ARGS ((char *name, Operator where[], int num));
  496. X+ int InsertIntoSortBuffer ARGS ((int jul, int tim, char *body, int typ));
  497. X+ void IssueSortedReminders ARGS ((void));    
  498. X+ int UserFuncExists ARGS ((char *fn));
  499. X*** ../patch3/queue.c    Fri Jan  8 13:24:41 1993
  500. X--- ./queue.c    Mon Mar  1 12:58:47 1993
  501. X***************
  502. X*** 28,35 ****
  503. X  #include "protos.h"
  504. X  
  505. X  /* List structure for holding queued reminders */
  506. X! typedef struct _queuedrem {
  507. X!    struct _queuedrem *next;
  508. X     int typ;
  509. X     int RunDisabled;
  510. X     char *text;
  511. X--- 28,35 ----
  512. X  #include "protos.h"
  513. X  
  514. X  /* List structure for holding queued reminders */
  515. X! typedef struct queuedrem {
  516. X!    struct queuedrem *next;
  517. X     int typ;
  518. X     int RunDisabled;
  519. X     char *text;
  520. X***************
  521. X*** 270,278 ****
  522. X     printf("Contents of AT queue:%s", NL);
  523. X  
  524. X     while (q) {
  525. X!       printf("Trigger: %02d:%02d  Activate: %02d:%02d  Rep: %d  Delta: %d%s",
  526. X!               q->tt.ttime / 60, q->tt.ttime % 60,
  527. X!           q->tt.nexttime / 60, q->tt.nexttime % 60,
  528. X                q->tt.rep, q->tt.delta, NL);
  529. X        printf("Text: %s %s%s%s", ((q->typ == MSG_TYPE) ? "MSG" : "RUN"),
  530. X                q->text,
  531. X--- 270,278 ----
  532. X     printf("Contents of AT queue:%s", NL);
  533. X  
  534. X     while (q) {
  535. X!       printf("Trigger: %02d%c%02d  Activate: %02d%c%02d  Rep: %d  Delta: %d%s",
  536. X!               q->tt.ttime / 60, TIMESEP, q->tt.ttime % 60,
  537. X!           q->tt.nexttime / 60, TIMESEP, q->tt.nexttime % 60,
  538. X                q->tt.rep, q->tt.delta, NL);
  539. X        printf("Text: %s %s%s%s", ((q->typ == MSG_TYPE) ? "MSG" : "RUN"),
  540. X                q->text,
  541. X*** ../patch3/rem2ps.1    Fri Jan 29 13:37:01 1993
  542. X--- ./rem2ps.1    Mon Feb 15 18:45:11 1993
  543. X***************
  544. X*** 24,32 ****
  545. X  not use this option, the default encoding is used.
  546. X  .TP
  547. X  .B \-m media
  548. X! Set the page size.  You must specify the media type, which can be one of the
  549. X! following.  (Sizes are approximate.  For a list of media types, type
  550. X! "rem2ps -m help".)
  551. X  .RS
  552. X  .TP
  553. X  Letter
  554. X--- 24,32 ----
  555. X  not use this option, the default encoding is used.
  556. X  .TP
  557. X  .B \-m media
  558. X! Set the page size.  If you use the \-m option, you must specify the
  559. X! media type, which can be one of the
  560. X! following.  (Sizes are approximate.)
  561. X  .RS
  562. X  .TP
  563. X  Letter
  564. X***************
  565. X*** 69,75 ****
  566. X  10 x 14 in.
  567. X  .PP
  568. X  Type "rem2ps -m help" for a list of available media.  Note that the media
  569. X! type (and all \fBRem2ps\fR options) are case-sensitive.
  570. X  .RE
  571. X  .TP
  572. X  \fB\-f\fR[\fBshed\fR] \fIfont\fR
  573. X--- 69,76 ----
  574. X  10 x 14 in.
  575. X  .PP
  576. X  Type "rem2ps -m help" for a list of available media.  Note that the media
  577. X! type (and all \fBRem2ps\fR options) are case-sensitive.  If you don't use
  578. X! the \fB\-m\fR option, the media defaults to Letter.
  579. X  .RE
  580. X  .TP
  581. X  \fB\-f\fR[\fBshed\fR] \fIfont\fR
  582. X*** ../patch3/rem2ps.c    Mon Feb  8 14:31:59 1993
  583. X--- ./rem2ps.c    Mon Mar  1 12:59:48 1993
  584. X***************
  585. X*** 31,38 ****
  586. X  #endif
  587. X  #define NEW(type) ((type *) malloc(sizeof(type)))
  588. X  
  589. X! typedef struct _CalEntry {
  590. X!    struct _CalEntry *next;
  591. X     char *entry;
  592. X  } CalEntry;
  593. X  
  594. X--- 31,38 ----
  595. X  #endif
  596. X  #define NEW(type) ((type *) malloc(sizeof(type)))
  597. X  
  598. X! typedef struct calentry {
  599. X!    struct calentry *next;
  600. X     char *entry;
  601. X  } CalEntry;
  602. X  
  603. X*** ../patch3/remind.1    Tue Feb  2 14:36:32 1993
  604. X--- ./remind.1    Fri Mar  5 11:51:37 1993
  605. X***************
  606. X*** 37,42 ****
  607. X--- 37,43 ----
  608. X  empty boxes smaller.  \fISpc\fR specifies how many blank lines to leave
  609. X  between the day number and the first reminder entry.  It defaults to 1.
  610. X  .RS
  611. X+ .PP
  612. X  Any of \fIcol\fR, \fIpad\fR or \fIspc\fR can be omitted, providing you
  613. X  provide the correct number of commas.  Don't use any spaces in the option.
  614. X  .RE
  615. X***************
  616. X*** 106,111 ****
  617. X--- 107,120 ----
  618. X  Echo lines when displaying error messages
  619. X  .RE
  620. X  .TP
  621. X+ \fB\-g\fR[\fBa|d\fR[\fBa|d\fR]]
  622. X+ Normally, reminders are issued in the order in which they are encountered
  623. X+ in the reminder script.  The \fB\-g\fR option cause \fBRemind\fR to
  624. X+ sort reminders by date and time prior to issuing them.  The optional
  625. X+ \fBa\fR and \fBd\fR characters specify the sort order (ascending or
  626. X+ descending) for the date and time fields.  See the section "Sorting
  627. X+ Reminders" for more information.
  628. X+ .TP
  629. X  \fB\-b\fR[\fIn\fR]
  630. X  Set the time format for the calendar and simple-calendar outputs.  \fIN\fR
  631. X  can range from 0 to 2, with the default 0.  A value of 0 causes times
  632. X***************
  633. X*** 117,122 ****
  634. X--- 126,165 ----
  635. X  Sets the iteration limit for the \fBSATISFY\fR clause of a \fBREM\fR
  636. X  command.  Defaults to 150.
  637. X  .TP
  638. X+ \fB\-k\fR\fIcmd\fR
  639. X+ Instead of simply printing \fBMSG\fR-type reminders, this causes them to be
  640. X+ passed to the specific \fIcmd\fR.  You must use '%s' where you want the body to
  641. X+ appear, and may need to enclose this option in quotes.  Also, because
  642. X+ \fIcmd\fR is run using the \fBsystem()\fR library function, shell quotes in
  643. X+ the body of the message may cause problems.  Note that this option
  644. X+ \fBoverrides\fR the \fB\-r\fR option and the \fBRUN OFF\fR command.
  645. X+ .PP
  646. X+ .RS
  647. X+ As an example, suppose you have an X-Windows program called xmessage, which
  648. X+ pops up a window and displays its invocation arguments.  You could use:
  649. X+ .PP
  650. X+ .nf
  651. X+         remind '-kxmessage %s &' ...
  652. X+ .fi
  653. X+ .PP
  654. X+ to have all of your \fBMSG\fR-type reminders processed using xmessage.
  655. X+ .PP
  656. X+ A word of warning:  It is very easy to spawn dozens of xmessage processes
  657. X+ with the above technique.  So be very careful.  Also, the \fIcmd\fR is passed
  658. X+ as an argument to \fBsprintf()\fR.  If you use formatting directives other
  659. X+ than %s, or use more than one %s directive, there's a good chance that
  660. X+ you'll crash \fBRemind\fR.  Finally, because \fIcmd\fR is executed using
  661. X+ the \fBsystem()\fR library function, shell delimiters in \fBMSG\fR-type
  662. X+ reminders could cause problems.  \fIIn particular, never run untrusted
  663. X+ reminders using the \fR\fB\-k\fR\fI option\fR.  A reminder like:
  664. X+ .PP
  665. X+ .nf
  666. X+     REM msg foo ; rm -Rf .
  667. X+ .fi
  668. X+ .PP
  669. X+ would cause havoc if run with the \fB\-k\fR option.
  670. X+ .RE
  671. X+ .TP
  672. X  \fB\-z\fR[\fIn\fR]
  673. X  Runs \fBRemind\fR in the daemon mode.  If \fIn\fR is supplied, it
  674. X  specifies how often (in minutes) \fBRemind\fR should wake up to
  675. X***************
  676. X*** 129,135 ****
  677. X  The \fB\-u\fR option is available only to root, and cannot be used by normal
  678. X  users.  The option changes the uid and gid as described, and sets the
  679. X  environment variables HOME, SHELL and USER to the home directory, shell,
  680. X! and user name, respectively, of the specified user.  This option is meant for
  681. X  use in shell scripts which mail reminders to all users.
  682. X  .PP
  683. X  If you supply a \fIdate\fR on the command line, it must consist of
  684. X--- 172,179 ----
  685. X  The \fB\-u\fR option is available only to root, and cannot be used by normal
  686. X  users.  The option changes the uid and gid as described, and sets the
  687. X  environment variables HOME, SHELL and USER to the home directory, shell,
  688. X! and user name, respectively, of the specified user.  LOGNAME is also
  689. X! set to the specified user name.  This option is meant for
  690. X  use in shell scripts which mail reminders to all users.
  691. X  .PP
  692. X  If you supply a \fIdate\fR on the command line, it must consist of
  693. X***************
  694. X*** 188,193 ****
  695. X--- 232,238 ----
  696. X  [\fBOMIT\fR \fIomit_list\fR]
  697. X  [\fBAT\fR \fItime\fR [\fItdelta\fR] [\fItrepeat\fR]]
  698. X  [\fBUNTIL\fR \fIexpiry_date\fR]
  699. X+ [\fBSCANFROM\fR \fIscan_date\fR]
  700. X  \fBMSG\fR | \fBRUN\fR | \fBCAL\fR | \fBSATISFY\fR
  701. X  .I body
  702. X  .RE
  703. X***************
  704. X*** 206,214 ****
  705. X  .PP
  706. X  The keywords \fBMSG\fR, \fBRUN\fR and \fBCAL\fR denote the \fItype\fR
  707. X  of the reminder.  (\fBSATISFY\fR is more complicated and will be explained
  708. X! later.)  A \fBMSG\fR type reminder simply prints a message to the standard
  709. X  output, after passing the \fIbody\fR through a special substitution filter,
  710. X! described in the section "The Substitution Filter."  A \fBRUN\fR-type
  711. X  reminder also passes the \fIbody\fR through the substitution filter, but
  712. X  then executes the result as a system command.  A \fBCAL\fR-type reminder
  713. X  is used only to place entries in the calendar produced when \fBRemind\fR
  714. X--- 251,264 ----
  715. X  .PP
  716. X  The keywords \fBMSG\fR, \fBRUN\fR and \fBCAL\fR denote the \fItype\fR
  717. X  of the reminder.  (\fBSATISFY\fR is more complicated and will be explained
  718. X! later.)  A \fBMSG\fR-type reminder normally prints a message to the standard
  719. X  output, after passing the \fIbody\fR through a special substitution filter,
  720. X! described in the section "The Substitution Filter."  However, if you have
  721. X! used the \fB\-k\fR command-line option, then \fBMSG\fR-type reminders are
  722. X! passed to the appropriate program.  Note that the options \fB\-c\fR,
  723. X! \fB\-s\fR, \fB\-p\fR and \fB\-n\fR disable the \fB\-k\fR option.
  724. X! .PP
  725. X! A \fBRUN\fR-type
  726. X  reminder also passes the \fIbody\fR through the substitution filter, but
  727. X  then executes the result as a system command.  A \fBCAL\fR-type reminder
  728. X  is used only to place entries in the calendar produced when \fBRemind\fR
  729. X***************
  730. X*** 491,496 ****
  731. X--- 541,553 ----
  732. X  period.  Similarly, if you specify a weekday, it is used only to calculate
  733. X  the initial date, and does not affect the repetition period.
  734. X  .PP
  735. X+ .B SCANFROM
  736. X+ .PP
  737. X+ The \fBSCANFROM\fR keyword is for advanced \fBRemind\fR programmers
  738. X+ only, and will be explained in the section "Details about Trigger Computation"
  739. X+ near the end of this manual.  Note that \fBSCANFROM\fR is available only
  740. X+ in versions of \fBRemind\fR from 03.00.04 up.
  741. X+ .PP
  742. X  .B EXPIRY DATES
  743. X  .PP
  744. X  Some reminders should be issued periodically for a certain time, but then
  745. X***************
  746. X*** 578,583 ****
  747. X--- 635,642 ----
  748. X  by a \fItime\fR and optional \fItdelta\fR and \fItrepeat\fR.  The \fItime\fR
  749. X  must be specified in 24-hour format, with 0:00 representing midnight,
  750. X  12:00 representing noon, and 23:59 representing one minute to midnight.
  751. X+ You can use either a colon or a period to separate the hours from the
  752. X+ minutes.  That is, 13:39 and 13.39 are equivalent.
  753. X  .PP
  754. X  \fBRemind\fR treats timed reminders specially.  If the trigger date
  755. X  for a timed reminder is the same as the current system date, the
  756. X***************
  757. X*** 1043,1049 ****
  758. X  .PP
  759. X  If you run \fBRemind\fR with the \fB\-r\fR command-line option,
  760. X  \fBRUN\fR-type reminders and the \fBshell()\fR function will be disabled,
  761. X! regardless of any \fBRUN\fR commands in the reminder script.
  762. X  .PP
  763. X  One use of the \fBRUN\fR command is to provide a secure interface
  764. X  between \fBRemind\fR and the \fBElm\fR mail system.  The \fBElm\fR
  765. X--- 1102,1109 ----
  766. X  .PP
  767. X  If you run \fBRemind\fR with the \fB\-r\fR command-line option,
  768. X  \fBRUN\fR-type reminders and the \fBshell()\fR function will be disabled,
  769. X! regardless of any \fBRUN\fR commands in the reminder script.  However,
  770. X! any command supplied with the \fB\-k\fR option will still be executed.
  771. X  .PP
  772. X  One use of the \fBRUN\fR command is to provide a secure interface
  773. X  between \fBRemind\fR and the \fBElm\fR mail system.  The \fBElm\fR
  774. X***************
  775. X*** 1071,1076 ****
  776. X--- 1131,1139 ----
  777. X      Reminders for Friday, 30th October, 1992 (today):
  778. X  .fi
  779. X  .PP
  780. X+ (The banner is not printed if any of the calendar-producing options
  781. X+ is used, or if the \fB\-k\fR option is used.)
  782. X+ .PP
  783. X  The \fBBANNER\fR command lets you change the format.  It should appear
  784. X  before any \fBREM\fR commands.  The format is:
  785. X  .PP
  786. X***************
  787. X*** 1166,1175 ****
  788. X  .RE
  789. X  .TP
  790. X  .B TIME constants
  791. X! 12:33, 0:01, 14:15, 16:42
  792. X  .PP
  793. X  .RS
  794. X! Note that \fBTIME\fR constants are written in 24-hour format
  795. X  .RE
  796. X  .TP
  797. X  .B DATE constants
  798. X--- 1229,1241 ----
  799. X  .RE
  800. X  .TP
  801. X  .B TIME constants
  802. X! 12:33, 0:01, 14:15, 16:42, 12.16, 13.00, 1.11
  803. X  .PP
  804. X  .RS
  805. X! Note that \fBTIME\fR constants are written in 24-hour format.  Either the
  806. X! period or colon can be used to separate the minutes from the hours.
  807. X! However, Remind will consistently output times using only one separator
  808. X! character.  (The output separator character is chosen at compile-time.)
  809. X  .RE
  810. X  .TP
  811. X  .B DATE constants
  812. X***************
  813. X*** 1389,1394 ****
  814. X--- 1455,1468 ----
  815. X  function returns 0 if the file can be accessed with the specified \fImode\fR,
  816. X  and -1 otherwise.
  817. X  .TP
  818. X+ .B args(s_fname)
  819. X+ Returns the number of arguments expected by the user-defined function
  820. X+ \fIfname\fR, or -1 if no such user-defined function exists.  Note that
  821. X+ this function examines only user-defined functions, not built-in functions.
  822. X+ Its main use is to determine whether or not a particular user-defined
  823. X+ function has been defined previously.  The \fBargs()\fR function is
  824. X+ available only in versions of \fBRemind\fR from 03.00.04 and up.
  825. X+ .TP
  826. X  .B asc(s_string)
  827. X  Returns an \fBINT\fR which is the ASCII code of the first character
  828. X  in \fIstring\fR.  As a special case, \fBasc("")\fR returns 0.
  829. X***************
  830. X*** 1491,1496 ****
  831. X--- 1565,1587 ----
  832. X  error if it is undefined or not of type \fBSTRING\fR.
  833. X  .RE
  834. X  .TP
  835. X+ .B dosubst(s_str [,d_date [,t_time]])
  836. X+ Returns a \fBSTRING\fR which is the result of passing \fIstr\fR through
  837. X+ the substitution filter described earlier.  The parameters \fIdate\fR
  838. X+ and \fItime\fR establish the effective trigger date and time used by the
  839. X+ substitution filter.  If \fIdate\fR and \fItime\fR are omitted, they
  840. X+ default to \fBtoday()\fR and \fBnow()\fR.
  841. X+ .RS
  842. X+ .PP
  843. X+ Note that if \fIstr\fR does not end with "%", a newline character will be
  844. X+ added to the end of the result.  Also, calling \fBdosubst()\fR with a
  845. X+ \fIdate\fR which is in the past (i.e., if \fIdate\fR < \fBtoday()\fR)
  846. X+ will produce undefined results.
  847. X+ .PP
  848. X+ \fBDosubst()\fR is only available starting from version 03.00.04 of
  849. X+ \fBRemind\fR.
  850. X+ .RE
  851. X+ .TP
  852. X  .B filename()
  853. X  Returns (as a \fBSTRING\fR) the name of the current file being processed
  854. X  by \fBRemind\fR.  Inside included files, returns the name of the
  855. X***************
  856. X*** 1516,1521 ****
  857. X--- 1607,1613 ----
  858. X  string \fIsearch\fR.  The first character of a string is numbered 1.
  859. X  If \fItarget\fR does not exist in \fIsearch\fR, then 0 is returned.
  860. X  .RS
  861. X+ .PP
  862. X  The optional parameter \fIstart\fR specifies the position in
  863. X  \fIsearch\fR at which to start looking for \fItarget\fR.
  864. X  .RE
  865. X***************
  866. X*** 1579,1584 ****
  867. X--- 1671,1677 ----
  868. X  Can take from one to three arguments.  If one argument is supplied, returns
  869. X  "s" if \fInum\fR is not 1, and "" if \fInum\fR is 1.
  870. X  .RS
  871. X+ .PP
  872. X  If two arguments are supplied, returns \fIstr1\fR + "s" if \fInum\fR is
  873. X  not 1.  Otherwise, returns \fIstr1\fR.
  874. X  .PP
  875. X***************
  876. X*** 1622,1628 ****
  877. X  calendar entry currently being computed.
  878. X  .TP
  879. X  .B trigdate()
  880. X! Returns the calculated trigger date of the last \fBREM\fR command.  If used
  881. X  in the \fIbody\fR of a \fBREM\fR command, returns that command's trigger date.
  882. X  .TP
  883. X  .B trigger(d_date)
  884. X--- 1715,1722 ----
  885. X  calendar entry currently being computed.
  886. X  .TP
  887. X  .B trigdate()
  888. X! Returns the calculated trigger date of the last \fBREM\fR
  889. X! or \fBIFTRIG\fR command.  If used
  890. X  in the \fIbody\fR of a \fBREM\fR command, returns that command's trigger date.
  891. X  .TP
  892. X  .B trigger(d_date)
  893. X***************
  894. X*** 1656,1661 ****
  895. X--- 1750,1756 ----
  896. X  returns the value of variable XY, if it is defined.  If XY is not defined,
  897. X  an error results.
  898. X  .RS
  899. X+ .PP
  900. X  However, if you supply a second argument, it is returned if the \fIvarname\fR
  901. X  is not defined.  The expression value("XY", 0) will return 0 if XY is not
  902. X  defined, and the value of XY if it is defined.
  903. X***************
  904. X*** 1663,1669 ****
  905. X  .TP
  906. X  .B version()
  907. X  Returns a string specifying the version of \fBRemind\fR.  For version 
  908. X! 03.00.03, returns "03.00.03".  It is guaranteed that as new versions of
  909. X  \fBRemind\fR are released, the value returned by \fBversion()\fR will
  910. X  strictly increase, according to the rules for string ordering.
  911. X  .TP
  912. X--- 1758,1764 ----
  913. X  .TP
  914. X  .B version()
  915. X  Returns a string specifying the version of \fBRemind\fR.  For version 
  916. X! 03.00.04, returns "03.00.04".  It is guaranteed that as new versions of
  917. X  \fBRemind\fR are released, the value returned by \fBversion()\fR will
  918. X  strictly increase, according to the rules for string ordering.
  919. X  .TP
  920. X***************
  921. X*** 1725,1730 ****
  922. X--- 1820,1826 ----
  923. X          ["SET"] a 1
  924. X  .fi
  925. X  .RS
  926. X+ .PP
  927. X  This restriction is because \fBRemind\fR must be able to unambiguously
  928. X  determine the first token of a line for the flow-control commands (to
  929. X  be discussed later.)
  930. X***************
  931. X*** 1886,1891 ****
  932. X--- 1982,1988 ----
  933. X  The \fBvalue()\fR function \fIalways\fR accesses the "global" value of a
  934. X  variable, even if it has the same name as an argument.  For example:
  935. X  .RS
  936. X+ .PP
  937. X  .nf
  938. X          fset func(x) value("x")
  939. X          set x 1
  940. X***************
  941. X*** 1992,1999 ****
  942. X  for September, 1992.  Labour Day was on Monday, 7 September, 1992.
  943. X  However, when \fBRemind\fR gets around to calculating the trigger
  944. X  for Tuesday, 8 September, 1992, the \fBOMIT\fR command will now be
  945. X! ommitting Labour Day for 1993, and the "Mon AFTER" command
  946. X! will not be triggered.
  947. X  .PP
  948. X  It is probably best to stay away from computing \fBOMIT\fR
  949. X  trigger dates unless you keep these pitfalls in mind.
  950. X--- 2089,2097 ----
  951. X  for September, 1992.  Labour Day was on Monday, 7 September, 1992.
  952. X  However, when \fBRemind\fR gets around to calculating the trigger
  953. X  for Tuesday, 8 September, 1992, the \fBOMIT\fR command will now be
  954. X! omitting Labour Day for 1993, and the "Mon AFTER" command
  955. X! will not be triggered.  (But see the description of \fBSCANFROM\fR
  956. X! in the section "Details about Trigger Computation.")
  957. X  .PP
  958. X  It is probably best to stay away from computing \fBOMIT\fR
  959. X  trigger dates unless you keep these pitfalls in mind.
  960. X***************
  961. X*** 2178,2183 ****
  962. X--- 2276,2355 ----
  963. X  If you use \fBsh\fR or \fBbash\fR, you may have to use the "nohup" command
  964. X  to ensure that the daemon is not killed when you log out.
  965. X  .PP
  966. X+ .SH SORTING REMINDERS
  967. X+ .PP
  968. X+ The \fB\-g\fR option causes \fBRemind\fR to sort reminders by
  969. X+ trigger date and time before issuing them.  Note that reminders are
  970. X+ still calculated in the order encountered in the script.  However, rather
  971. X+ than being issued immediately, they are saved in an internal buffer.
  972. X+ When \fBRemind\fR has finished processing the script, it issues the
  973. X+ saved reminders in sorted order.  The \fB\-g\fR option can be followed
  974. X+ by one or two characters, which must be "a" or "d".  The first character
  975. X+ specifies the sort order by trigger date (ascending or descending) and
  976. X+ the second specifies the sort order by trigger time.  The default is
  977. X+ to sort both fields in ascending order.
  978. X+ .PP
  979. X+ In ascending order, reminders are issued with the most imminent first.
  980. X+ Descending order is the reverse.  Reminders are always sorted by
  981. X+ trigger date, and reminders with the same trigger date are then sorted
  982. X+ by trigger time.  Non-timed reminders are always issued after timed
  983. X+ reminders in this mode.
  984. X+ .PP
  985. X+ You can define a user-defined function called SORTBANNER which takes one
  986. X+ \fBDATE\fR-type argument.  In sort mode, the following sequence happens:
  987. X+ .PP
  988. X+ If \fBRemind\fR notices that the next reminder to issue has a different
  989. X+ trigger date from the previous one (or if it is the first one to be
  990. X+ issued), then SORTBANNER is called with the trigger date as its argument.
  991. X+ The result is coerced to a string, and passed through the substitution
  992. X+ filter with the appropriate trigger date.  The result is then displayed.
  993. X+ .PP
  994. X+ Here's an example - consider the following fragment:
  995. X+ .PP
  996. X+ .nf
  997. X+     # Switch off the normal banner
  998. X+     BANNER %
  999. X+     REM 11 March 1993 ++1 MSG Not so important
  1000. X+     REM 17 March 1993 ++7 MSG Way in the future
  1001. X+     REM 10 March 1993 MSG Important Reminder
  1002. X+     REM 11 March 1993 ++1 MSG Not so important - B
  1003. X+     FSET sortbanner(x) iif(x == today(), \\
  1004. X+         "***** THINGS TO DO TODAY *****", \\
  1005. X+         "----- Things to do %b -----")
  1006. X+ .fi
  1007. X+ .PP
  1008. X+ Running this with the \fB-gaa\fR option on 10 March 1993
  1009. X+ produces the following output:
  1010. X+ .PP
  1011. X+ .nf
  1012. X+     ***** THINGS TO DO TODAY *****
  1013. X+ 
  1014. X+     Important Reminder
  1015. X+ 
  1016. X+     ----- Things to do tomorrow -----
  1017. X+ 
  1018. X+     Not so important
  1019. X+ 
  1020. X+     Not so important - B
  1021. X+ 
  1022. X+     ----- Things to do in 7 days' time -----
  1023. X+ 
  1024. X+     Way in the future
  1025. X+ .fi
  1026. X+ .PP
  1027. X+ You can use the \fBargs()\fR built-in function to determine whether or
  1028. X+ not SORTBANNER has been defined.  (This could be used, for example, to
  1029. X+ provide a default definition for SORTBANNER in a system-wide file included
  1030. X+ at the end of the user's file.)  Here's an example:
  1031. X+ .PP
  1032. X+ .nd
  1033. X+     # Create a default sortbanner function if it hasn't already
  1034. X+     # been defined
  1035. X+     if args("sortbanner") != 1
  1036. X+         fset sortbanner(x) "--- Things to do %b ---"
  1037. X+     endif
  1038. X+ .fi
  1039. X+ .PP
  1040. X  .SH FOREIGN LANGUAGE SUPPORT
  1041. X  .PP
  1042. X  Your version of \fBRemind\fR may have been compiled to support a
  1043. X***************
  1044. X*** 2197,2203 ****
  1045. X  .PP
  1046. X  .B COMMAND ABBREVIATIONS
  1047. X  .PP
  1048. X! The following commands can be abbreviated:
  1049. X  .TP
  1050. X  o
  1051. X  \fBREM\fR can be omitted - it is implied if no other valid command
  1052. X--- 2369,2375 ----
  1053. X  .PP
  1054. X  .B COMMAND ABBREVIATIONS
  1055. X  .PP
  1056. X! The following tokens can be abbreviated:
  1057. X  .TP
  1058. X  o
  1059. X  \fBREM\fR can be omitted - it is implied if no other valid command
  1060. X***************
  1061. X*** 2220,2225 ****
  1062. X--- 2392,2400 ----
  1063. X  .TP
  1064. X  o
  1065. X  \fBINCLUDE\fR --> \fBINC\fR
  1066. X+ .TP
  1067. X+ o
  1068. X+ \fBSCANFROM\fR --> \fBSCAN\fR
  1069. X  .PP
  1070. X  .B NIFTY EXAMPLES
  1071. X  .PP
  1072. X***************
  1073. X*** 2283,2293 ****
  1074. X  multiples of 4.  The second \fBREM\fR command actually issues the
  1075. X  reminder.
  1076. X  .PP
  1077. X  .B DETAILS ABOUT TRIGVALID()
  1078. X  .PP
  1079. X  The \fBtrigvalid()\fR function returns 1 if \fBRemind\fR could find a trigger
  1080. X  date for the previous \fBREM\fR or \fBIFTRIG\fR command.  More specifically,
  1081. X! it returns 1 if \fBRemind\fR finds a date \fInot in the past\fR which
  1082. X  satisfies the trigger.  In addition, there is one special case in which
  1083. X  \fBtrigvalid()\fR returns 1 and \fBtrigdate()\fR returns a meaningful result:
  1084. X  .PP
  1085. X--- 2458,2532 ----
  1086. X  multiples of 4.  The second \fBREM\fR command actually issues the
  1087. X  reminder.
  1088. X  .PP
  1089. X+ .B DETAILS ABOUT TRIGGER COMPUTATION
  1090. X+ .PP
  1091. X+ Here is a \fIconceptual\fR description of how triggers are calculated.
  1092. X+ Note that \fBRemind\fR actually uses a much more efficient procedure,
  1093. X+ but the results are the same as if the conceptual procedure had been
  1094. X+ followed.
  1095. X+ .PP
  1096. X+ \fBRemind\fR starts from the current date (that is, the value of
  1097. X+ \fBtoday()\fR) and scans forward, examining each day one at a time
  1098. X+ until it finds a date which satisfies the trigger, or can prove that
  1099. X+ no such dates (on or later than \fBtoday()\fR) exist.
  1100. X+ .PP
  1101. X+ If \fBRemind\fR is executing a \fBSATISFY\fR-type reminder, it evaluates
  1102. X+ the expression with \fBtrigdate()\fR set to the date found above.  If
  1103. X+ the expression evaluates to zero or the null string, \fBRemind\fR continues
  1104. X+ the scanning procedure described above, starting with the day after the
  1105. X+ trigger found above.
  1106. X+ .PP
  1107. X+ The \fBSCANFROM\fR clause (having a syntax similar to \fBUNTIL\fR)
  1108. X+ can modify the search strategy used.  In this case, \fBRemind\fR begins the
  1109. X+ scanning procedure at \fIscan_date\fR, which is the date specified in
  1110. X+ the \fBSCANFROM\fR clause.  For example:
  1111. X+ .PP
  1112. X+ .nf
  1113. X+     REM Mon 1 SCANFROM 17 Jan 1992 MSG Foo
  1114. X+ .fi
  1115. X+ .PP
  1116. X+ The example above will always have a trigger date of Monday, 3 February 1992.
  1117. X+ That is because \fBRemind\fR starts scanning from 17 January 1992, and
  1118. X+ stops scanning as soon as it hits a date which satisfies "Mon 1."
  1119. X+ .PP
  1120. X+ The main use of \fBSCANFROM\fR is in situations where you want to
  1121. X+ calculate the positions of floating holidays.  Consider the Labour
  1122. X+ Day example shown much earlier.  Labour Day is the first Monday
  1123. X+ in September.  It can move over a range of 7 days.  Consider the
  1124. X+ following sequence:
  1125. X+ .PP
  1126. X+ .nf
  1127. X+     REM Mon 1 Sept SCANFROM [trigger(today()-7)] SATISFY 1
  1128. X+     OMIT [trigger(trigdate())]
  1129. X+ 
  1130. X+     REM Mon AFTER MSG Hello
  1131. X+ .fi
  1132. X+ .PP
  1133. X+ The \fBSCANFROM\fR clause makes sure that \fBRemind\fR begins scanning
  1134. X+ from 7 days before the current date.  This ensures that Labour Day for
  1135. X+ the current year will continue to be triggered until 7 days after it has
  1136. X+ occurred.  This allows you to safely use the AFTER keyword as shown.
  1137. X+ .PP
  1138. X+ In general, use \fBSCANFROM\fR as shown for safe moveable \fBOMITs\fR.  The
  1139. X+ amount you should scan back by (7 days in the example above) depends on
  1140. X+ the number of possible consecutive \fBOMITted\fR days which may occur, and
  1141. X+ on the range of the moveable holiday.  Generally, a value of 7 is safe.
  1142. X+ .PP
  1143. X+ Note that if you use one \fBREM\fR command to calculate a trigger date,
  1144. X+ perform date calculations (addition or subtraction, for example) and
  1145. X+ then use the modified date in a subsequent \fBREM\fR command, the results
  1146. X+ \fImay not be what you intended.\fR  This is because you have circumvented
  1147. X+ the normal scanning mechanism.  You should try to write \fBREM\fR commands
  1148. X+ which compute trigger dates that can be used unmodified in subsequent
  1149. X+ \fBREM\fR commands.  The file "defs.rem" which comes with the \fBRemind\fR
  1150. X+ distribution contains examples.
  1151. X+ .PP
  1152. X  .B DETAILS ABOUT TRIGVALID()
  1153. X  .PP
  1154. X  The \fBtrigvalid()\fR function returns 1 if \fBRemind\fR could find a trigger
  1155. X  date for the previous \fBREM\fR or \fBIFTRIG\fR command.  More specifically,
  1156. X! it returns 1 if \fBRemind\fR finds a date \fInot before the starting
  1157. X! date of the scanning\fR which
  1158. X  satisfies the trigger.  In addition, there is one special case in which
  1159. X  \fBtrigvalid()\fR returns 1 and \fBtrigdate()\fR returns a meaningful result:
  1160. X  .PP
  1161. X***************
  1162. X*** 2294,2300 ****
  1163. X  If the \fBREM\fR or \fBIFTRIG\fR command did not contain an \fBUNTIL\fR
  1164. X  clause, and contained all of the \fIday\fR, \fImonth\fR and \fIyear\fR
  1165. X  components, then \fBRemind\fR will correctly compute a trigger date, even
  1166. X! if it happens to be in the past.  Note that this behaviour is not true for
  1167. X  versions of \fBRemind\fR prior to 03.00.01.
  1168. X  .SH AUTHOR
  1169. X  .PP
  1170. X--- 2533,2540 ----
  1171. X  If the \fBREM\fR or \fBIFTRIG\fR command did not contain an \fBUNTIL\fR
  1172. X  clause, and contained all of the \fIday\fR, \fImonth\fR and \fIyear\fR
  1173. X  components, then \fBRemind\fR will correctly compute a trigger date, even
  1174. X! if it happens to be before the start of scanning.
  1175. X! Note that this behaviour is not true for
  1176. X  versions of \fBRemind\fR prior to 03.00.01.
  1177. X  .SH AUTHOR
  1178. X  .PP
  1179. X*** ../patch3/test.cmp    Tue Feb  2 14:36:18 1993
  1180. X--- ./test.cmp    Wed Mar  3 17:01:52 1993
  1181. X***************
  1182. X*** 199,204 ****
  1183. X--- 199,226 ----
  1184. X  ./test.rem(114): Trig = Monday, 18 February, 1991
  1185. X  
  1186. X  CLEAR-OMIT-CONTEXT
  1187. X+ # Test the scanfrom clause
  1188. X+ REM Fri SATISFY 1
  1189. X+ ./test.rem(118): Trig = Friday, 22 February, 1991
  1190. X+ OMIT [trigger(trigdate())]
  1191. X+ trigdate() => 1991/02/22
  1192. X+ trigger(1991/02/22) => "22 February 1991"
  1193. X+ REM Fri after MSG 23 Feb 1991
  1194. X+ ./test.rem(120): Trig = Saturday, 23 February, 1991
  1195. X+ CLEAR-OMIT-CONTEXT
  1196. X+ REM Fri SCANFROM [trigger(today()-7)] SATISFY 1
  1197. X+ today() => 1991/02/16
  1198. X+ 1991/02/16 - 7 => 1991/02/09
  1199. X+ trigger(1991/02/09) => "9 February 1991"
  1200. X+ ./test.rem(122): Trig = Friday, 15 February, 1991
  1201. X+ OMIT [trigger(trigdate())]
  1202. X+ trigdate() => 1991/02/15
  1203. X+ trigger(1991/02/15) => "15 February 1991"
  1204. X+ REM Fri after MSG 16 Feb 1991
  1205. X+ ./test.rem(124): Trig = Saturday, 16 February, 1991
  1206. X+ 16 Feb 1991
  1207. X+ 
  1208. X+ CLEAR-OMIT-CONTEXT
  1209. X  set a000 abs(1)
  1210. X  abs(1) => 1
  1211. X  set a001 abs(-1)
  1212. X***************
  1213. X*** 221,227 ****
  1214. X  coerce("string", 11:44) => "11:44"
  1215. X  set a009 coerce("int", "badnews")
  1216. X  coerce("int", "badnews") => Can't coerce
  1217. X! ./test.rem(126): Can't coerce
  1218. X  set a010 coerce("int", "12")
  1219. X  coerce("int", "12") => 12
  1220. X  set a011 coerce("int", 11:44)
  1221. X--- 243,249 ----
  1222. X  coerce("string", 11:44) => "11:44"
  1223. X  set a009 coerce("int", "badnews")
  1224. X  coerce("int", "badnews") => Can't coerce
  1225. X! ./test.rem(135): Can't coerce
  1226. X  set a010 coerce("int", "12")
  1227. X  coerce("int", "12") => 12
  1228. X  set a011 coerce("int", 11:44)
  1229. X***************
  1230. X*** 233,239 ****
  1231. X  date(1992, 2, 2) => 1992/02/02
  1232. X  set a014 date(1993, 2, 29)
  1233. X  date(1993, 2, 29) => Bad date specification
  1234. X! ./test.rem(131): Bad date specification
  1235. X  set a015 day(today())
  1236. X  today() => 1991/02/16
  1237. X  day(1991/02/16) => 16
  1238. X--- 255,261 ----
  1239. X  date(1992, 2, 2) => 1992/02/02
  1240. X  set a014 date(1993, 2, 29)
  1241. X  date(1993, 2, 29) => Bad date specification
  1242. X! ./test.rem(140): Bad date specification
  1243. X  set a015 day(today())
  1244. X  today() => 1991/02/16
  1245. X  day(1991/02/16) => 16
  1246. X***************
  1247. X*** 328,342 ****
  1248. X  set a050 substr(a049, 2)
  1249. X  a049 => 21
  1250. X  substr(21, 2) => Type mismatch
  1251. X! ./test.rem(169): Type mismatch
  1252. X  set a051 substr(a050, 2, 6)
  1253. X! a050 => ./test.rem(170): Undefined variable: a050
  1254. X  set a052 time(1+2, 3+4)
  1255. X  1 + 2 => 3
  1256. X  3 + 4 => 7
  1257. X  time(3, 7) => 03:07
  1258. X  rem 10 jan 1992 AT 11:22 CAL
  1259. X! ./test.rem(172): Trig = Friday, 10 January, 1992
  1260. X  set a053 trigdate()
  1261. X  trigdate() => 1992/01/10
  1262. X  set a054 trigtime()
  1263. X--- 350,364 ----
  1264. X  set a050 substr(a049, 2)
  1265. X  a049 => 21
  1266. X  substr(21, 2) => Type mismatch
  1267. X! ./test.rem(178): Type mismatch
  1268. X  set a051 substr(a050, 2, 6)
  1269. X! a050 => ./test.rem(179): Undefined variable: a050
  1270. X  set a052 time(1+2, 3+4)
  1271. X  1 + 2 => 3
  1272. X  3 + 4 => 7
  1273. X  time(3, 7) => 03:07
  1274. X  rem 10 jan 1992 AT 11:22 CAL
  1275. X! ./test.rem(181): Trig = Friday, 10 January, 1992
  1276. X  set a053 trigdate()
  1277. X  trigdate() => 1992/01/10
  1278. X  set a054 trigtime()
  1279. X***************
  1280. X*** 349,355 ****
  1281. X  "a05" + "6" => "a056"
  1282. X  value("a056") => "SDFJHSDF KSJDFH KJSDFH KSJDFH"
  1283. X  set a058 version()
  1284. X! version() => "03.00.03"
  1285. X  set a059 wkday(today())
  1286. X  today() => 1991/02/16
  1287. X  wkday(1991/02/16) => "Saturday"
  1288. X--- 371,377 ----
  1289. X  "a05" + "6" => "a056"
  1290. X  value("a056") => "SDFJHSDF KSJDFH KJSDFH KSJDFH"
  1291. X  set a058 version()
  1292. X! version() => "03.00.04"
  1293. X  set a059 wkday(today())
  1294. X  today() => 1991/02/16
  1295. X  wkday(1991/02/16) => "Saturday"
  1296. X***************
  1297. X*** 389,401 ****
  1298. X  fset g(x,y) max(x,y)
  1299. X  fset h(x,y) min(g(x+y, x*y), g(x-y, x/y))
  1300. X  set a071 g(1, 2)
  1301. X! UserFN g(1, 2)
  1302. X  x => 1
  1303. X  y => 2
  1304. X  max(1, 2) => 2
  1305. X  Leaving UserFN g() => 2
  1306. X  set a072 h(2, 3)
  1307. X! UserFN h(2, 3)
  1308. X  x => 2
  1309. X  y => 3
  1310. X  2 + 3 => 5
  1311. X--- 411,423 ----
  1312. X  fset g(x,y) max(x,y)
  1313. X  fset h(x,y) min(g(x+y, x*y), g(x-y, x/y))
  1314. X  set a071 g(1, 2)
  1315. X! Entering UserFN g(1, 2)
  1316. X  x => 1
  1317. X  y => 2
  1318. X  max(1, 2) => 2
  1319. X  Leaving UserFN g() => 2
  1320. X  set a072 h(2, 3)
  1321. X! Entering UserFN h(2, 3)
  1322. X  x => 2
  1323. X  y => 3
  1324. X  2 + 3 => 5
  1325. X***************
  1326. X*** 402,408 ****
  1327. X  x => 2
  1328. X  y => 3
  1329. X  2 * 3 => 6
  1330. X! UserFN g(5, 6)
  1331. X  x => 5
  1332. X  y => 6
  1333. X  max(5, 6) => 6
  1334. X--- 424,430 ----
  1335. X  x => 2
  1336. X  y => 3
  1337. X  2 * 3 => 6
  1338. X! Entering UserFN g(5, 6)
  1339. X  x => 5
  1340. X  y => 6
  1341. X  max(5, 6) => 6
  1342. X***************
  1343. X*** 413,419 ****
  1344. X  x => 2
  1345. X  y => 3
  1346. X  2 / 3 => 0
  1347. X! UserFN g(-1, 0)
  1348. X  x => -1
  1349. X  y => 0
  1350. X  max(-1, 0) => 0
  1351. X--- 435,441 ----
  1352. X  x => 2
  1353. X  y => 3
  1354. X  2 / 3 => 0
  1355. X! Entering UserFN g(-1, 0)
  1356. X  x => -1
  1357. X  y => 0
  1358. X  max(-1, 0) => 0
  1359. X***************
  1360. X*** 421,427 ****
  1361. X  min(6, 0) => 0
  1362. X  Leaving UserFN h() => 0
  1363. X  set a073 h("foo", 11:33)
  1364. X! UserFN h("foo", 11:33)
  1365. X  x => "foo"
  1366. X  y => 11:33
  1367. X  "foo" + 11:33 => "foo11:33"
  1368. X--- 443,449 ----
  1369. X  min(6, 0) => 0
  1370. X  Leaving UserFN h() => 0
  1371. X  set a073 h("foo", 11:33)
  1372. X! Entering UserFN h("foo", 11:33)
  1373. X  x => "foo"
  1374. X  y => 11:33
  1375. X  "foo" + 11:33 => "foo11:33"
  1376. X***************
  1377. X*** 428,434 ****
  1378. X  x => "foo"
  1379. X  y => 11:33
  1380. X  "foo" * 11:33 => Type mismatch
  1381. X! ./test.rem(195): Operator '*' Type mismatch
  1382. X  Leaving UserFN h() => Type mismatch
  1383. X  
  1384. X      Variable  Value
  1385. X--- 450,456 ----
  1386. X  x => "foo"
  1387. X  y => 11:33
  1388. X  "foo" * 11:33 => Type mismatch
  1389. X! ./test.rem(204): Operator '*' Type mismatch
  1390. X  Leaving UserFN h() => Type mismatch
  1391. X  
  1392. X      Variable  Value
  1393. X***************
  1394. X*** 453,459 ****
  1395. X          a048  "foo"
  1396. X          a067  "INT"
  1397. X          a039  "February"
  1398. X!         a058  "03.00.03"
  1399. X          a049  21
  1400. X          a068  "STRING"
  1401. X          a059  "Saturday"
  1402. X--- 475,481 ----
  1403. X          a048  "foo"
  1404. X          a067  "INT"
  1405. X          a039  "February"
  1406. X!         a058  "03.00.04"
  1407. X          a049  21
  1408. X          a068  "STRING"
  1409. X          a059  "Saturday"
  1410. X*** ../patch3/test.rem    Wed Dec 16 10:51:50 1992
  1411. X--- ./test.rem    Wed Mar  3 17:01:45 1993
  1412. X***************
  1413. X*** 114,119 ****
  1414. X--- 114,128 ----
  1415. X  REM 18 Feb 1991 ++1 MSG 18 Feb 1991 ++1 (17Feb91 omitted)
  1416. X  
  1417. X  CLEAR-OMIT-CONTEXT
  1418. X+ # Test the scanfrom clause
  1419. X+ REM Fri SATISFY 1
  1420. X+ OMIT [trigger(trigdate())]
  1421. X+ REM Fri after MSG 23 Feb 1991
  1422. X+ CLEAR-OMIT-CONTEXT
  1423. X+ REM Fri SCANFROM [trigger(today()-7)] SATISFY 1
  1424. X+ OMIT [trigger(trigdate())]
  1425. X+ REM Fri after MSG 16 Feb 1991
  1426. X+ CLEAR-OMIT-CONTEXT
  1427. X  set a000 abs(1)
  1428. X  set a001 abs(-1)
  1429. X  set a002 asc("foo")
  1430. X*** ../patch3/token.c    Thu Jan 21 16:45:40 1993
  1431. X--- ./token.c    Tue Mar  2 12:10:53 1993
  1432. X***************
  1433. X*** 75,85 ****
  1434. X     { "once",         3,     T_Once,        0 },
  1435. X     { "pop-omit-context", 3,    T_Pop,        0 },
  1436. X     { "preserve",        8,      T_Preserve,     0 },
  1437. X!    { "Push-omit-context", 4,     T_Push,        0 },
  1438. X     { "rem",        3,    T_Rem,        0 },
  1439. X     { "run",         3,     T_RemType,     RUN_TYPE },
  1440. X     { "satisfy",        7,    T_RemType,      SAT_TYPE },
  1441. X     { "saturday",    3,    T_WkDay,    5 },
  1442. X     { "september",     3,     T_Month,     8 },
  1443. X     { "set",        3,    T_Set,        0 },
  1444. X     { "skip",         3,     T_Skip,     SKIP_SKIP },
  1445. X--- 75,86 ----
  1446. X     { "once",         3,     T_Once,        0 },
  1447. X     { "pop-omit-context", 3,    T_Pop,        0 },
  1448. X     { "preserve",        8,      T_Preserve,     0 },
  1449. X!    { "push-omit-context", 4,     T_Push,        0 },
  1450. X     { "rem",        3,    T_Rem,        0 },
  1451. X     { "run",         3,     T_RemType,     RUN_TYPE },
  1452. X     { "satisfy",        7,    T_RemType,      SAT_TYPE },
  1453. X     { "saturday",    3,    T_WkDay,    5 },
  1454. X+    { "scanfrom",    4,    T_Scanfrom,    0 },
  1455. X     { "september",     3,     T_Month,     8 },
  1456. X     { "set",        3,    T_Set,        0 },
  1457. X     { "skip",         3,     T_Skip,     SKIP_SKIP },
  1458. X***************
  1459. X*** 173,178 ****
  1460. X--- 174,180 ----
  1461. X  #endif
  1462. X  {
  1463. X     register int top, bot, mid, r;
  1464. X+    int l;
  1465. X  
  1466. X     tok->type = T_Illegal;
  1467. X     if (! *s) {
  1468. X***************
  1469. X*** 191,196 ****
  1470. X--- 193,199 ----
  1471. X        return;
  1472. X     }
  1473. X  
  1474. X+    l = strlen(s);
  1475. X     bot = 0;
  1476. X     top = sizeof(TokArray) / sizeof(TokArray[0]) - 1;
  1477. X  
  1478. X***************
  1479. X*** 198,207 ****
  1480. X        mid = (top + bot) / 2;
  1481. X        r = TokStrCmp(&TokArray[mid], s);
  1482. X        if (!r) {
  1483. X!      tok->type = TokArray[mid].type;
  1484. X!      tok->val  = TokArray[mid].val;
  1485. X!      return;
  1486. X!       }
  1487. X        if (r > 0) top = mid-1; else bot=mid+1;
  1488. X     }
  1489. X  
  1490. X--- 201,222 ----
  1491. X        mid = (top + bot) / 2;
  1492. X        r = TokStrCmp(&TokArray[mid], s);
  1493. X        if (!r) {
  1494. X!          if (l >= TokArray[mid].MinLen) {
  1495. X!            tok->type = TokArray[mid].type;
  1496. X!         tok->val  = TokArray[mid].val;
  1497. X!         return;
  1498. X!          } else {
  1499. X!         while (mid && !TokStrCmp(&TokArray[mid-1],s)) mid--;
  1500. X!         while (!TokStrCmp(&TokArray[mid], s) && l < TokArray[mid].MinLen)
  1501. X!            mid++;
  1502. X!         if (!TokStrCmp(&TokArray[mid], s)) {
  1503. X!            tok->type = TokArray[mid].type;
  1504. X!            tok->val = TokArray[mid].val;
  1505. X!            return;
  1506. X!         }
  1507. X!          }
  1508. X!      break;
  1509. X!        }
  1510. X        if (r > 0) top = mid-1; else bot=mid+1;
  1511. X     }
  1512. X  
  1513. X***************
  1514. X*** 209,215 ****
  1515. X     array. */
  1516. X  #if LANG != ENGLISH
  1517. X      for (r=0; r<(sizeof(NonEnglishToks) / sizeof(Token)); r++) {
  1518. X!        if (!TokStrCmp(&NonEnglishToks[r], s)) {
  1519. X            tok->type = NonEnglishToks[r].type;
  1520. X            tok->val = NonEnglishToks[r].val;
  1521. X        return;
  1522. X--- 224,231 ----
  1523. X     array. */
  1524. X  #if LANG != ENGLISH
  1525. X      for (r=0; r<(sizeof(NonEnglishToks) / sizeof(Token)); r++) {
  1526. X!        if (l >= NonEnglishToks[r].MinLen && 
  1527. X!                 !TokStrCmp(&NonEnglishToks[r], s)) {
  1528. X            tok->type = NonEnglishToks[r].type;
  1529. X            tok->val = NonEnglishToks[r].val;
  1530. X        return;
  1531. X***************
  1532. X*** 247,254 ****
  1533. X     if (isdigit(*s)) {
  1534. X        PARSENUM(t->val, s);
  1535. X  
  1536. X!       /* If we hit a colon, we've probably got a time hr:min */
  1537. X!       if (*s == ':') {
  1538. X       s++;
  1539. X       hour = t->val;
  1540. X       PARSENUM(min, s);
  1541. X--- 263,270 ----
  1542. X     if (isdigit(*s)) {
  1543. X        PARSENUM(t->val, s);
  1544. X  
  1545. X!       /* If we hit a colon or a period, we've probably got a time hr:min */
  1546. X!       if (*s == ':' || *s == '.' || *s == TIMESEP) {
  1547. X       s++;
  1548. X       hour = t->val;
  1549. X       PARSENUM(min, s);
  1550. X***************
  1551. X*** 312,327 ****
  1552. X  #endif
  1553. X  {
  1554. X     register int r;
  1555. X-    register int l=0;
  1556. X     char *tk = t->name;
  1557. X     while(*tk && *s) {
  1558. X        r = UPPER(*tk) - UPPER(*s);
  1559. X        tk++;
  1560. X        s++;
  1561. X-       l++;
  1562. X        if (r) return r;
  1563. X     }
  1564. X-    if (l < t->MinLen) return 1;
  1565. X     if (!*s) return 0;
  1566. X     return (*tk - *s);
  1567. X  }
  1568. X--- 328,340 ----
  1569. X*** ../patch3/types.h    Fri Jan  8 13:23:23 1993
  1570. X--- ./types.h    Mon Mar  1 16:56:54 1993
  1571. X***************
  1572. X*** 51,56 ****
  1573. X--- 51,57 ----
  1574. X     int until;
  1575. X     int typ;
  1576. X     int once;
  1577. X+    int scanfrom;
  1578. X  } Trigger;
  1579. X  
  1580. X  /* A time trigger */
  1581. X***************
  1582. X*** 84,90 ****
  1583. X  #define NO_UNTIL -1
  1584. X  #define NO_ONCE 0
  1585. X  #define ONCE_ONCE 1
  1586. X! 
  1587. X  #define NO_SKIP 0
  1588. X  #define SKIP_SKIP 1
  1589. X  #define BEFORE_SKIP 2
  1590. X--- 85,91 ----
  1591. X  #define NO_UNTIL -1
  1592. X  #define NO_ONCE 0
  1593. X  #define ONCE_ONCE 1
  1594. X! #define NO_DATE -1
  1595. X  #define NO_SKIP 0
  1596. X  #define SKIP_SKIP 1
  1597. X  #define BEFORE_SKIP 2
  1598. X***************
  1599. X*** 121,127 ****
  1600. X    T_Number,
  1601. X    T_Clr,
  1602. X    T_Debug,
  1603. X!   T_Dumpvars
  1604. X  };
  1605. X  
  1606. X  /* The structure of a token */
  1607. X--- 122,129 ----
  1608. X    T_Number,
  1609. X    T_Clr,
  1610. X    T_Debug,
  1611. X!   T_Dumpvars,
  1612. X!   T_Scanfrom
  1613. X  };
  1614. X  
  1615. X  /* The structure of a token */
  1616. X***************
  1617. X*** 154,156 ****
  1618. X--- 156,162 ----
  1619. X  #define SC_AMPM   0   /* Time shown as 3:00am, etc. */
  1620. X  #define SC_MIL    1   /* 24-hour time format */
  1621. X  #define SC_NOTIME 2   /* Do not display time in SC format. */
  1622. X+ 
  1623. X+ /* Flags for sorting */
  1624. X+ #define SORT_ASCEND 1
  1625. X+ #define SORT_DESCEND 2
  1626. X*** ../patch3/userfns.c    Fri Feb  5 14:57:30 1993
  1627. X--- ./userfns.c    Tue Mar  2 11:39:01 1993
  1628. X***************
  1629. X*** 27,34 ****
  1630. X  #define FUNC_HASH_SIZE 32   /* Size of User-defined function hash table */
  1631. X  
  1632. X  /* Define the data structure used to hold a user-defined function */
  1633. X! typedef struct _udf_struct {
  1634. X!    struct _udf_struct *next;
  1635. X     char name[VAR_NAME_LEN+1];
  1636. X     char *text;
  1637. X     Var *locals;
  1638. X--- 27,34 ----
  1639. X  #define FUNC_HASH_SIZE 32   /* Size of User-defined function hash table */
  1640. X  
  1641. X  /* Define the data structure used to hold a user-defined function */
  1642. X! typedef struct udf_struct {
  1643. X!    struct udf_struct *next;
  1644. X     char name[VAR_NAME_LEN+1];
  1645. X     char *text;
  1646. X     Var *locals;
  1647. X***************
  1648. X*** 40,45 ****
  1649. X--- 40,49 ----
  1650. X  /* The hash table */
  1651. X  static UserFunc *FuncHash[FUNC_HASH_SIZE];
  1652. X  
  1653. X+ /* Access to built-in functions */
  1654. X+ extern int NumFuncs;
  1655. X+ extern Operator Func[];
  1656. X+ 
  1657. X  /* We need access to the expression evaluation stack */
  1658. X  extern Value ValStack[];
  1659. X  extern int ValStackPtr;
  1660. X***************
  1661. X*** 80,85 ****
  1662. X--- 84,95 ----
  1663. X     func = NEW(UserFunc);
  1664. X     if (!func) return E_NO_MEM;
  1665. X     StrnCpy(func->name, TokBuffer, VAR_NAME_LEN);
  1666. X+    if (!Hush) {
  1667. X+       if (FindFunc(TokBuffer, Func, NumFuncs)) {
  1668. X+          Eprint("Warning:  Attempt to redefine built-in function '%s'",
  1669. X+              TokBuffer);
  1670. X+       }
  1671. X+    }
  1672. X     func->locals = NULL;
  1673. X     func->text = NULL;
  1674. X     func->IsCached = 1;
  1675. X***************
  1676. X*** 252,262 ****
  1677. X     /* Search for the function */
  1678. X     f = FuncHash[h];
  1679. X     while (f && !StrinEq(name, f->name, VAR_NAME_LEN)) f = f->next;
  1680. X!    if (!f) return E_UNDEF_FUNC;
  1681. X! 
  1682. X     /* Debugging stuff */
  1683. X     if (DebugFlag & DB_PRTEXPR) {
  1684. X!       fprintf(ErrFp, "UserFN %s(", f->name);
  1685. X        for (i=0; i<nargs; i++) {
  1686. X           PrintValue(&ValStack[ValStackPtr - nargs + i], ErrFp);
  1687. X           if (i<nargs-1) fprintf(ErrFp, ", ");
  1688. X--- 262,274 ----
  1689. X     /* Search for the function */
  1690. X     f = FuncHash[h];
  1691. X     while (f && !StrinEq(name, f->name, VAR_NAME_LEN)) f = f->next;
  1692. X!    if (!f) {
  1693. X!       Eprint("Undefined function '%s'", name);
  1694. X!       return E_UNDEF_FUNC;
  1695. X!    }
  1696. X     /* Debugging stuff */
  1697. X     if (DebugFlag & DB_PRTEXPR) {
  1698. X!       fprintf(ErrFp, "Entering UserFN %s(", f->name);
  1699. X        for (i=0; i<nargs; i++) {
  1700. X           PrintValue(&ValStack[ValStackPtr - nargs + i], ErrFp);
  1701. X           if (i<nargs-1) fprintf(ErrFp, ", ");
  1702. X***************
  1703. X*** 264,278 ****
  1704. X        fprintf(ErrFp, ")\n");
  1705. X     }
  1706. X     /* Detect illegal recursive call */
  1707. X!    if (f->IsActive) return E_RECURSIVE;
  1708. X! 
  1709. X     /* Check number of args */
  1710. X!    if (nargs != f->nargs)
  1711. X        return (nargs < f->nargs) ? E_2FEW_ARGS : E_2MANY_ARGS;
  1712. X! 
  1713. X     /* Found the function - set up a local variable frame */
  1714. X     h = SetUpLocalVars(f);
  1715. X!    if (h) return h;
  1716. X  
  1717. X     /* Evaluate the expression */
  1718. X     f->IsActive = 1;
  1719. X--- 276,307 ----
  1720. X        fprintf(ErrFp, ")\n");
  1721. X     }
  1722. X     /* Detect illegal recursive call */
  1723. X!    if (f->IsActive) {
  1724. X!       if (DebugFlag &DB_PRTEXPR) {
  1725. X!          fprintf(ErrFp, "Leaving UserFN %s() => ", name);
  1726. X!          fprintf(ErrFp, "%s\n", ErrMsg[E_RECURSIVE]);
  1727. X!       }
  1728. X!       return E_RECURSIVE;
  1729. X!    }
  1730. X!    
  1731. X     /* Check number of args */
  1732. X!    if (nargs != f->nargs) {
  1733. X!       if (DebugFlag &DB_PRTEXPR) {
  1734. X!          fprintf(ErrFp, "Leaving UserFN %s() => ", name);
  1735. X!          fprintf(ErrFp, "%s\n",
  1736. X!         ErrMsg[(nargs < f->nargs) ? E_2FEW_ARGS : E_2MANY_ARGS]);
  1737. X!       }
  1738. X        return (nargs < f->nargs) ? E_2FEW_ARGS : E_2MANY_ARGS;
  1739. X!    }
  1740. X     /* Found the function - set up a local variable frame */
  1741. X     h = SetUpLocalVars(f);
  1742. X!    if (h) {
  1743. X!       if (DebugFlag &DB_PRTEXPR) {
  1744. X!          fprintf(ErrFp, "Leaving UserFN %s() => ", name);
  1745. X!          fprintf(ErrFp, "%s\n", ErrMsg[h]);
  1746. X!       }
  1747. X!       return h;
  1748. X!    }
  1749. X  
  1750. X     /* Evaluate the expression */
  1751. X     f->IsActive = 1;
  1752. X***************
  1753. X*** 343,345 ****
  1754. X--- 372,398 ----
  1755. X        v = v->next;
  1756. X     }
  1757. X  }
  1758. X+ /***************************************************************/
  1759. X+ /*                                                             */
  1760. X+ /*  UserFuncExists                                             */
  1761. X+ /*                                                             */
  1762. X+ /*  Return the number of arguments accepted by the function if */
  1763. X+ /*  it is defined, or -1 if it is not defined.                 */
  1764. X+ /*                                                             */
  1765. X+ /***************************************************************/
  1766. X+ #ifdef HAVE_PROTOS
  1767. X+ PUBLIC int UserFuncExists(char *fn)
  1768. X+ #else
  1769. X+ int UserFuncExists(fn)
  1770. X+ char *fn;
  1771. X+ #endif
  1772. X+ {
  1773. X+    UserFunc *f;
  1774. X+    int h = HashVal(fn) % FUNC_HASH_SIZE;
  1775. X+ 
  1776. X+    f = FuncHash[h];
  1777. X+    while (f && !StrinEq(fn, f->name, VAR_NAME_LEN)) f = f->next;
  1778. X+    if (!f) return -1;
  1779. X+    else return f->nargs;
  1780. X+ }
  1781. X+ 
  1782. X*** ../patch3/utils.c    Thu Jan 21 16:33:51 1993
  1783. X--- ./utils.c    Thu Feb 18 13:28:38 1993
  1784. X***************
  1785. X*** 19,24 ****
  1786. X--- 19,25 ----
  1787. X  #include <malloc.h>
  1788. X  #endif
  1789. X  #include <ctype.h>
  1790. X+ #include "globals.h"
  1791. X  
  1792. X  #define UPPER(c) (islower(c) ? toupper(c) : c)
  1793. X  
  1794. X***************
  1795. X*** 218,220 ****
  1796. X--- 219,243 ----
  1797. X  }
  1798. X  #endif
  1799. X  
  1800. X+ /***************************************************************/
  1801. X+ /*                                                             */
  1802. X+ /*  DateOK                                                     */
  1803. X+ /*                                                             */
  1804. X+ /*  Return 1 if the date is OK, 0 otherwise.                   */
  1805. X+ /*                                                             */
  1806. X+ /***************************************************************/
  1807. X+ #ifdef HAVE_PROTOS
  1808. X+ PUBLIC int DateOK(int y, int m, int d)
  1809. X+ #else
  1810. X+ int DateOK(y, m, d)
  1811. X+ int y, m, d;
  1812. X+ #endif
  1813. X+ {
  1814. X+    if (d < 1                 ||
  1815. X+        m < 0                 ||
  1816. X+        y < BASE              ||
  1817. X+        m > 11                ||
  1818. X+        y > BASE + YR_RANGE   ||
  1819. X+        d > DaysInMonth(m, y) ) return 0;
  1820. X+    else return 1;
  1821. X+ }
  1822. END_OF_FILE
  1823.   if test 58300 -ne `wc -c <'patch.04.B'`; then
  1824.     echo shar: \"'patch.04.B'\" unpacked with wrong size!
  1825.   elif test -f 'patch.04.A'; then
  1826.     echo shar: Combining  \"'patch.04'\" \(111518 characters\)
  1827.     cat 'patch.04.A' 'patch.04.B' > 'patch.04'
  1828.     if test 111518 -ne `wc -c <'patch.04'`; then
  1829.       echo shar: \"'patch.04'\" combined with wrong size!
  1830.     else
  1831.       rm patch.04.A patch.04.B
  1832.     fi
  1833.   fi
  1834.   # end of 'patch.04.B'
  1835. fi
  1836. echo shar: End of archive 2 \(of 3\).
  1837. cp /dev/null ark2isdone
  1838. MISSING=""
  1839. for I in 1 2 3 ; do
  1840.     if test ! -f ark${I}isdone ; then
  1841.     MISSING="${MISSING} ${I}"
  1842.     fi
  1843. done
  1844. if test "${MISSING}" = "" ; then
  1845.     echo You have unpacked all 3 archives.
  1846.     rm -f ark[1-9]isdone
  1847. else
  1848.     echo You still must unpack the following archives:
  1849.     echo "        " ${MISSING}
  1850. fi
  1851. exit 0
  1852. exit 0 # Just in case...
  1853.