home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume38 / remind / patch07a < prev    next >
Encoding:
Text File  |  1993-07-22  |  51.6 KB  |  1,494 lines

  1. Newsgroups: comp.sources.misc
  2. From: <dfs@doe.carleton.ca> (David F. Skoll)
  3. Subject: v38i062:  remind - A replacement for calendar, Patch07a/3
  4. Message-ID: <csm-v38i062=remind.163723@sparky.Sterling.COM>
  5. X-Md4-Signature: 2ce1700591aef22a24fb7f7501eba57d
  6. Sender: kent@sparky.sterling.com (Kent Landfield)
  7. Organization: Dept. of Electronics, Carleton University
  8. Date: Thu, 22 Jul 1993 21:37:44 GMT
  9. Approved: kent@sparky.sterling.com
  10.  
  11. Submitted-by: <dfs@doe.carleton.ca> (David F. Skoll)
  12. Posting-number: Volume 38, Issue 62
  13. Archive-name: remind/patch07a
  14. Environment: UNIX, MS-DOS, OS/2
  15. Patch-To: remind: Volume 33, Issue 58-69
  16.  
  17. This is patch 7 for version 3.0 of Remind.
  18.  
  19. Remind is a sophisticated calendar/alarm program, which runs under
  20. MS-DOS, UNIX and OS/2.
  21.  
  22. >From the WHATSNEW file:
  23.  
  24. * Version 3.0 Patch 7
  25.  
  26. + MAJOR ENHANCEMENTS
  27.  
  28. - Added "system variables" to allow the user more control over
  29.   Remind operation, and to allow queries about the command-line
  30.   options from within a reminder script.  They allow for specification
  31.   of longitude and latitude for use by sunrise/sunset calculations.
  32.  
  33. - Added sunrise(), sunset(), isdst() and minsfromutc() functions -
  34.   these are needed to support sunrise and sunset calculations.
  35.  
  36. + MINOR ENHANCEMENTS
  37.  
  38. - Allowed the MSG, RUN, CAL, PS and PSF keywords to be used in the
  39.   same reminder as the SATISFY keyword.  This makes many complex
  40.   reminders more compact.
  41.  
  42. - Added the filedir() function to enable Remind's include to emulate
  43.   CPP's #include more closely.
  44.  
  45. - Allowed non-root users to use the "-u" option.  It only affects
  46.   the "SHELL", "HOME", "USER" and "LOGNAME" environment variables -
  47.   it doesn't change the effective uid and gid when run by non-root.
  48.  
  49. - Added built-in function "easterdate" to calculate date of Easter
  50.   Sunday - function courtesy of Michael Salmon.
  51.  
  52. - Improved the Jewish holiday reminders in "defs.rem" to give advance
  53.   notice of holidays.
  54.  
  55. - Allowed the "simple calendar" option (-s) to specify a number of
  56.   weeks as well as a number of months, in the same fashion as the
  57.   -c option.  Thanks to Dave Rickel.
  58.  
  59. + BUG FIXES
  60.  
  61. - Corrected the behaviour of "hebdate" for jahrzeits; added an additional
  62.   parameter to specify the behaviour of dates in Adar during leap years.
  63.  
  64. - Changed kall so that "kall sh" doesn't commit suicide - patch courtesy
  65.   of Michael Salmon.
  66.  
  67. Availability: Remind is available via anonymous ftp at ftp.doe.carleton.ca
  68. (134.117.9.35) in the directory /pub/remind-3.0 - see the file README.1st
  69. in that directory for a list of files.
  70. -----
  71. #! /bin/sh
  72. # This is a shell archive.  Remove anything before this line, then feed it
  73. # into a shell via "sh file" or similar.  To overwrite existing files,
  74. # type "sh file -c".
  75. # Contents:  patch.07.C
  76. # Wrapped by kent@sparky on Thu Jul 22 16:19:13 1993
  77. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  78. echo If this archive is complete, you will see the following message:
  79. echo '          "shar: End of archive 1 (of 3)."'
  80. if test -f 'patch.07.C' -a "${1}" != "-c" ; then 
  81.   echo shar: Will not clobber existing file \"'patch.07.C'\"
  82. else
  83.   echo shar: Extracting \"'patch.07.C'\" \(47360 characters\)
  84.   sed "s/^X//" >'patch.07.C' <<'END_OF_FILE'
  85. X+ 
  86. X+ #if !defined(HAVE_MKTIME)
  87. X+    loc_t = timelocal(&local);
  88. X+    local.tm_isdst = 0;
  89. X+    utc_t = timegm(&local);
  90. X+ #else
  91. X+    loc_t = mktime(&local);
  92. X+    if (loc_t == -1) return 1;
  93. X+    temp = gmtime(&loc_t);
  94. X+    utc = *temp;
  95. X+    utc.tm_isdst = 0;
  96. X+    utc_t = mktime(&utc);
  97. X+    if (utc_t == -1) return 1;
  98. X+ #endif
  99. X+    temp = localtime(&loc_t);
  100. X+ #ifdef HAVE_MKTIME
  101. X+    if (mins) *mins = (int)  ( ((temp->tm_isdst) ? 60 : 0) +
  102. X+                              (loc_t - utc_t) / 60 );  /* Should use difftime */
  103. X+ #else
  104. X+    if (mins) *mins = (int) ((utc_t - loc_t) / 60);
  105. X+ #endif   
  106. X+    if (isdst) *isdst = temp->tm_isdst;
  107. X+    return 0;
  108. X+ }
  109. X*** ../p6/makefile.os2    Fri Apr 23 13:00:11 1993
  110. X--- ./makefile.os2    Mon Jun 28 12:30:19 1993
  111. X***************
  112. X*** 25,31 ****
  113. X  # YOU SHOULDN'T EDIT ANYTHING BELOW HERE.  You may want to change some things
  114. X  # in config.h; then, you should be able to type 'make'.
  115. X  #-----------------------------------------------------------------------------
  116. X! VERSION= 03.00.06
  117. X  
  118. X  HDRS= config.h err.h expr.h globals.h protos.h types.h version.h \
  119. X  lang.h english.h german.h dutch.h finish.h
  120. X--- 25,31 ----
  121. X  # YOU SHOULDN'T EDIT ANYTHING BELOW HERE.  You may want to change some things
  122. X  # in config.h; then, you should be able to type 'make'.
  123. X  #-----------------------------------------------------------------------------
  124. X! VERSION= 03.00.07
  125. X  
  126. X  HDRS= config.h err.h expr.h globals.h protos.h types.h version.h \
  127. X  lang.h english.h german.h dutch.h finish.h
  128. X*** ../p6/makefile.tc    Fri Apr 23 13:00:07 1993
  129. X--- ./makefile.tc    Mon Jun 28 12:30:09 1993
  130. X***************
  131. X*** 1,6 ****
  132. X  # Makefile for REMIND for Turbo C for MSDOS
  133. X  
  134. X! VERSION= 03.00.06
  135. X  
  136. X  HDRS= config.h err.h expr.h globals.h protos.h types.h version.h \
  137. X  lang.h english.h german.h dutch.h finnish.h
  138. X--- 1,6 ----
  139. X  # Makefile for REMIND for Turbo C for MSDOS
  140. X  
  141. X! VERSION= 03.00.07
  142. X  
  143. X  HDRS= config.h err.h expr.h globals.h protos.h types.h version.h \
  144. X  lang.h english.h german.h dutch.h finnish.h
  145. X*** ../p6/protos.h    Thu Apr 22 10:24:12 1993
  146. X--- ./protos.h    Mon Jun 28 12:37:30 1993
  147. X***************
  148. X*** 90,98 ****
  149. X  void FindToken ARGS ((const char *s, Token *tok));
  150. X  void FindNumericToken ARGS ((const char *s, Token *t));
  151. X  int ComputeTrigger ARGS ((int today, Trigger *trig, int *err));
  152. X- int StrEq ARGS ((const char *s1, const char *s2));
  153. X- int StriEq ARGS ((const char *s1, const char *s2));
  154. X- int StrinEq ARGS ((const char *s1, const char *s2, int n));
  155. X  char *StrnCpy ARGS ((char *dest, const char *source, int n));
  156. X  int StrMatch ARGS ((const char *s1, const char *s2, int n));
  157. X  int StrinCmp ARGS ((const char *s1, const char *s2, int n));
  158. X--- 90,95 ----
  159. X***************
  160. X*** 125,130 ****
  161. X  int DaysInHebYear ARGS((int y));
  162. X  char *DaysInHebMonths ARGS((int ylen));
  163. X  int HebToJul ARGS((int hy, int hm, int hd));
  164. X! int GetValidHebDate ARGS((int yin, int min, int din, int *mout, int *dout, int yahr));
  165. X! int GetNextHebrewDate ARGS((int julstart, int hm, int hd, int yahr, int *ans));
  166. X  int ComputeJahr ARGS ((int y, int m, int d, int *ans));
  167. X--- 122,131 ----
  168. X  int DaysInHebYear ARGS((int y));
  169. X  char *DaysInHebMonths ARGS((int ylen));
  170. X  int HebToJul ARGS((int hy, int hm, int hd));
  171. X! int GetValidHebDate ARGS((int yin, int min, int din, int adarbehave, int *mout, int *dout, int yahr));
  172. X! int GetNextHebrewDate ARGS((int julstart, int hm, int hd, int yahr, int adarbehave, int *ans));
  173. X  int ComputeJahr ARGS ((int y, int m, int d, int *ans));
  174. X+ int GetSysVar ARGS ((const char *name, Value *val));
  175. X+ int SetSysVar ARGS ((const char *name, int value));
  176. X+ void DumpSysVarByName ARGS ((const char *name));
  177. X+ int CalcMinsFromUTC ARGS ((int jul, int tim, int *mins, int *isdst));
  178. X*** ../p6/rem2ps.c    Mon May  3 10:37:57 1993
  179. X--- ./rem2ps.c    Mon Jun 28 12:30:22 1993
  180. X***************
  181. X*** 139,145 ****
  182. X        }
  183. X     }
  184. X     if (!validfile) {
  185. X!       fprintf(stderr, "Couldn't find any calendar data!\n");
  186. X        exit(1);
  187. X     }
  188. X     printf("%%%%Trailer\n");
  189. X--- 139,146 ----
  190. X        }
  191. X     }
  192. X     if (!validfile) {
  193. X!       fprintf(stderr, "rem2ps: Couldn't find any calendar data - are you\n");
  194. X!       fprintf(stderr, "        sure you fed me input produced by remind -p ...?\n");
  195. X        exit(1);
  196. X     }
  197. X     printf("%%%%Trailer\n");
  198. X***************
  199. X*** 163,169 ****
  200. X     int days, wkday, prevdays, nextdays;
  201. X     int sfirst;
  202. X     int i;
  203. X!    int smallcol;
  204. X     int is_ps;
  205. X     CalEntry *c, *d;
  206. X  
  207. X--- 164,170 ----
  208. X     int days, wkday, prevdays, nextdays;
  209. X     int sfirst;
  210. X     int i;
  211. X!    int smallcol = 0; /* Stop GCC from complaining about uninit var */
  212. X     int is_ps;
  213. X     CalEntry *c, *d;
  214. X  
  215. X*** ../p6/remind.1    Mon May  3 15:28:18 1993
  216. X--- ./remind.1    Mon Jul 19 11:31:13 1993
  217. X***************
  218. X*** 46,57 ****
  219. X  The \fB\-s\fR option is very similar to the \fB\-c\fR option, except
  220. X  that the output calendar is not formatted.  It is listed in a "simple
  221. X  format" which can be used as input for more sophisticated calendar-drawing
  222. X! programs.
  223. X  .TP
  224. X  .B \-p\fR\fIn\fR
  225. X  The \fB\-p\fR option is very similar to the \fB\-s\fR option, except
  226. X  that the output contains additional information for use by the
  227. X! \fBrem2ps\fR program, which creates a PostScript calendar.
  228. X  .TP
  229. X  .B \-v
  230. X  The \fB\-v\fR option makes the output of \fBRemind\fR slightly more verbose.
  231. X--- 46,59 ----
  232. X  The \fB\-s\fR option is very similar to the \fB\-c\fR option, except
  233. X  that the output calendar is not formatted.  It is listed in a "simple
  234. X  format" which can be used as input for more sophisticated calendar-drawing
  235. X! programs.  If \fIn\fR starts with "+", then it is interpreted as a number
  236. X! of weeks.
  237. X  .TP
  238. X  .B \-p\fR\fIn\fR
  239. X  The \fB\-p\fR option is very similar to the \fB\-s\fR option, except
  240. X  that the output contains additional information for use by the
  241. X! \fBrem2ps\fR program, which creates a PostScript calendar.  For this
  242. X! option, \fIn\fR cannot start with "+"; it must specify a number of months.
  243. X  .TP
  244. X  .B \-v
  245. X  The \fB\-v\fR option makes the output of \fBRemind\fR slightly more verbose.
  246. X***************
  247. X*** 169,180 ****
  248. X  .TP
  249. X  \fB\-u\fR\fIname\fR
  250. X  Runs \fBRemind\fR with the uid and gid of the user specified by \fIname\fR.
  251. X! The \fB\-u\fR option is available only to root, and cannot be used by normal
  252. X! users.  The option changes the uid and gid as described, and sets the
  253. X  environment variables HOME, SHELL and USER to the home directory, shell,
  254. X  and user name, respectively, of the specified user.  LOGNAME is also
  255. X  set to the specified user name.  This option is meant for
  256. X  use in shell scripts which mail reminders to all users.
  257. X  .TP
  258. X  \fB\-i\fR\fIvar\fR\fB=\fR\fIexpr\fR
  259. X  Sets the value of the specified \fIvar\fR to \fIexpr\fR, and \fBpreserves\fR
  260. X--- 171,187 ----
  261. X  .TP
  262. X  \fB\-u\fR\fIname\fR
  263. X  Runs \fBRemind\fR with the uid and gid of the user specified by \fIname\fR.
  264. X! The option changes the uid and gid as described, and sets the
  265. X  environment variables HOME, SHELL and USER to the home directory, shell,
  266. X  and user name, respectively, of the specified user.  LOGNAME is also
  267. X  set to the specified user name.  This option is meant for
  268. X  use in shell scripts which mail reminders to all users.
  269. X+ .PP
  270. X+ .RS
  271. X+ Non-root users can also use the \fB\-u\fR option.  However, in this
  272. X+ case, it only changes the environment variables as described above.
  273. X+ It does not change the effective uid or gid.
  274. X+ .RE
  275. X  .TP
  276. X  \fB\-i\fR\fIvar\fR\fB=\fR\fIexpr\fR
  277. X  Sets the value of the specified \fIvar\fR to \fIexpr\fR, and \fBpreserves\fR
  278. X***************
  279. X*** 1438,1443 ****
  280. X--- 1445,1583 ----
  281. X      UNSET a b mydir time date
  282. X  .fi
  283. X  .PP
  284. X+ .B SYSTEM VARIABLES
  285. X+ .PP
  286. X+ In addition to the regular user variables, \fBRemind\fR has several
  287. X+ "system variables" which are used to query or control the operating
  288. X+ state of \fBRemind\fR.  System variables are available starting from
  289. X+ version 03.00.07 of \fBRemind\fR.
  290. X+ .PP
  291. X+ All system variables begin with a dollar sign '$'.  They can be used
  292. X+ in \fBSET\fR commands and expressions just as regular variables can.  However,
  293. X+ system variables always hold values of type \fBINT\fR.  In addition,
  294. X+ some system variables cannot be modified, and you cannot create new
  295. X+ system variables.  System variables can be initialized on the command
  296. X+ line with the \fB\-i\fR option, but you may need to quote them to avoid
  297. X+ having the shell interpret the dollar sign.  System variable names are
  298. X+ not case-sensitive.
  299. X+ .PP
  300. X+ The following system variables are defined.  Those marked
  301. X+ "read-only" cannot be changed with the \fBSET\fR command.
  302. X+ .TP
  303. X+ .B $CalcUTC 
  304. X+ If 1 (the default), then \fBRemind\fR uses C library functions
  305. X+ to calculate the number of minutes between local and universal time.
  306. X+ This affects astronomical calculations (\fBsunrise()\fR for example.)
  307. X+ If 0, then you must supply the number of minutes between local and
  308. X+ universal time in the \fB$MinsFromUTC\fR system variable.
  309. X+ .TP
  310. X+ .B $CalMode (read-only)
  311. X+ If non-zero, then the \fB\-c\fR option was supplied on the command line.
  312. X+ .TP
  313. X+ .B $Daemon (read-only)
  314. X+ If the daemon mode \fB\-z\fR was invoked, contains the number of
  315. X+ minutes between wakeups.  If not running in daemon mode, contains
  316. X+ 0.  For the MS-DOS version, always contains 0.
  317. X+ .TP
  318. X+ .B $DontFork (read-only)
  319. X+ If non-zero, then the \fB\-c\fR option was supplied on the command line.
  320. X+ For the MS-DOS version, always contains 1.
  321. X+ .TP
  322. X+ .B $DontTrigAts (read-only)
  323. X+ If non-zero, then the \fB\-a\fR option was supplied on the command line.
  324. X+ For the MS-DOS version, always contains 0.
  325. X+ .TP
  326. X+ .B $DontQueue (read-only)
  327. X+ If non-zero, then the \fB\-q\fR option was supplied on the command line.
  328. X+ For the MS-DOS version, always contains 1.
  329. X+ .TP
  330. X+ .B $FoldYear
  331. X+ The standard Unix library functions may have difficulty dealing with dates
  332. X+ later than 2037.  If this variable is set to 1, then the UTC calculations
  333. X+ "fold back" years later than 2037 before using the Unix library functions.
  334. X+ For example, to find out whether or not daylight savings time is in
  335. X+ effect in June, 2077, the year is "folded back" to 2010, because both
  336. X+ years begin on a Monday, and both are non-leapyears.  The rules for
  337. X+ daylight savings time are thus presumed to be identical for both
  338. X+ years, and the Unix library functions can handle 2010.  By default,
  339. X+ this variable is 0.  Set it to 1 if the sun or UTC functions misbehave
  340. X+ for years greater than 2037.
  341. X+ .TP
  342. X+ .B $HushMode (read-only)
  343. X+ If non-zero, then the \fB\-h\fR option was supplied on the command line.
  344. X+ .TP
  345. X+ .B $IgnoreOnce (read-only)
  346. X+ If non-zero, then the \fB\-o\fR option was supplied on the command line,
  347. X+ or a date different from today's true date was supplied.  If non-zero,
  348. X+ then \fBONCE\fR directives will be ignored.
  349. X+ .TP
  350. X+ .B $InfDelta (read-only)
  351. X+ If non-zero, then the \fB\-t\fR option was supplied on the command line.
  352. X+ .TP
  353. X+ .B $LatDeg, $LatMin, $LatSec
  354. X+ These specify the latitude of your location.  \fB$LatDeg\fR can
  355. X+ range from -90 to 90, and the others from -59 to 59.  Northern latitudes
  356. X+ are positive; southern ones are negative.  For southern latitudes, all
  357. X+ three components should be negative.
  358. X+ .TP
  359. X+ .B $LongDeg, $LongMin, $LongSec
  360. X+ These specify the longitude of your location.  \fB$LongDeg\fR can
  361. X+ range from -180 to 180.  Western longitudes are positive; eastern
  362. X+ ones are negative.
  363. X+ .RS
  364. X+ .PP
  365. X+ The latitude and longitude information is required for the functions
  366. X+ \fBsunrise()\fR and \fBsunset()\fR.  Default values can be compiled
  367. X+ into \fBRemind\fR, or you can \fBSET\fR the correct values at the
  368. X+ start of your reminder scripts.
  369. X+ .RE
  370. X+ .TP
  371. X+ .B $MaxSatIter
  372. X+ The maximum number of iterations for the \fBSATISFY\fR clause
  373. X+ (described later.)  Must be at least 10.
  374. X+ .TP
  375. X+ .B $MinsFromUTC
  376. X+ The number of minutes between Universal Time and local time.  If
  377. X+ \fB$CalcUTC\fR is non-zero, this is calculated upon startup of \fBRemind\fR.
  378. X+ Otherwise, you must set it explicitly.  If \fB$CalcUTC\fR is zero,
  379. X+ then \fB$MinsFromUTC\fR is used in the astronomical calculations.  You
  380. X+ must adjust it for daylight savings time yourself.  Also, if you
  381. X+ want to initialize \fB$MinsFromUTC\fR
  382. X+ using the \fB\-i\fR command-line option, you
  383. X+ must also set \fB$CalcUTC\fR to 0 with the \fB\-i\fR option.
  384. X+ .TP
  385. X+ .B $NextMode (read-only)
  386. X+ If non-zero, then the \fB\-n\fR option was supplied on the command line.
  387. X+ .TP
  388. X+ .B $NumQueued (read-only)
  389. X+ Contains the number of reminders queued so far for background
  390. X+ timed triggering.  For MS-DOS, always returns 0.
  391. X+ .TP
  392. X+ .B $NumTrig (read-only)
  393. X+ Contains the number of reminders triggered for the current date.  One
  394. X+ use for this variable is as follows:  Suppose you wish to shade in
  395. X+ the box of a PostScript calendar whenever a holiday is triggered.  You
  396. X+ could save the value of \fB$NumTrig\fR in a regular variable
  397. X+ prior to executing a block of
  398. X+ holiday reminders.  If the value of \fB$NumTrig\fR after the holiday
  399. X+ block is greater than the saved value, then at least one holiday
  400. X+ was triggered, and you can execute the command to shade in the
  401. X+ calendar box.  (See the section "Calendar Mode".)
  402. X+ .TP
  403. X+ .B $PSCal (read-only)
  404. X+ If non-zero, then the \fB\-p\fR option was supplied on the command line.
  405. X+ .TP
  406. X+ .B $RunOff (read-only)
  407. X+ If non-zero, the \fBRUN\fR directives are disabled.
  408. X+ .TP
  409. X+ .B $SimpleCal (read-only)
  410. X+ Set to a non-zero value if \fIeither\fR of the \fB\-p\fR or \fB\-s\fR
  411. X+ command-line options was supplied.
  412. X+ .PP
  413. X+ Note:  If any of the calendar modes are in effect, then the
  414. X+ values of $Daemon, $DontFork, $DontTrigAts, $DontQueue, $HushMode,
  415. X+ $IgnoreOnce, $InfDelta, and $NextMode are not meaningful.
  416. X+ .PP
  417. X  .B BUILT-IN FUNCTIONS
  418. X  .PP
  419. X  \fBRemind\fR has a plethora of built-in functions.  The syntax for a function
  420. X***************
  421. X*** 1596,1601 ****
  422. X--- 1736,1761 ----
  423. X  \fBRemind\fR.
  424. X  .RE
  425. X  .TP
  426. X+ .B easterdate(di_arg)
  427. X+ If \fIarg\fR is an \fBINT\fR, then returns the date of Easter Sunday
  428. X+ for the specified year.  If \fIarg\fR is a \fBDATE\fR, then returns the
  429. X+ date of the next Easter Sunday on or after \fIarg\fR.
  430. X+ .TP
  431. X+ .B filedir()
  432. X+ Returns the directory which contains the current file being
  433. X+ processed.  It may be a relative or absolute pathname, but
  434. X+ is guaranteed to be correct for use in an \fBINCLUDE\fR command as
  435. X+ follows:
  436. X+ .PP
  437. X+ .nf
  438. X+         INCLUDE [filedir()]/stuff
  439. X+ .fi
  440. X+ .PP
  441. X+ .RS
  442. X+ This includes the file "stuff" in the same directory as the
  443. X+ current file being processed.
  444. X+ .RE
  445. X+ .TP
  446. X  .B filename()
  447. X  Returns (as a \fBSTRING\fR) the name of the current file being processed
  448. X  by \fBRemind\fR.  Inside included files, returns the name of the
  449. X***************
  450. X*** 1630,1635 ****
  451. X--- 1790,1805 ----
  452. X  \fIsearch\fR at which to start looking for \fItarget\fR.
  453. X  .RE
  454. X  .TP
  455. X+ .B isdst([d_date [,t_time]])
  456. X+ Returns a positive number if daylight savings time is in
  457. X+ effect on the specified date and time.  \fIDate\fR
  458. X+ defaults to \fBtoday()\fR and \fItime\fR defaults to midnight.
  459. X+ .RS
  460. X+ .PP
  461. X+ Note that this function is only as reliable as the C run-time library
  462. X+ functions.  It is available starting with version 03.00.07 of \fBRemind\fR.
  463. X+ .RE
  464. X+ .TP
  465. X  .B isleap(id_arg)
  466. X  Returns 1 if \fIarg\fR is a leap year, and 0 otherwise.  \fIArg\fR can
  467. X  be either an \fBINT\fR or a \fBDATE\fR object.  If a \fBDATE\fR is
  468. X***************
  469. X*** 1639,1645 ****
  470. X  Returns 1 if \fIdate\fR is omitted, given the current global \fBOMIT\fR
  471. X  context.  Returns 0 otherwise.
  472. X  .TP
  473. X! .B hebdate(i_day, s_hebmon [,id_yrstart [,i_jahrflag]])
  474. X  Support for Hebrew dates - see the section "The Hebrew Calendar"
  475. X  .TP
  476. X  .B hebday(d_date)
  477. X--- 1809,1815 ----
  478. X  Returns 1 if \fIdate\fR is omitted, given the current global \fBOMIT\fR
  479. X  context.  Returns 0 otherwise.
  480. X  .TP
  481. X! .B hebdate(i_day, s_hebmon [,id_yrstart [,i_jahr [,i_aflag]]])
  482. X  Support for Hebrew dates - see the section "The Hebrew Calendar"
  483. X  .TP
  484. X  .B hebday(d_date)
  485. X***************
  486. X*** 1648,1654 ****
  487. X  .B hebmon(d_date)
  488. X  Support for Hebrew dates - see the section "The Hebrew Calendar"
  489. X  .TP
  490. X! .Bhebyear(d_date)
  491. X  Support for Hebrew dates - see the section "The Hebrew Calendar"
  492. X  .TP
  493. X  .B language()
  494. X--- 1818,1824 ----
  495. X  .B hebmon(d_date)
  496. X  Support for Hebrew dates - see the section "The Hebrew Calendar"
  497. X  .TP
  498. X! .B hebyear(d_date)
  499. X  Support for Hebrew dates - see the section "The Hebrew Calendar"
  500. X  .TP
  501. X  .B language()
  502. X***************
  503. X*** 1673,1678 ****
  504. X--- 1843,1860 ----
  505. X  can be of any type, but must all be of the same type.  They are compared
  506. X  as with the < operator.
  507. X  .TP
  508. X+ .B minsfromutc([d_date [,t_time]])
  509. X+ Returns the number of minutes from Universal Time (formerly GMT) to
  510. X+ local time on the specified date and time.  \fIDate\fR defaults to
  511. X+ \fBtoday()\fR and \fItime\fR defaults to midnight.  If local time
  512. X+ is before UT, the result is negative.  Otherwise, the result is
  513. X+ positive.
  514. X+ .RS
  515. X+ .PP
  516. X+ Note that this function is only as reliable as the C run-time library
  517. X+ functions.  It is available starting with version 03.00.07 of \fBRemind\fR.
  518. X+ .RE
  519. X+ .TP
  520. X  .B minute(t_time)
  521. X  Returns the minute component of \fItime\fR.
  522. X  .TP
  523. X***************
  524. X*** 1735,1740 ****
  525. X--- 1917,1945 ----
  526. X  from 1.  If \fIend\fR is not supplied, then it defaults to the length
  527. X  of \fIstr\fR.
  528. X  .TP
  529. X+ .B sunrise([d_date])
  530. X+ Returns a \fBTIME\fR indicating the time of sunrise on the specified
  531. X+ \fIdate\fR (default \fBtoday()\fR.)  In high lattitudes, there
  532. X+ may be no sunrise on a particular day, in which case \fBsunrise()\fR
  533. X+ returns the \fBINT\fR 0.
  534. X+ .TP
  535. X+ .B sunset([d_date])
  536. X+ Returns a \fBTIME\fR indicating the time of sunset on the specified
  537. X+ \fIdate\fR (default \fBtoday()\fR.)  In high lattitudes, there
  538. X+ may be no sunset on a particular day, in which case \fBsunset()\fR
  539. X+ returns the \fBINT\fR 0.
  540. X+ .RS
  541. X+ .PP
  542. X+ The functions \fBsunrise()\fR and \fBsunset()\fR are based on
  543. X+ an algorithm in "Almanac for Computers for the year 1978" by
  544. X+ L. E. Doggett, Nautical Almanac Office, USNO.  They require
  545. X+ the latitude and longitude to be specified by setting the appropriate
  546. X+ system variables.  (See "System Variables".)  The sun functions
  547. X+ should be accurate to within about 2 minutes for latitudes lower
  548. X+ than 60 degrees.  The functions are available starting from version
  549. X+ 03.00.07 of \fBRemind\fR.
  550. X+ .RE
  551. X+ .TP
  552. X  .B time(i_hr, i_min)
  553. X  Creates a \fBTIME\fR with the hour and minute components specified by
  554. X  \fIhr\fR and \fImin\fR.
  555. X***************
  556. X*** 2126,2131 ****
  557. X--- 2331,2365 ----
  558. X  It is probably best to stay away from computing \fBOMIT\fR
  559. X  trigger dates unless you keep these pitfalls in mind.
  560. X  .PP
  561. X+ For versions of \fBRemind\fR starting from 03.00.07, you can include
  562. X+ a \fBMSG\fR, \fBRUN\fR, etc. clause in a \fBSATISFY\fR clause as
  563. X+ follows:
  564. X+ .PP
  565. X+ .nf
  566. X+     REM trigger_stuff SATISFY [expr] MSG body
  567. X+ .fi
  568. X+ .PP
  569. X+ Note that for this case only, the \fIexpr\fR after \fBSATISFY\fR
  570. X+ \fImust\fR be enclosed in braces.  It must come after all the other
  571. X+ components of the trigger, and immediately before the \fBMSG\fR,
  572. X+ \fBRUN\fR, etc. keyword.  If \fIexpr\fR cannot be satisfied, then
  573. X+ the reminder is not triggered.
  574. X+ .PP
  575. X+ Thus, the "Friday the 13th" example can be expressed more compactly as:
  576. X+ .PP
  577. X+ .nf
  578. X+     REM 13 +2 SATISFY [wkdaynum(trigdate()) == 5] \\
  579. X+         MSG Friday the 13th is %b.
  580. X+ .fi
  581. X+ .PP
  582. X+ And you can trigger a reminder on Mondays, Wednesdays and Thursdays
  583. X+ occurring on odd-numbered days of the month with the following:
  584. X+ .PP
  585. X+ .nf
  586. X+     REM Mon Wed Thu SATISFY [day(trigdate())%2] \\
  587. X+         MSG Here it is!!!
  588. X+ .fi
  589. X+ .PP
  590. X  .SH DEBUGGING REMINDER SCRIPTS
  591. X  .PP
  592. X  Although the command-line \fB\-d\fR option is useful for debugging, it
  593. X***************
  594. X*** 2157,2163 ****
  595. X  .PP
  596. X  If you supply a space-separated list of variable names, the corresponding
  597. X  variables are displayed.  If you do not supply a list of variables, then
  598. X! all variables in memory are displayed.
  599. X  .PP
  600. X  .B THE ERRMSG COMMAND
  601. X  .PP
  602. X--- 2391,2400 ----
  603. X  .PP
  604. X  If you supply a space-separated list of variable names, the corresponding
  605. X  variables are displayed.  If you do not supply a list of variables, then
  606. X! all variables in memory are displayed.  To dump a system variable,
  607. X! put its name in the list of variables to dump.  If you put a lone
  608. X! dollar sign in the list of variables to dump, then all system variables
  609. X! will be dumped.
  610. X  .PP
  611. X  .B THE ERRMSG COMMAND
  612. X  .PP
  613. X***************
  614. X*** 2547,2553 ****
  615. X  Returns the Hebrew year corresponding to \fIdate\fR.  For example,
  616. X  hebyear('1993/04/12') returns 5753.
  617. X  .TP
  618. X! .B hebdate(i_day, s_hebmon [,id_yrstart [,i_jahrflag]])
  619. X  The \fBhebdate()\fR function is the most complex of the Hebrew support
  620. X  functions.  It can take from 2 to 4 arguments.  It returns a \fBDATE\fR
  621. X  corresponding to the Hebrew date.
  622. X--- 2784,2790 ----
  623. X  Returns the Hebrew year corresponding to \fIdate\fR.  For example,
  624. X  hebyear('1993/04/12') returns 5753.
  625. X  .TP
  626. X! .B hebdate(i_day, s_hebmon [,id_yrstart [,i_jahr [,i_aflag]]])
  627. X  The \fBhebdate()\fR function is the most complex of the Hebrew support
  628. X  functions.  It can take from 2 to 4 arguments.  It returns a \fBDATE\fR
  629. X  corresponding to the Hebrew date.
  630. X***************
  631. X*** 2582,2590 ****
  632. X  .PP
  633. X  If \fIyrstart\fR is not supplied, it defaults to \fBtoday()\fR.
  634. X  .PP
  635. X! The \fIjahrflag\fR modifies the behaviour of \fBhebdate()\fR as follows:
  636. X  .PP
  637. X! If \fIjahrflag\fR is 0 (the default),
  638. X  then \fBhebdate()\fR keeps scanning until it
  639. X  finds a date which exactly satisfies the other parameters.  For example:
  640. X  .PP
  641. X--- 2819,2827 ----
  642. X  .PP
  643. X  If \fIyrstart\fR is not supplied, it defaults to \fBtoday()\fR.
  644. X  .PP
  645. X! The \fIjahr\fR modifies the behaviour of \fBhebdate()\fR as follows:
  646. X  .PP
  647. X! If \fIjahr\fR is 0 (the default),
  648. X  then \fBhebdate()\fR keeps scanning until it
  649. X  finds a date which exactly satisfies the other parameters.  For example:
  650. X  .PP
  651. X***************
  652. X*** 2596,2602 ****
  653. X  next occurrence of 30 Adar A after 1 January, 1993.  This behaviour is
  654. X  appropriate for Purim Katan, which only appears in leap years.
  655. X  .PP
  656. X! If \fIjahrflag\fR is 1, then the date is modified as follows:
  657. X  .TP
  658. X  o
  659. X  30 Heshvan is converted to 1 Kislev in years when Heshvan is chaser
  660. X--- 2833,2839 ----
  661. X  next occurrence of 30 Adar A after 1 January, 1993.  This behaviour is
  662. X  appropriate for Purim Katan, which only appears in leap years.
  663. X  .PP
  664. X! If \fIjahr\fR is 1, then the date is modified as follows:
  665. X  .TP
  666. X  o
  667. X  30 Heshvan is converted to 1 Kislev in years when Heshvan is chaser
  668. X***************
  669. X*** 2614,2620 ****
  670. X  This behaviour is appropriate for smachot (joyous occasions) and for
  671. X  some jahrzeits - see "JAHRZEITS."
  672. X  .PP
  673. X! if \fIjahrflag\fR is 2, then the date is modified as follows:
  674. X  .TP
  675. X  o
  676. X  30 Kislev and 30 Heshvan are converted to 29 Kislev and 29 Heshvan,
  677. X--- 2851,2857 ----
  678. X  This behaviour is appropriate for smachot (joyous occasions) and for
  679. X  some jahrzeits - see "JAHRZEITS."
  680. X  .PP
  681. X! if \fIjahr\fR is 2, then the date is modified as follows:
  682. X  .TP
  683. X  o
  684. X  30 Kislev and 30 Heshvan are converted to 29 Kislev and 29 Heshvan,
  685. X***************
  686. X*** 2627,2635 ****
  687. X  Other dates in Adar A are moved to the corresponding day in Adar in
  688. X  non-leapyears
  689. X  .PP
  690. X! if \fIjahrflag\fR is not 0, 1, or 2, it is interpreted as a Hebrew year,
  691. X  and the behaviour is calculated as described in the next section,
  692. X  "JAHRZEITS."
  693. X  .RE
  694. X  .PP
  695. X  .B JAHRZEITS
  696. X--- 2864,2894 ----
  697. X  Other dates in Adar A are moved to the corresponding day in Adar in
  698. X  non-leapyears
  699. X  .PP
  700. X! if \fIjahr\fR is not 0, 1, or 2, it is interpreted as a Hebrew year,
  701. X  and the behaviour is calculated as described in the next section,
  702. X  "JAHRZEITS."
  703. X+ .PP
  704. X+ The \fIaflag\fR parameter modifies the behaviour of the function for
  705. X+ dates in Adar during leap years.  The \fIaflag\fR is \fIonly\fR used
  706. X+ if \fIyrstart\fR is a \fBDATE\fR type (or is omitted, defaulting to
  707. X+ \fBtoday()\fR.)
  708. X+ .PP
  709. X+ The \fIaflag\fR only affects date calculations if \fIhebmon\fR is
  710. X+ specified as "Adar".  In leap years, the following algorithm is followed:
  711. X+ .TP
  712. X+ o
  713. X+ If \fIaflag\fR is 0, then the date is triggered in Adar B.  This is
  714. X+ the default.
  715. X+ .TP
  716. X+ o
  717. X+ If \fIaflag\fR is 1, then the date is triggered in Adar A.  This may
  718. X+ be appropriate for jahrzeits in the Ashkenazi tradition; consult a
  719. X+ rabbi.
  720. X+ .TP
  721. X+ o
  722. X+ If \fIaflag\fR is 2, then the date is triggered in both Adar A and Adar
  723. X+ B of a leap year.  Some Ashkenazim perform jahrzeit in both Adar A and
  724. X+ Adar B.
  725. X  .RE
  726. X  .PP
  727. X  .B JAHRZEITS
  728. X***************
  729. X*** 2661,2669 ****
  730. X  If the death occurred on 30 Adar A, it is observed on 30 Shvat in a
  731. X  non-leapyear.
  732. X  .PP
  733. X! Specifying a Hebrew year for the \fIjahrflag\fR parameter causes the
  734. X! correct behaviour to be selected for a death in that year.
  735. X  .PP
  736. X  .SH MISCELLANEOUS
  737. X  .PP
  738. X  .B COMMAND ABBREVIATIONS
  739. X--- 2920,2933 ----
  740. X  If the death occurred on 30 Adar A, it is observed on 30 Shvat in a
  741. X  non-leapyear.
  742. X  .PP
  743. X! Specifying a Hebrew year for the \fIjahr\fR parameter causes the
  744. X! correct behaviour to be selected for a death in that year.  You may
  745. X! also have to specify \fIaflag\fR, depending on your tradition.
  746. X  .PP
  747. X+ The jahrzeit information was supplied by Frank Yellin, who quoted
  748. X+ "The Comprehensive Hebrew Calendar" by Arthur Spier, and "Calendrical
  749. X+ Calculations" by E. M. Reingold and Nachum Dershowitz.
  750. X+ .PP
  751. X  .SH MISCELLANEOUS
  752. X  .PP
  753. X  .B COMMAND ABBREVIATIONS
  754. X***************
  755. X*** 2840,2846 ****
  756. X--- 3104,3116 ----
  757. X  David F. Skoll
  758. X  .SH BUGS
  759. X  .PP
  760. X+ There's no good reason why read-only system variables are not
  761. X+ implemented as functions, or why functions like \fBversion()\fR, etc.
  762. X+ are not implemented as read-only system variables.
  763. X+ .PP
  764. X  Hebrew dates change at midnight, not sunset.
  765. X+ .PP
  766. X+ The UTC functions are not reliable under MS-DOS.
  767. X  .PP
  768. X  The MS-DOS and OS/2 versions of \fBRemind\fR do not support queuing or timed
  769. X  activation of reminders.
  770. X*** ../p6/test-rem    Thu Apr 22 10:24:17 1993
  771. X--- ./test-rem    Mon Jun 28 12:30:08 1993
  772. X***************
  773. X*** 11,17 ****
  774. X  # ---------------------------------------------------------------------------
  775. X  
  776. X  TEST_GETENV="foo bar baz" ; export TEST_GETENV
  777. X! ./remind -e -dxtev ./test.rem 16 feb 1991 > ./test.out
  778. X  cmp -s ./test.out ./test.cmp
  779. X  if [ "$?" = "0" ]; then
  780. X     echo "Remind:  Acceptance test PASSED"
  781. X--- 11,17 ----
  782. X  # ---------------------------------------------------------------------------
  783. X  
  784. X  TEST_GETENV="foo bar baz" ; export TEST_GETENV
  785. X! ./remind -e -dxte ./test.rem 16 feb 1991 > ./test.out
  786. X  cmp -s ./test.out ./test.cmp
  787. X  if [ "$?" = "0" ]; then
  788. X     echo "Remind:  Acceptance test PASSED"
  789. X*** ../p6/test.cmp    Fri Apr 23 12:59:58 1993
  790. X--- ./test.cmp    Mon Jun 28 12:30:09 1993
  791. X***************
  792. X*** 631,637 ****
  793. X  "a05" + "6" => "a056"
  794. X  value("a056") => "SDFJHSDF KSJDFH KJSDFH KSJDFH"
  795. X  set a058 version()
  796. X! version() => "03.00.06"
  797. X  set a059 wkday(today())
  798. X  today() => 1991/02/16
  799. X  wkday(1991/02/16) => "Saturday"
  800. X--- 631,637 ----
  801. X  "a05" + "6" => "a056"
  802. X  value("a056") => "SDFJHSDF KSJDFH KJSDFH KSJDFH"
  803. X  set a058 version()
  804. X! version() => "03.00.07"
  805. X  set a059 wkday(today())
  806. X  today() => 1991/02/16
  807. X  wkday(1991/02/16) => "Saturday"
  808. X***************
  809. X*** 712,723 ****
  810. X  "foo" * 11:33 => Type mismatch
  811. X  ./test.rem(240): Operator '*' Type mismatch
  812. X  Leaving UserFN h() => Type mismatch
  813. X! 
  814. X      Variable  Value
  815. X  
  816. X          a017  29
  817. X          a036  "bar"
  818. X          a055  1
  819. X          a008  "11:44"
  820. X          a027  0
  821. X          a046  "ies"
  822. X--- 712,758 ----
  823. X  "foo" * 11:33 => Type mismatch
  824. X  ./test.rem(240): Operator '*' Type mismatch
  825. X  Leaving UserFN h() => Type mismatch
  826. X! set a074 dosubst("%a %b %c %d %e %f %g %h", '1992/5/5')
  827. X! dosubst("%a %b %c %d %e %f %g %h", 1992/05/05) => "on Tuesday, 5 May, 1992 in 444 days' tim"...
  828. X! msg [a074]%
  829. X! ./test.rem(242): Trig = Saturday, 16 February, 1991
  830. X! a074 => "on Tuesday, 5 May, 1992 in 444 days' tim"...
  831. X! on Tuesday, 5 May, 1992 in 444 days' time on Tuesday 5 on 05/05/1992 on 05/05/1992 on Tuesday, 5 May on 05/05
  832. X! set a075 dosubst("%i %j %k %l %m %n %o %p", '1992/5/5')
  833. X! dosubst("%i %j %k %l %m %n %o %p", 1992/05/05) => "on 05/05 on Tuesday, May 5th, 1992 on Tu"...
  834. X! msg [a075]%
  835. X! ./test.rem(244): Trig = Saturday, 16 February, 1991
  836. X! a075 => "on 05/05 on Tuesday, May 5th, 1992 on Tu"...
  837. X! on 05/05 on Tuesday, May 5th, 1992 on Tuesday, May 5th on 1992/05/05 May 5  s
  838. X! set a076 dosubst("%q %r %s %t %u %v %w %x", '1992/5/5')
  839. X! dosubst("%q %r %s %t %u %v %w %x", 1992/05/05) => "s' 05 th 05 on Tuesday, 5th May, 1992 on"...
  840. X! msg [a076]%
  841. X! ./test.rem(246): Trig = Saturday, 16 February, 1991
  842. X! a076 => "s' 05 th 05 on Tuesday, 5th May, 1992 on"...
  843. X! s' 05 th 05 on Tuesday, 5th May, 1992 on Tuesday, 5th May Tuesday 444
  844. X! set a077 dosubst("%y %z", '1992/5/5')
  845. X! dosubst("%y %z", 1992/05/05) => "1992 92
  846. X! "
  847. X! msg [a077]%
  848. X! ./test.rem(248): Trig = Saturday, 16 February, 1991
  849. X! a077 => "1992 92
  850. X! "
  851. X! 1992 92
  852. X! set a078 easterdate(today())
  853. X! today() => 1991/02/16
  854. X! easterdate(1991/02/16) => 1991/03/31
  855. X! set a079 easterdate(1992)
  856. X! easterdate(1992) => 1992/04/19
  857. X! set a080 easterdate(1995)
  858. X! easterdate(1995) => 1995/04/16
  859. X! set a081 ""
  860. X! dump
  861. X      Variable  Value
  862. X  
  863. X          a017  29
  864. X          a036  "bar"
  865. X          a055  1
  866. X+         a074  "on Tuesday, 5 May, 1992 in 444 days' tim"...
  867. X          a008  "11:44"
  868. X          a027  0
  869. X          a046  "ies"
  870. X***************
  871. X*** 725,730 ****
  872. X--- 760,766 ----
  873. X          a018  1
  874. X          a037  1991/02/15
  875. X          a056  "SDFJHSDF KSJDFH KJSDFH KSJDFH"
  876. X+         a075  "on 05/05 on Tuesday, May 5th, 1992 on Tu"...
  877. X          a028  1
  878. X          a047  -1
  879. X          a066  0
  880. X***************
  881. X*** 731,745 ****
  882. X          a019  0
  883. X          a038  33
  884. X          a057  "SDFJHSDF KSJDFH KJSDFH KSJDFH"
  885. X          a029  0
  886. X          a048  "foo"
  887. X          a067  "INT"
  888. X          a039  "February"
  889. X!         a058  "03.00.06"
  890. X          a049  21
  891. X          a068  "STRING"
  892. X          a059  "Saturday"
  893. X          a069  "TIME"
  894. X          a000  1
  895. X          a010  12
  896. X          a001  1
  897. X--- 767,786 ----
  898. X          a019  0
  899. X          a038  33
  900. X          a057  "SDFJHSDF KSJDFH KJSDFH KSJDFH"
  901. X+         a076  "s' 05 th 05 on Tuesday, 5th May, 1992 on"...
  902. X          a029  0
  903. X          a048  "foo"
  904. X          a067  "INT"
  905. X          a039  "February"
  906. X!         a058  "03.00.07"
  907. X!         a077  "1992 92
  908. X! "
  909. X          a049  21
  910. X          a068  "STRING"
  911. X          a059  "Saturday"
  912. X+         a078  1991/03/31
  913. X          a069  "TIME"
  914. X+         a079  1992/04/19
  915. X          a000  1
  916. X          a010  12
  917. X          a001  1
  918. X***************
  919. X*** 762,767 ****
  920. X--- 803,809 ----
  921. X          a023  1
  922. X          a042  "4th"
  923. X          a061  1991
  924. X+         a080  1995/04/16
  925. X          a033  "foo"
  926. X          a052  03:07
  927. X          a071  2
  928. X***************
  929. X*** 769,774 ****
  930. X--- 811,817 ----
  931. X          a024  0
  932. X          a043  "UNIX"
  933. X          a062  -19
  934. X+         a081  ""
  935. X          a015  16
  936. X          a034  1991/02/17
  937. X          a053  1992/01/10
  938. X***************
  939. X*** 784,786 ****
  940. X--- 827,830 ----
  941. X          a026  7
  942. X          a045  "iess"
  943. X          a064  1
  944. X+ 
  945. X*** ../p6/test.rem    Thu Apr 22 10:24:19 1993
  946. X--- ./test.rem    Mon Jun 28 12:30:07 1993
  947. X***************
  948. X*** 238,240 ****
  949. X--- 238,253 ----
  950. X  set a071 g(1, 2)
  951. X  set a072 h(2, 3)
  952. X  set a073 h("foo", 11:33)
  953. X+ set a074 dosubst("%a %b %c %d %e %f %g %h", '1992/5/5')
  954. X+ msg [a074]%
  955. X+ set a075 dosubst("%i %j %k %l %m %n %o %p", '1992/5/5')
  956. X+ msg [a075]%
  957. X+ set a076 dosubst("%q %r %s %t %u %v %w %x", '1992/5/5')
  958. X+ msg [a076]%
  959. X+ set a077 dosubst("%y %z", '1992/5/5')
  960. X+ msg [a077]%
  961. X+ set a078 easterdate(today())
  962. X+ set a079 easterdate(1992)
  963. X+ set a080 easterdate(1995)
  964. X+ set a081 ""
  965. X+ dump
  966. X*** ../p6/trigger.c    Thu Apr 22 10:24:20 1993
  967. X--- ./trigger.c    Mon Jun 28 12:29:57 1993
  968. X***************
  969. X*** 143,149 ****
  970. X          if (JMonth(j) == trig->m) return j;
  971. X       }
  972. X       if (m >= trig->m) j = Julian(y+1, trig->m, 1);
  973. X!      else if (m < trig->m) j = Julian(y, trig->m, 1);
  974. X       while(! (trig->wd & (1 << (j%7)))) j++;
  975. X       return j; /* Guaranteed to be within the month */
  976. X  
  977. X--- 143,149 ----
  978. X          if (JMonth(j) == trig->m) return j;
  979. X       }
  980. X       if (m >= trig->m) j = Julian(y+1, trig->m, 1);
  981. X!      else j = Julian(y, trig->m, 1);
  982. X       while(! (trig->wd & (1 << (j%7)))) j++;
  983. X       return j; /* Guaranteed to be within the month */
  984. X  
  985. X*** ../p6/userfns.c    Thu Apr 22 10:24:21 1993
  986. X--- ./userfns.c    Mon Jun 28 12:38:47 1993
  987. X***************
  988. X*** 75,80 ****
  989. X--- 75,81 ----
  990. X  
  991. X     /* Get the function name */
  992. X     if ( (r=ParseIdentifier(p, TokBuffer)) ) return r;
  993. X+    if (*TokBuffer == '$') return E_BAD_ID;
  994. X  
  995. X     /* Should be followed by '(' */
  996. X     c = ParseNonSpaceChar(p, &r, 0);
  997. X***************
  998. X*** 108,113 ****
  999. X--- 109,115 ----
  1000. X     else {
  1001. X        while(1) {
  1002. X       if ( (r=ParseIdentifier(p, TokBuffer)) ) return r;
  1003. X+          if (*TokBuffer == '$') return E_BAD_ID;
  1004. X       v = NEW(Var);
  1005. X       func->nargs++;
  1006. X       v->v.type = ERR_TYPE;
  1007. X***************
  1008. X*** 211,217 ****
  1009. X     cur = FuncHash[h];
  1010. X     prev = NULL;
  1011. X     while(cur) {
  1012. X!       if (StrinEq(name, cur->name, VAR_NAME_LEN)) break;
  1013. X        prev = cur;
  1014. X        cur = cur->next;
  1015. X     }
  1016. X--- 213,219 ----
  1017. X     cur = FuncHash[h];
  1018. X     prev = NULL;
  1019. X     while(cur) {
  1020. X!       if (! StrinCmp(name, cur->name, VAR_NAME_LEN)) break;
  1021. X        prev = cur;
  1022. X        cur = cur->next;
  1023. X     }
  1024. X***************
  1025. X*** 261,267 ****
  1026. X  
  1027. X     /* Search for the function */
  1028. X     f = FuncHash[h];
  1029. X!    while (f && !StrinEq(name, f->name, VAR_NAME_LEN)) f = f->next;
  1030. X     if (!f) {
  1031. X        Eprint("Undefined function '%s'", name);
  1032. X        return E_UNDEF_FUNC;
  1033. X--- 263,269 ----
  1034. X  
  1035. X     /* Search for the function */
  1036. X     f = FuncHash[h];
  1037. X!    while (f && StrinCmp(name, f->name, VAR_NAME_LEN)) f = f->next;
  1038. X     if (!f) {
  1039. X        Eprint("Undefined function '%s'", name);
  1040. X        return E_UNDEF_FUNC;
  1041. X***************
  1042. X*** 391,397 ****
  1043. X     int h = HashVal(fn) % FUNC_HASH_SIZE;
  1044. X  
  1045. X     f = FuncHash[h];
  1046. X!    while (f && !StrinEq(fn, f->name, VAR_NAME_LEN)) f = f->next;
  1047. X     if (!f) return -1;
  1048. X     else return f->nargs;
  1049. X  }
  1050. X--- 393,399 ----
  1051. X     int h = HashVal(fn) % FUNC_HASH_SIZE;
  1052. X  
  1053. X     f = FuncHash[h];
  1054. X!    while (f && StrinCmp(fn, f->name, VAR_NAME_LEN)) f = f->next;
  1055. X     if (!f) return -1;
  1056. X     else return f->nargs;
  1057. X  }
  1058. X*** ../p6/utils.c    Thu Apr 22 10:24:22 1993
  1059. X--- ./utils.c    Mon Jun 28 12:37:05 1993
  1060. X***************
  1061. X*** 25,94 ****
  1062. X  
  1063. X  /***************************************************************/
  1064. X  /*                                                             */
  1065. X- /*  StrEq                                                      */
  1066. X- /*                                                             */
  1067. X- /*  Are two strings equal?                                     */
  1068. X- /*                                                             */
  1069. X- /***************************************************************/
  1070. X- #ifdef HAVE_PROTOS
  1071. X- PUBLIC int StrEq(const char *s1, const char *s2)
  1072. X- #else
  1073. X- int StrEq(s1, s2)
  1074. X- char *s1, *s2;
  1075. X- #endif
  1076. X- {
  1077. X-    while (*s1 && *s2) {
  1078. X-       if (*s1++ != *s2++) return 0;
  1079. X-    }
  1080. X-    if (*s1 || *s2) return 0 ; else return 1;
  1081. X- }
  1082. X- 
  1083. X- /***************************************************************/
  1084. X- /*                                                             */
  1085. X- /*  StriEq                                                     */
  1086. X- /*                                                             */
  1087. X- /*  Are two strings equal, ignoring case?                      */
  1088. X- /*                                                             */
  1089. X- /***************************************************************/
  1090. X- #ifdef HAVE_PROTOS
  1091. X- PUBLIC int StriEq(const char *s1, const char *s2)
  1092. X- #else
  1093. X- int StriEq(s1, s2)
  1094. X- char *s1, *s2;
  1095. X- #endif
  1096. X- {
  1097. X-    while (*s1 && *s2) {
  1098. X-       if (UPPER(*s1) != UPPER(*s2)) return 0;
  1099. X-       s1++;
  1100. X-       s2++;
  1101. X-    }
  1102. X-    if (*s1 || *s2) return 0 ; else return 1;
  1103. X- }
  1104. X- 
  1105. X- /***************************************************************/
  1106. X- /*                                                             */
  1107. X- /*  StrinEq                                                    */
  1108. X- /*  Are two strings equal to a given number of chars?          */
  1109. X- /*                                                             */
  1110. X- /***************************************************************/
  1111. X- #ifdef HAVE_PROTOS
  1112. X- PUBLIC int StrinEq(const char *s1, const char *s2, int n)
  1113. X- #else
  1114. X- int StrinEq(s1, s2, n)
  1115. X- char *s1, *s2;
  1116. X- int n;
  1117. X- #endif
  1118. X- {
  1119. X-    while (*s1 && *s2 && n--) {
  1120. X-       if (UPPER(*s1) != UPPER(*s2)) return 0;
  1121. X-       s1++;
  1122. X-       s2++;
  1123. X-    }
  1124. X-    if (n && (*s1 || *s2)) return 0 ; else return 1;
  1125. X- }
  1126. X- 
  1127. X- /***************************************************************/
  1128. X- /*                                                             */
  1129. X  /*  StrnCpy                                                    */
  1130. X  /*                                                             */
  1131. X  /*  Just like strncpy EXCEPT we ALWAYS copy the trailing 0.    */
  1132. X--- 25,30 ----
  1133. X***************
  1134. X*** 128,134 ****
  1135. X  {
  1136. X     int l;
  1137. X     if ((l = strlen(s1)) < n) return 0;
  1138. X!    return StrinEq(s1, s2, l);
  1139. X  }
  1140. X  
  1141. X  /***************************************************************/
  1142. X--- 64,70 ----
  1143. X  {
  1144. X     int l;
  1145. X     if ((l = strlen(s1)) < n) return 0;
  1146. X!    return !StrinCmp(s1, s2, l);
  1147. X  }
  1148. X  
  1149. X  /***************************************************************/
  1150. X*** ../p6/var.c    Thu Apr 22 10:24:22 1993
  1151. X--- ./var.c    Mon Jul 19 10:58:54 1993
  1152. X***************
  1153. X*** 81,87 ****
  1154. X     prev = NULL;
  1155. X  
  1156. X     while(v) {
  1157. X!       if (StrinEq(str, v->name, VAR_NAME_LEN)) return v;
  1158. X        prev = v;
  1159. X        v = v-> next;
  1160. X     }
  1161. X--- 81,87 ----
  1162. X     prev = NULL;
  1163. X  
  1164. X     while(v) {
  1165. X!       if (! StrinCmp(str, v->name, VAR_NAME_LEN)) return v;
  1166. X        prev = v;
  1167. X        v = v-> next;
  1168. X     }
  1169. X***************
  1170. X*** 123,129 ****
  1171. X     prev = NULL;
  1172. X  
  1173. X     while(v) {
  1174. X!       if (StrinEq(str, v->name, VAR_NAME_LEN)) break;
  1175. X        prev = v;
  1176. X        v = v-> next;
  1177. X     }
  1178. X--- 123,129 ----
  1179. X     prev = NULL;
  1180. X  
  1181. X     while(v) {
  1182. X!       if (! StrinCmp(str, v->name, VAR_NAME_LEN)) break;
  1183. X        prev = v;
  1184. X        v = v-> next;
  1185. X     }
  1186. X***************
  1187. X*** 179,185 ****
  1188. X     /* Try searching local variables first */
  1189. X     v = locals;
  1190. X     while (v) {
  1191. X!       if (StrinEq(str, v->name, VAR_NAME_LEN))
  1192. X       return CopyValue(val, &v->v);
  1193. X        v = v->next;
  1194. X     }
  1195. X--- 179,185 ----
  1196. X     /* Try searching local variables first */
  1197. X     v = locals;
  1198. X     while (v) {
  1199. X!       if (! StrinCmp(str, v->name, VAR_NAME_LEN))
  1200. X       return CopyValue(val, &v->v);
  1201. X        v = v->next;
  1202. X     }
  1203. X***************
  1204. X*** 214,222 ****
  1205. X     r = EvaluateExpr(p, &v);
  1206. X     if (r) return r;
  1207. X  
  1208. X!    r = SetVar(TokBuffer, &v);
  1209. X! 
  1210. X!    return r;
  1211. X  }
  1212. X  
  1213. X  /***************************************************************/
  1214. X--- 214,224 ----
  1215. X     r = EvaluateExpr(p, &v);
  1216. X     if (r) return r;
  1217. X  
  1218. X!    if (*TokBuffer == '$') {
  1219. X!       if (v.type != INT_TYPE) return E_BAD_TYPE;
  1220. X!       return SetSysVar(TokBuffer+1, v.v.val);
  1221. X!    }
  1222. X!    return SetVar(TokBuffer, &v);
  1223. X  }
  1224. X  
  1225. X  /***************************************************************/
  1226. X***************
  1227. X*** 273,285 ****
  1228. X     }
  1229. X     fprintf(ErrFp, "%*s  %s\n\n", VAR_NAME_LEN, "Variable", "Value");
  1230. X     while(1) {
  1231. X!       v = FindVar(TokBuffer, 0);
  1232. X!       TokBuffer[VAR_NAME_LEN] = 0;
  1233. X!       if (!v) fprintf(ErrFp, "%*s  *UNDEFINED*\n", VAR_NAME_LEN, TokBuffer);
  1234. X!       else {
  1235. X!          fprintf(ErrFp, "%*s  ", VAR_NAME_LEN, v->name);
  1236. X!          PrintValue(&(v->v), ErrFp);
  1237. X!      fprintf(ErrFp, "\n");
  1238. X        }
  1239. X        r = ParseToken(p, TokBuffer);
  1240. X        if (r) return r;
  1241. X--- 275,291 ----
  1242. X     }
  1243. X     fprintf(ErrFp, "%*s  %s\n\n", VAR_NAME_LEN, "Variable", "Value");
  1244. X     while(1) {
  1245. X!       if (*TokBuffer == '$') {
  1246. X!          DumpSysVarByName(TokBuffer+1);
  1247. X!       } else {
  1248. X!          v = FindVar(TokBuffer, 0);
  1249. X!          TokBuffer[VAR_NAME_LEN] = 0;
  1250. X!          if (!v) fprintf(ErrFp, "%*s  *UNDEFINED*\n", VAR_NAME_LEN, TokBuffer);
  1251. X!          else {
  1252. X!             fprintf(ErrFp, "%*s  ", VAR_NAME_LEN, v->name);
  1253. X!             PrintValue(&(v->v), ErrFp);
  1254. X!             fprintf(ErrFp, "\n");
  1255. X!          }
  1256. X        }
  1257. X        r = ParseToken(p, TokBuffer);
  1258. X        if (r) return r;
  1259. X***************
  1260. X*** 405,409 ****
  1261. X--- 411,611 ----
  1262. X        r = PreserveVar(TokBuffer);
  1263. X        if (r) return r;
  1264. X     }
  1265. X+ }
  1266. X+ 
  1267. X+ /***************************************************************/
  1268. X+ /*                                                             */
  1269. X+ /*  SYSTEM VARIABLES                                           */
  1270. X+ /*                                                             */
  1271. X+ /*  Interface for modifying and reading system variables.      */
  1272. X+ /*                                                             */
  1273. X+ /*  All system variables are of type "INT".                    */
  1274. X+ /*                                                             */
  1275. X+ /***************************************************************/
  1276. X+ 
  1277. X+ /* The structure of a system variable */
  1278. X+ typedef struct {
  1279. X+    char *name;
  1280. X+    char modifiable;
  1281. X+    int *value;   
  1282. X+    int min;
  1283. X+    int max;
  1284. X+ } SysVar;
  1285. X+ 
  1286. X+ #define NO_CONSTRAINT 4532
  1287. X+ /* All of the system variables sorted alphabetically */
  1288. X+ static SysVar SysVarArr[] = {
  1289. X+        /* name          modifiable    value        min    max */
  1290. X+    {   "CalcUTC",      1,        &CalculateUTC,    0,    1   },
  1291. X+    {   "CalMode",      0,        &DoCalendar,    0,    0   },
  1292. X+    {   "Daemon",      0,        &Daemon,    0,    0   },
  1293. X+    {   "DontFork",      0,        &DontFork,    0,    0   },
  1294. X+    {   "DontQueue",      0,        &DontQueue,    0,    0   },
  1295. X+    {   "DontTrigAts",      0,        &DontIssueAts,    0,    0   },
  1296. X+    {   "FoldYear",      1,        &FoldYear,    0,    1   },
  1297. X+    {   "HushMode",      0,        &Hush,        0,    0   },
  1298. X+    {   "IgnoreOnce",      0,        &IgnoreOnce,    0,    0   },
  1299. X+    {   "InfDelta",      0,        &InfiniteDelta,    0,    0   },
  1300. X+    {   "LatDeg",      1,        &LatDeg,    -90,    90  },
  1301. X+    {   "LatMin",      1,        &LatMin,    -59,    59  },
  1302. X+    {   "LatSec",      1,        &LatSec,    -59,    59  },
  1303. X+    {   "LongDeg",      1,        &LongDeg,    -180,    180  },
  1304. X+    {   "LongMin",      1,        &LongMin,    -59,    59  },
  1305. X+    {   "LongSec",      1,        &LongSec,    -59,    59  },
  1306. X+    {   "MaxSatIter",      1,        &MaxSatIter,    10,    NO_CONSTRAINT },
  1307. X+    {   "MinsFromUTC",      1,        &MinsFromUTC,    -13*60,    13*60 },
  1308. X+    {   "NextMode",      0,        &NextMode,    0,    0   },
  1309. X+    {   "NumQueued",      0,        &NumQueued,    0,    0   },
  1310. X+    {   "NumTrig",      0,        &NumTriggered,    0,    0   },
  1311. X+    {   "PSCal",          0,        &PsCal,        0,    0   },
  1312. X+    {   "RunOff",      0,        &RunDisabled,    0,    0   },
  1313. X+    {   "SimpleCal",      0,        &DoSimpleCalendar,    0,  0 }
  1314. X+ };
  1315. X+ 
  1316. X+ #define NUMSYSVARS ( sizeof(SysVarArr) / sizeof(SysVar) )
  1317. X+ PRIVATE SysVar *FindSysVar ARGS((const char *name));
  1318. X+ PRIVATE void DumpSysVar ARGS((const char *name, const SysVar *v));
  1319. X+ /***************************************************************/
  1320. X+ /*                                                             */
  1321. X+ /*  SetSysVar                                                  */
  1322. X+ /*                                                             */
  1323. X+ /*  Set a system variable to the indicated value.              */
  1324. X+ /*                                                             */
  1325. X+ /***************************************************************/
  1326. X+ #ifdef HAVE_PROTOS
  1327. X+ PUBLIC int SetSysVar(const char *name, int value)
  1328. X+ #else
  1329. X+ int SetSysVar(name, value)
  1330. X+ char *name;
  1331. X+ int value;
  1332. X+ #endif
  1333. X+ {
  1334. X+    SysVar *v = FindSysVar(name);
  1335. X+    if (!v) return E_NOSUCH_VAR;
  1336. X+    if (!v->modifiable) {
  1337. X+       Eprint("Cannot modify system variable '$%s'", name);
  1338. X+       return E_CANT_MODIFY;
  1339. X+    }
  1340. X+    if (v->max != NO_CONSTRAINT && value > v->max) return E_2HIGH;
  1341. X+    if (v->min != NO_CONSTRAINT && value < v->min) return E_2LOW;
  1342. X+    *(v->value) = value;
  1343. X+    return OK;
  1344. X+ }
  1345. X+ 
  1346. X+ /***************************************************************/
  1347. X+ /*                                                             */
  1348. X+ /*  GetSysVar                                                  */
  1349. X+ /*                                                             */
  1350. X+ /*  Get the value of a system variable                         */
  1351. X+ /*                                                             */
  1352. X+ /***************************************************************/
  1353. X+ #ifdef HAVE_PROTOS
  1354. X+ PUBLIC int GetSysVar(const char *name, Value *val)
  1355. X+ #else
  1356. X+ int GetSysVar(name, val)
  1357. X+ char *name;
  1358. X+ Value *val;
  1359. X+ #endif
  1360. X+ {
  1361. X+    SysVar *v = FindSysVar(name);
  1362. X+ 
  1363. X+    val->type = INT_TYPE;
  1364. X+    val->v.val = 0;
  1365. X+    if (!v) return E_NOSUCH_VAR;
  1366. X+    val->v.val = *(v->value);
  1367. X+    return OK;
  1368. X+ }
  1369. X+ 
  1370. X+ /***************************************************************/
  1371. X+ /*                                                             */
  1372. X+ /* FindSysVar                                                  */
  1373. X+ /*                                                             */
  1374. X+ /* Find a system var with specified name.                      */
  1375. X+ /*                                                             */
  1376. X+ /***************************************************************/
  1377. X+ #ifdef HAVE_PROTOS
  1378. X+ PRIVATE SysVar *FindSysVar(const char *name)
  1379. X+ #else
  1380. X+ static SysVar *FindSysVar(name)
  1381. X+ char *name;
  1382. X+ #endif
  1383. X+ {
  1384. X+    int top=NUMSYSVARS-1, bottom=0;
  1385. X+    int mid=(top + bottom) / 2;
  1386. X+    int r;
  1387. X+ 
  1388. X+    while (top >= bottom) {
  1389. X+       r = StrCmpi(name, SysVarArr[mid].name);
  1390. X+       if (!r) return &SysVarArr[mid];
  1391. X+       else if (r>0) bottom = mid+1;
  1392. X+       else        top = mid-1;
  1393. X+       mid = (top+bottom) / 2;
  1394. X+    }
  1395. X+    return NULL;
  1396. X+ }
  1397. X+    
  1398. X+ /***************************************************************/
  1399. X+ /*                                                             */
  1400. X+ /*  DumpSysVarByName                                           */
  1401. X+ /*                                                             */
  1402. X+ /*  Given the name of a system variable, display it.           */
  1403. X+ /*  If name is "", dump all system variables.                  */
  1404. X+ /*                                                             */
  1405. X+ /***************************************************************/
  1406. X+ #ifdef HAVE_PROTOS
  1407. X+ PUBLIC void DumpSysVarByName(const char *name)
  1408. X+ #else
  1409. X+ void DumpSysVarByName(name)
  1410. X+ char *name;
  1411. X+ #endif
  1412. X+ {
  1413. X+    int i;
  1414. X+    SysVar *v;
  1415. X+ 
  1416. X+    if (!name || !*name) {
  1417. X+       for (i=0; i<NUMSYSVARS; i++) DumpSysVar(name, SysVarArr + i);
  1418. X+       return;
  1419. X+    }
  1420. X+    
  1421. X+    v = FindSysVar(name);
  1422. X+    DumpSysVar(name, v);
  1423. X+    return;
  1424. X+ }
  1425. X+ 
  1426. X+ /***************************************************************/
  1427. X+ /*                                                             */
  1428. X+ /*  DumpSysVar                                                 */
  1429. X+ /*                                                             */
  1430. X+ /*  Dump the system variable.                                  */
  1431. X+ /*                                                             */
  1432. X+ /***************************************************************/
  1433. X+ #ifdef HAVE_PROTOS
  1434. X+ PRIVATE void DumpSysVar(const char *name, const SysVar *v)
  1435. X+ #else
  1436. X+ static void DumpSysVar(name, v)
  1437. X+ char *name;
  1438. X+ SysVar *v;
  1439. X+ #endif
  1440. X+ {
  1441. X+    char buffer[VAR_NAME_LEN+10];
  1442. X+ 
  1443. X+    if (name && !*name) name=NULL;
  1444. X+    if (!v && !name) return;  /* Shouldn't happen... */
  1445. X+    
  1446. X+    buffer[0]='$'; buffer[1] = 0;
  1447. X+    if (name) strcat(buffer, name); else strcat(buffer, v->name);
  1448. X+    fprintf(ErrFp, "%*s  ", VAR_NAME_LEN, buffer);
  1449. X+    if (v) {
  1450. X+       if (!v->modifiable) fprintf(ErrFp, "%d\n", *v->value);
  1451. X+       else {
  1452. X+          fprintf(ErrFp, "%-10d  Allowed range: ", *v->value);
  1453. X+      if (v->min == NO_CONSTRAINT) fprintf(ErrFp, "(-Inf, ");
  1454. X+      else                         fprintf(ErrFp, "[%d, ", v->min);
  1455. X+      if (v->max == NO_CONSTRAINT) fprintf(ErrFp, "Inf)\n");
  1456. X+      else                         fprintf(ErrFp, "%d]\n", v->max);
  1457. X+       }
  1458. X+    } else   fprintf(ErrFp, "*UNDEFINED*\n");
  1459. X+ 
  1460. X+    return;
  1461. X  }
  1462. X  
  1463. END_OF_FILE
  1464.   if test 47360 -ne `wc -c <'patch.07.C'`; then
  1465.     echo shar: \"'patch.07.C'\" unpacked with wrong size!
  1466.   elif test -f 'patch.07.A' && test -f 'patch.07.B'; then
  1467.     echo shar: Combining  \"'patch.07'\" \(117693 characters\)
  1468.     cat 'patch.07.A' 'patch.07.B' 'patch.07.C' > 'patch.07'
  1469.     if test 117693 -ne `wc -c <'patch.07'`; then
  1470.       echo shar: \"'patch.07'\" combined with wrong size!
  1471.     else
  1472.       rm patch.07.A patch.07.B patch.07.C
  1473.     fi
  1474.   fi
  1475.   # end of 'patch.07.C'
  1476. fi
  1477. echo shar: End of archive 1 \(of 3\).
  1478. cp /dev/null ark1isdone
  1479. MISSING=""
  1480. for I in 1 2 3 ; do
  1481.     if test ! -f ark${I}isdone ; then
  1482.     MISSING="${MISSING} ${I}"
  1483.     fi
  1484. done
  1485. if test "${MISSING}" = "" ; then
  1486.     echo You have unpacked all 3 archives.
  1487.     rm -f ark[1-9]isdone
  1488. else
  1489.     echo You still must unpack the following archives:
  1490.     echo "        " ${MISSING}
  1491. fi
  1492. exit 0
  1493. exit 0 # Just in case...
  1494.