Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
REMIND(1)		       VERSION 05.03.05			     REMIND(1)

NAME
       remind -	a sophisticated	reminder service

SYNOPSIS
       remind [options]	filename [date]	[*rep] [time]

DESCRIPTION
       Remind  reads  the supplied filename and	executes the commands found in
       it.  The	commands are used to issue reminders  and  alarms.   Each  re-
       minder  or alarm	can consist of a message sent to standard output, or a
       program to be executed.

       If filename is specified	as a single dash '-', then  Remind  takes  its
       input from standard input.

       If  filename  happens  to be a directory	rather than a plain file, then
       Remind reads all	of the files (but not any  subdirectories!)   in  that
       directory that match the	pattern	"*.rem".  The files are	read in	sorted
       order;  the  sort order may depend on your locale, but should match the
       sort order used by the shell to expand "*.rem".

       Remind reads its	files starting from the	beginning to the end, or until
       it encounters a line whose  sole	 content  is  "__EOF__"	 (without  the
       quotes.)	 Anything after	the __EOF__ marker is completely ignored.

OPTIONS
       Remind  has  a  slew  of	options.  If you're new	to the program,	ignore
       them for	now and	skip to	the section "REMINDER FILES".

       -n     The -n option causes Remind to print the next occurrence of each
	      reminder in a simple calendar format.  You can sort this by date
	      by piping	the output through sort(1).  Note that the  -n	option
	      causes  any  -g option to	be ignored and also implicitly enables
	      the -o option.

       -j[n]  Runs Remind in "purge" mode to get  rid  of  expired  reminders.
	      See the section PURGE MODE for details.

       -r     The -r option disables RUN directives and	the shell() function.

       -c[flags]n
	      The  -c  option causes Remind to produce a calendar that is sent
	      to standard output.  If you supply a number n, then  a  calendar
	      will be generated	for n months, starting with the	current	month.
	      By  default,  a calendar for only	the current month is produced.
	      This option implicitly enables the -o option.

	      You can precede n	(if any) with a	set of flags.  The  flags  are
	      as follows:

	      '+'    causes a calendar for n weeks to be produced.

	      'a'    causes Remind to display reminders	on the calendar	on the
		     day  they actually	occur as well as on any	preceding days
		     specified by the reminder's delta.	 This also causes  Re-
		     mind to include text outside %"...%" sequences that would
		     otherwise	be removed (though the actual %" markers them-
		     selves are	removed.)

	      'l'    causes Remind to use  VT100  line-drawing	characters  to
		     draw  the	calendar.   The	 characters are	hard-coded and
		     will only work on terminals that emulate the  VT00	 line-
		     drawing character set.

	      'u'    is	similar	to 'l',	but causes Remind to use UNICODE line-
		     drawing  characters to draw the calendar.	The characters
		     are hard-coded and	will only work on terminals  that  are
		     set  to UTF-8 character encoding.	This flag also enables
		     the use of	the UNICODE "left-to-right" mark that can  fix
		     up	 formatting  problems  with right-to-left languages in
		     the calendar display.

	      'c'    causes Remind to use VT100	escape sequences  to  approxi-
		     mate  SPECIAL  COLOR  reminders.	Note that this flag is
		     kept for  backwards-compatibility;	 you  should  use  the
		     -@[n][,m][,b] command-line	option instead.

       -@[n][,m][,b]
	      Tells  Remind  to	 approximate SPECIAL COLOR and SHADE reminders
	      using VT100 escape sequences.  The approximation is  (of	neces-
	      sity)  very  coarse,  because the	VT100 only has eight different
	      color sequences, each with one of	 two  brightnesses.   A	 color
	      component	 greater than 64 is considered "on", and if any	of the
	      three color components is	greater	than 128, the color is consid-
	      ered "bright".

	      If you supply the	optional numeric parameters, the have the fol-
	      lowing meanings:	n=0 tells Remind to use	the standard 16	 VT100
	      colors.	n=1 tells it to	use an extended	256-color palette sup-
	      ported by	many terminal emulators	such as	xterm.	And n=2	 tells
	      it  to  use  escape  sequences  that support true	24-bit colors,
	      again supported by many terminal emulators such as xterm.

	      If the optional m	parameter is supplied following	a comma,  then
	      m=0  tells  Remind that the terminal background is dark, and Re-
	      mind will	brighten up dark colors	to make	them visible.  If m=1,
	      then Remind assumes the terminal background is light and it will
	      darken bright colors to make them	visible.  If m is specified as
	      2, then Remind does not perform any adjustments,	and  some  re-
	      minders  may  be	hard  or impossible to see if the color	is too
	      close to the terminal background color.  If you supply the  let-
	      ter  t  rather  than a number, then Remind attempts to guess the
	      background color of the terminal,	even if	stdout is not a	termi-
	      nal.

	      On startup, if the standard output is  a	terminal,  Remind  at-
	      tempts  to determine if the terminal background is dark or light
	      by sending a special escape sequence to determine	the background
	      color.  The m parameter can override this	check (or force	it  if
	      m	is given as t.)

	      If  the optional b parameter is supplied following a comma, then
	      b=0 tells	Remind to ignore SPECIAL SHADE reminders (the default)
	      and b=1 tells Remind to respect SPECIAL SHADE reminders by emit-
	      ting VT100 escape	codes to color the background of the  calendar
	      cell.   Note  that SHADE does not	work well unless you are using
	      the extended 256-color palette (n=1) or the true	24-bit	colors
	      (n=2).  Note that	for calendar cells that	are shaded, the	clamp-
	      ing mechanism described earlier for m=0 or m=1 is	skipped; it is
	      assumed  that if you set both the	foreground color of a reminder
	      and the background color of a cell, then you know	what  you  are
	      doing.

       -wcol[,pad[,spc]]]
	      The -w option specifies the output width,	padding	and spacing of
	      the  formatted  calendar	output.	  Col  specifies the number of
	      columns in the output device.  If	col is not  specified,	or  is
	      specified	 as  0,	 it defaults to	the larger of 71 or the	actual
	      width of your terminal, or to 80 if standard  output  is	not  a
	      terminal.	  If col is specified as the letter t, then Remind at-
	      tempts to	get the	width of the /dev/tty terminal	device.	  This
	      is  useful,  for example,	if you pipe calendar output into less;
	      even though standard output is a pipe, you want the calendar  to
	      be sized correctly for your terminal window:

		      remind -c	-wt .reminders | less

	      Note  that the value of col is also used to set the system vari-
	      able $FormWidth, which is	initialized to col - 8.	  See  "SYSTEM
	      VARIABLES" for details.

	      Pad  specifies  how  many	 lines	to use to "pad"	empty calendar
	      boxes.  This defaults to 5.  If you have many reminders on  cer-
	      tain  days  that	make your calendar too large to	fit on a page,
	      you can try reducing pad to make the empty boxes	smaller.   Spc
	      specifies	 how  many blank lines to leave	between	the day	number
	      and the first reminder entry.  It	defaults to 1.

	      Any of col, pad or spc can be omitted, providing you provide the
	      correct number of	commas.	 Don't use any spaces in the option.

       -s[a]n The -s option is very similar to the -c option, except that  the
	      output  calendar	is  not	 formatted.  It	is listed in a "simple
	      format" that can be used as input	for more sophisticated	calen-
	      dar-drawing  programs.   If n starts with	"+", then it is	inter-
	      preted as	a number of weeks.  This option	 also  implicitly  en-
	      ables the	-o option.

	      If  you  immediately follow the s	with the letter	a, then	Remind
	      displays reminders on the	calendar on the	day they actually  oc-
	      cur as well as on	any preceding days specified by	the reminder's
	      delta.

       -p[a][p][p][q][+]n
	      The  -p option is	very similar to	the -s option, except that the
	      output contains additional information for  use  by  a  back-end
	      such as the Rem2PS program, which	creates	a PostScript calendar,
	      and various other	back-end programs.  If n starts	with "+", then
	      it  specifies  a number of weeks rather than a number of months,
	      and back-ends are	expected to produce  weekly  calendars.	  Note
	      that not all back-ends support weekly calendars; currently, only
	      rem2pdf  and  rem2html do.  Specifying a weekly calendar implic-
	      itly enables the pure JSON interchange format, similar to	-ppp.

	      The format of the	-p output is described in  the	rem2ps(1)  man
	      page.   If  you immediately follow the p with the	letter a, then
	      Remind displays reminders	on the calendar	on the day they	 actu-
	      ally occur as well as on any preceding days specified by the re-
	      minder's delta.  If you follow the p with	another	p, then	Remind
	      uses  a  more  comprehensive  JSON-based	format rather than the
	      "simple calendar"	format.	 This format is	also documented	in the
	      rem2ps(1)	man page.  Finally, if you use three p's, as in	 -ppp,
	      then  Remind  uses  a  pure  JSON	 format,  again	 documented in
	      rem2ps(1).  If you include a q letter with this option, then the
	      normal calendar-mode substitution	filter	is  disabled  and  the
	      %"...%" sequences	are preserved in the output.

	      Note  that  to pass INFO strings to a back-end, you must use -pp
	      or -ppp.	The simpler -p format is not capable  of  transmitting
	      the INFO strings to the back-end.

	      The -p, -pp and -ppp options implicitly enable the -o option.

	      Note that	the -pp	or -ppp	options	also enable the	-l option.

       -l     If you use the -l	option in conjunction with the -p option, then
	      Remind outputs additional	information for	back-end programs such
	      as  rem2ps.   This additional information	lets the back-end pro-
	      grams correlate a	reminder with the source file and line	number
	      that produced it.

       -m     The  -m option causes the	-c or -p options to produce a calendar
	      whose first column is Monday rather than Sunday.	(This conforms
	      to the international standard.)

       -v     The -v option makes the output of	Remind slightly	more  verbose.
	      Currently,  this	causes Remind to echo a	bad line in case of an
	      error, and to print a security message if	 a  script  tests  the
	      $RunOff system variable.

       -o     The -o option causes Remind to ignore all	ONCE directives.  Note
	      that  ONCE  is  also ignored if any of the -c, -n, -p, or	-s op-
	      tions is used, if	a repetition factor *n is used,	or if  a  date
	      other than today's date is specified on the command-line.

       -t     The  -t  option  causes  Remind  to  trigger all non-expired re-
	      minders, regardless of the delta supplied	for each reminder.

       -tn    If you supply a number n after the -t option, then  Remind  pre-
	      tends  that  every REM command has a delta of ++n, regardless of
	      any existing delta.

       -tz    If you supply the	letter z after the -t option, then Remind sets
	      all REM statements' deltas to zero, regardless of	the value sup-
	      plied in the REM statement itself.  In effect, this disables all
	      deltas of	the form +n and	++n.

       -tt[n] The -tt option causes Remind to assume a default delta of	n min-
	      utes for all timed reminders.  If	-tt is given with no n,	a  de-
	      fault delta of 5 minutes is used.

       -h     The  -h option ("hush...") suppresses certain warning and	infor-
	      mation messages.	In particular, if no reminders are  triggered,
	      this mode	produces no output.

       -a     The -a option causes Remind not to immediately trigger timed re-
	      minders  that trigger on the current day.	 It also causes	Remind
	      not to place timed reminders in a	calendar.  If you  supply  two
	      or  more	-a  options,  then Remind will trigger timed reminders
	      that are in the future, but will	not  trigger  timed  reminders
	      whose  time  has passed.	(Regardless of how many	-a options you
	      supply, Remind will not include timed reminders in the  calendar
	      if at least one -a option	is used.)

       -q     The  -q  option  causes  Remind not to queue timed reminders for
	      later execution.

       -f     The -f option causes Remind to remain  in	 the  foreground  when
	      processing  queued  reminders,  rather  than forking off a back-
	      ground process to	handle them.

       -e     The -e option diverts error messages (normally sent to the stan-
	      dard error stream) to the	standard output	stream.

       -dchars
	      The -d option enables certain debugging modes.  The chars	 spec-
	      ify which	modes to enable:

	 e	Echo all input lines

	 x	Trace all expression evaluation

	 t	Display	all trigger date computation

	 v	Dump the variable table	after execution	of the reminder	script

	 l	Echo lines when	displaying error messages

	 f	Trace the reading of reminder files

	 s	Trace  expression  parsing and display the internal expression
		node tree.  This is unlikely to	be useful unless you are work-
		ing on Remind's	expression evaluation engine.

	 h	Dump hash-table	statistics on exit.

	 q	Output a TRANSLATE command each	time the _() built-in function
		is called or the %(...)	substitution sequence is encountered.

       -g[a|d[a|d[a|d[a|d]]]]
	      Normally,	reminders are issued in	the order in  which  they  are
	      encountered  in the reminder script.  The	-g option cause	Remind
	      to sort reminders	by date	and time prior to issuing  them.   The
	      optional a and d characters specify the sort order (ascending or
	      descending)  for	the  date,  time and priority fields.  See the
	      section "SORTING REMINDERS" for more information.

	      Note that	-g is ignored if you use the -n	option.

       -b[n]  Set the time format for the calendar  and	 simple-calendar  out-
	      puts.   N	can range from 0 to 2, with the	default	0.  A value of
	      0	causes times to	be inserted  in	 12-hour  (am/pm)  format.   1
	      causes  times  to	 be inserted in	24-hour	format,	and 2 inhibits
	      the automatic insertion of times in the calendar output.

       -x[n]  Sets the iteration limit for the SATISFY clause of  a  REM  com-
	      mand.  Defaults to 1000.

       -kcmd  Instead  of simply printing MSG-type reminders, this causes them
	      to be passed to the specific cmd.	 You must use '%s'  where  you
	      want  the	body to	appear,	and may	need to	enclose	this option in
	      quotes.  Note that all shell characters in the body of  the  re-
	      minder  are escaped with a backslash, and	the entire body	of the
	      reminder is passed as a single argument.	Note that this	option
	      overrides	the -r option and the RUN OFF command.

	      As an example, suppose you have an X Window program called xmes-
	      sage  that  pops	up  a window and displays its invocation argu-
	      ments.  You could	use:

			remind '-kxmessage %s &' ...

	      to have all of your MSG-type reminders processed using xmessage.

	      A	word of	warning: It is very easy to spawn dozens  of  xmessage
	      processes	 with  the  above technique.  So be very careful.  Be-
	      cause all	shell and whitespace characters	are escaped, the  pro-
	      gram  you	 execute with the -k option must be prepared to	handle
	      the entire message as a single argument.

	      If you follow the	-k option with a colon,	then  the  command  is
	      applied  only  to	 queued	timed reminders.  Normal reminders are
	      handled as usual.	 In the	above example, if you want normal  re-
	      minders to simply	be displayed as	usual, but queued reminders to
	      be sent to notify-send, you could	use:

			remind '-k:notify-send %s &' ...

	      You  use	both  -kcmd1 and -k:cmd2 to use	different commands for
	      queued versus non-queued reminders.

       -z[n] Runs Remind in "daemon mode".  If n
	      is supplied, it specifies	how often (in minutes)	Remind	should
	      wake up to check if the reminder script has been changed.	 N de-
	      faults  to  1, and can range from	1 to 60.  Note that the	use of
	      the -z option also enables the -f	option.

	      If Remind	is compiled on a system	that supports inotify(7), then
	      if the reminder script supplied on the command-line is  actually
	      a	directory, Remind additionally checks if all files within that
	      directory	have been modified since startup.

	      If  you  supply  the  option  -zj, Remind	runs in	a special mode
	      called server mode.  This	is  documented	in  the	 tkremind  man
	      page;  see  tkremind(1).	The older server mode option -z0 still
	      works, but is deprecated;	it uses	an ad-hoc method  to  communi-
	      cate  with the client rather than	using JSON to communicate with
	      the client.

       -uname Runs Remind with the uid and gid of the user specified by	 name.
	      The  option  changes  the	uid and	gid as described, and sets the
	      environment variables HOME, SHELL	and USER to  the  home	direc-
	      tory, shell, and user name, respectively,	of the specified user.
	      LOGNAME  is also set to the specified user name.	This option is
	      meant for	use in shell scripts that mail reminders to all	users.
	      Note that	as of Remind 3.00.17, using -u implies -r --  the  RUN
	      directive	 and  shell() functions	are disabled.  However,	if you
	      prefix name with a +-sign, then RUN and  shell()	are  not  dis-
	      abled.   That  is,  -uwhatever switches the user to whatever and
	      disables RUN, whereas -u+whatever	switches the user to  whatever
	      but leaves RUN enabled.

	      Non-root	users  can  also  use the -u option.  However, in this
	      case, it only changes the	 environment  variables	 as  described
	      above.  It does not change the effective uid or gid.

       -+username
	      Causes  Remind  to trust files owned by the user username.  Nor-
	      mally, if	Remind reads a file that you do	not own,  it  disables
	      RUN  and	the  shell()  function.	 This option causes it to also
	      trust files owned	by username.  You can supply multiple  -+  op-
	      tions  to	 trust	multiple  users,  up  to a limit of 20 trusted
	      users.

       -y     Causes Remind to synthesize a tag	for any	reminder that lacks  a
	      TAG clause.

       -ivar=expr
	      Sets  the	value of the specified var to expr, and	preserves var.
	      Expr can be any valid Remind expression.	See the	section	 "INI-
	      TIALIZING	 VARIABLES  ON THE COMMAND LINE" for more details.  If
	      you omit the =expr part, then var	is initialized to 0.  In other
	      words, -ivar is exactly the same as -ivar=0.

       -ifunc(args)=definition
	      Allows you to define a function on the command line.

       If you supply a date on the command line, it must consist of day	 month
       year,  where  day  is the day of	the month, month is at least the first
       three letters of	the English name of the	month, and year	is a year (all
       4 digits) from 1990 to about 2075.  You can leave out  the  day,	 which
       then defaults to	1.

       If  you	do  supply  a  date  on	the command line, then Remind uses it,
       rather than the actual system date, as its  notion  of  "today."	  This
       lets  you  create  calendars for	future months, or test to see how your
       reminders will be triggered in the future.  Similarly, you can supply a
       time to set Remind's notion of "now" to a particular time.  Supplying a
       time on the command line	also implicitly	enables	the -q option and dis-
       ables the -z option.  The time may be specified in 24-hour format  (eg,
       13:20) or common	"AM/PM"	format (1:20pm).

       If you would rather specify the date more succinctly, you can supply it
       as  YYYY-MM-DD  or  YYYY/MM/DD.	You can	even supply a date and time on
       the command line	as one argument: YYYY-MM-DD@HH:MM.

       In addition, you	can supply a repeat  parameter,	 which	has  the  form
       *rep.  This causes Remind to be run rep times, with the date increment-
       ing on each iteration.  You may have to enclose the parameter in	quotes
       to  avoid  shell	expansion.  See	the subsection "Repeated Execution" in
       the section "CALENDAR MODE" for more information.

LONG OPTIONS
       Remind supports the following long options, which are case-sensitive:

       --version The --version option causes Remind to print its version  num-
       ber to standard output and then exit.

       --print-errs
	      The  --print-errs	option causes Remind to	print all possible er-
	      ror messages to standard output and then exit.  The messages are
	      printed in a format suitable for the first argument of a	TRANS-
	      LATE  command.  If you TRANSLATE the error messages, then	Remind
	      will use the translated versions when outputting error and warn-
	      ing messages.  See also TRANSLATE	GENERATE in the	 section  "THE
	      TRANSLATION TABLE".

	      Note  that if an untranslated message contains printf-style for-
	      matting sequences	like "%s" or "%d", then	the translated message
	      must contain the same sequences in the  same  order,  or	Remind
	      will ignore it and use the original untranslated message.

       --print-config-cmd
	      This option causes Remind	to print the exact ./configure command
	      that  was	used when Remind was built.  You can use this to build
	      a	new version of Remind using the	same configuration as  an  ex-
	      isting one by running:

		      eval `remind --print-config-cmd`

	      from  the	 top-level  Remind  source  directory.	(However, it's
	      safer to simply run remind --print-config-cmd and	then  type  in
	      the command once you've verified that it looks OK.)

       --print-tokens
	      The --print-tokens option	causes Remind to print the tokens used
	      by  the  parser,	built-in  function  names, and system variable
	      names to standard	output and then	exit.  This output is designed
	      to make it easy to create	a syntax-highlighting file for various
	      text editors.  The output	can be modified	by hand	or by a	script
	      into a syntax-highlighting file with relative ease.

       --max-execution-time=n
	      Limit the	total execution	time (as measured by the  wall	clock)
	      to  n  seconds.	This  is useful	if Remind is invoked on	poten-
	      tially-untrustworthy files that could attempt to use  a  lot  of
	      resources.   Note	 that  the  limit  n is	approximate and	Remind
	      might execute for	one or two more	seconds	before it  is  killed.
	      If  n is specified as zero, then no limit	is applied, just as if
	      the option had not been used at all.

	      If a limit is applied, it	applies	only to	the foreground run  of
	      Remind.	If  Remind  finishes  processing  the  script and then
	      starts handling queued reminders,	the time limit is reset	to  no
	      limit.

       --test The  --test  long	option is only for use by the acceptance tests
	      run by "make test".  Do not use this option in production.

REMINDER FILES
       Remind uses scripts to control its operation.  You can use any text ed-
       itor capable of creating	plain-text files to create  a  Remind  script.
       The  commands inside a script can range from the	very simple and	almost
       immediately understandable:

	       REM Mar 31 MSG International Transgender	Day of Visibility

       to the baroque and obscure:

	       REM [date(thisyear, 1, 1) + 180]	++5 OMIT \
	       sat sun BEFORE MSG [ord(thisyear-1980)] payment due %b!

       A reminder file consists	of commands, with one command per line.	  Sev-
       eral  lines  can	 be continued using the	backslash character, as	in the
       above example.  In this case, all of the	concatenated lines are treated
       as a single line	by Remind.  Note that if an error occurs,  Remind  re-
       ports the line number of	the last line of a continued line.

       Remind  ignores	blank  lines,  and lines beginning with	the '#'	or ';'
       characters.  You	can use	the semicolon as a comment  character  if  you
       wish  to	pass a Remind script through the C pre-processor, which	inter-
       prets the '#' character as the start of a pre-processing	directive.

       Note that Remind	processes line	continuations  before  anything	 else.
       For example:

	    # This is a	comment	\
	    This line is part of the comment because of	line continuation \
	    and	so on.
	    REM	MSG This line is not ignored (no \ above)

       Remind  is not case sensitive; you can generally	use any	mixture	of up-
       per- or lower-case for commands,	parameters, invocation options,	etc.

THE REM	COMMAND
       The most	powerful command in a Remind script is the REM command.	  This
       command is responsible for issuing reminders.  Its syntax is:

	      REM  [ONCE]  [date_spec] [back] [delta] [repeat] [PRIORITY prio]
	      [SKIP | BEFORE | AFTER]  [OMIT  omit_list]  [ADDOMIT]  [NOQUEUE]
	      [OMITFUNC	 omit_function]	 [AT  time  [tdelta] [trepeat]]	[SCHED
	      sched_function]  [WARN  warn_function]  [UNTIL   expiry_date   |
	      THROUGH last_date] [SCANFROM scan_date | FROM start_date]	[DURA-
	      TION  duration] [TAG tag]	[INFO "info_string"] MSG | MSF | RUN |
	      CAL | SATISFY | SPECIAL special |	PS | PSFILE body

       The parts of the	REM command can	be specified in	any order, except that
       the body	must come immediately after the	MSG, RUN, CAL, PS,  PSFILE  or
       SATISFY	keyword.   The	portion	of the REM command before the MSG, MSF
       RUN, CAL	or SATISFY clause is called a trigger.

       In earlier versions of Remind, the REM  token  was  optional  providing
       that the	remainder of the command cannot	be mistaken for	another	Remind
       command.	  However, this	use is deprecated and will now cause a warning
       to be issued.  All of your reminder lines should	be  written  to	 start
       with the	REM command.

       MSG, MSF, RUN, CAL, SPECIAL, PS and PSFILE

       These  keywords denote the type of the reminder.	 (SATISFY is more com-
       plicated	and will be explained later.)  A  MSG-type  reminder  normally
       prints a	message	to the standard	output,	after passing the body through
       a  special substitution filter, described in the	section	"THE SUBSTITU-
       TION FILTER."  However, if you have used	the  -k	 command-line  option,
       then  MSG-type  reminders  are passed to	the appropriate	program.  Note
       that the	options	-c, -s,	-p and -n disable the -k option.

       Earlier versions	of Remind let you omit the  reminder  type,  in	 which
       case  it	 defaulted to MSG.  However, this usage	is deprecated and will
       cause a warning.	 Something like:

	    REM	6 January Dianne's Birthday

       will issue the warning "Missing REM type; assuming MSG"

       The MSF keyword is almost the same as the MSG keyword, except that  the
       reminder	 is formatted to fit into a paragraph-like format.  Three sys-
       tem variables control the formatting of MSF-type	reminders -  they  are
       $FirstIndent,  $SubsIndent  and	$FormWidth.  They are discussed	in the
       section "SYSTEM VARIABLES."  The	MSF keyword causes the spacing of your
       reminder	to be altered -	extra spaces are discarded, and	two spaces are
       placed after periods and	other characters, as specified by  the	system
       variables  $EndSent  and	 $EndSentIg.  Note that	if the body of the re-
       minder includes newline characters (placed there	with the %_ sequence),
       then the	newlines are treated as	the beginnings of new paragraphs,  and
       the  $FirstIndent  indentation  is used for the next line.  You can use
       two consecutive newlines	to have	spaced paragraphs emitted from a  sin-
       gle reminder body.

       A  RUN-type reminder also passes	the body through the substitution fil-
       ter, but	then executes the result as a system command.  A CAL-type  re-
       minder  is used only to place entries in	the calendar produced when Re-
       mind is run with	the -c,	-s or -p options.

       A PS or PSFILE-type reminder is used to pass PostScript	code  directly
       to  the	printer	when producing PostScript calendars.  This can be used
       to shade	certain	calendar entries (see the psshade() function), include
       graphics	in the calendar, or almost any other purpose you can think of.
       You should not use these	types of reminders unless you  are  an	expert
       PostScript  programmer.	The PS and PSFILE reminders are	ignored	unless
       Remind is run with the -p option.  See the section  "More  about	 Post-
       Script" for more	details.

       A  SPECIAL-type reminder	is used	to pass	"out-of-band" information from
       Remind to a calendar-producing back-end.	 It should be  followed	 by  a
       word  indicating	 the type of special data being	passed.	 The type of a
       special reminder	depends	on the back-end.   For	the  Rem2PS  back-end,
       SPECIAL PostScript is equivalent	to a PS-type reminder, and SPECIAL PS-
       File  is	 equivalent  to	a PSFILE-type reminder.	 The body of a SPECIAL
       reminder	is obviously dependent upon the	back-end.  A back-end must ig-
       nore a SPECIAL that it does not recognize.

       DATE SPECIFICATIONS

       A date_spec consists of zero to four parts.  These parts	are  day  (day
       of month), month	(month name), year and weekday.	 Month and weekday are
       the  English  names  of	months and weekdays.  At least the first three
       characters must be used.	 The following are  examples  of  the  various
       parts of	a date_spec:

       day:   1, 22, 31, 14, 3

       month: JANUARY, feb, March, ApR,	may, Aug

       year:  1990, 1993, 2030.	 The year can range from 1990 to 2075.

       weekday:
	      Monday, tue, Wed,	THU, Friday, saturday, sundAy

       Note  that  there can be	several	weekday	components separated by	spaces
       in a date_spec.

       INTERPRETATION OF DATE SPECIFICATIONS

       The following examples show how date specifications are interpreted.

       1. Null date specification - the	reminder is triggered every day.   The
       trigger date for	a specific run is simply the current system date.  For
       example:

	       REM MSG This is triggered every time Remind runs

       2. Only day present.  The reminder is triggered on the specified	day of
       each  month.  The trigger date for a particular run is the closest such
       day to the current system date.	For example:

	    REM	1 MSG First of every month.
	    REM	31 MSG 31st of every month that	has 31 days.

       3. Only month present.  The reminder is	triggered  every  day  of  the
       specified month.	 Example:

	    REM	Feb MSG	Every day in February

       4.  day and month present.  Examples:

	    REM	6 Jan MSG Every	6th of January
	    REM	Feb 29 MSG Every 29th of February

       5.  Only	year present. Example:

	    REM	1991 MSG Every day in 1991

       6.  year	and day	present.  Examples:

	    REM	1 1990 MSG 1st of every	month in 1990
	    REM	1992 23	MSG 23rd of every month	in 1992

       7.  year	and month present.  Examples:

	    REM	Feb 1991 MSG Every day in Feb 1991
	    REM	1992 September MSG Every day in	Sept 1992

       8.  year, month and day present.	 Examples:

	    REM	8 Jan 1991 MSG 8th January 1991.
	    REM	1992 March 9 MSG 9th March 1992.

       9.  weekday only.  Examples:

	    REM	Sat MSG	Every Saturday
	    REM	Mon Tue	Wed Thu	Fri MSG	Every working day
	    REM	Monday Wednesday MSG Every Monday and Wednesday

       10.  weekday and	day present.  Examples:

	    REM	Sat 1 MSG First	Saturday of every month
	    REM	Mon Tue	Wed Thu	Fri 15 \
		 MSG 1st working day on	or after 15th of every month

       11.  weekday and	month present.	Examples:

	    REM	Mon March MSG Every Monday in March
	    REM	Mon Tue	Wed Thu	Fri Feb	MSG Every working day in February

       12.  weekday, month and day present.  Examples:

	    REM	Mon 1 March MSG	First Monday in	March
	    REM	Sat Sun	15 July	MSG First Sat or Sun on	or after 15 July

       13.  weekday and	year present.  Example:

	    REM	Sat Sun	1991 MSG Every Saturday	and Sunday in 1991

       14.  weekday, day and year present.  Examples:

	    REM	Mon 15 1990 MSG	1st Mon	after 15th of every month in 1990
	    REM	Mon Tue	Wed Thu	Fri 1 1990 \
		 MSG 1st working day of	every month in 1990

       15.  weekday, month and year present.  Example:

	    REM	Mon Wed	1991 Feb MSG Every Mon and Wed in Feb 1991.

       16.  weekday, day, month	and year present.  Example:

	    REM	Mon Tue	Wed Thu	Fri 28 Oct 1990	\
		 MSG 1st working day on	or after 28 October 1990.

       Note  that  when	both weekday and day are specified, Remind chooses the
       first date on or	after the specified day	that also satisfies the	 week-
       day constraint.	It does	this by	picking	the first date on or after the
       specified day that is listed in the list	of weekdays.  Thus, a reminder
       like:

	    REM	Mon Tue	28 Oct 1990 MSG	Hi

       would  be issued	only on	Monday,	29 October, 1990.  It would not	be is-
       sued on Tuesday,	30 October, 1990, since	the 29th is the	first date  to
       satisfy the weekday constraints.

       SHORT-HAND DATE SPECIFICATIONS

       In addition to spelling out the day, month and year separately, you can
       specify	YYYY-MM-DD  or	YYYY/MM/DD.  For example, the following	state-
       ments are equivalent:

	    REM	5 June 2010 MSG	Cool!
	    REM	2010-06-05  MSG	Cool!

       You can also specify a date and time as YYYY-MM-DD@HH:MM.  These	state-
       ments are equivalent:

	    REM	19 Dec 2010 AT 16:45 MSG Hi
	    REM	2010-12-19@16:45 MSG Hi

       There's one subtlety with short-hand date specifications:  The  follow-
       ing statements are not equivalent:

	    REM	19 Dec 2010 AT 16:45 +60 MSG Hi
	    REM	2010-12-19@16:45 +60 MSG Hi

       In  the second statement, the "+60" is a	delta that applies to the date
       rather than a tdelta that applies to the	time.  We recommend explicitly
       using the AT keyword with timed reminders.

       THE REMIND ALGORITHM

       Remind uses the following algorithm to compute a	trigger	date: Starting
       from the	current	date, it examines each day, one	at a  time,  until  it
       finds a date that satisfies the date specification, or proves to	itself
       that  no	 such  date exists.  (Actually,	Remind merely behaves as if it
       used this algorithm; it would be	much too  slow	in  practice.	Inter-
       nally, Remind uses much faster techniques to calculate a	trigger	date.)
       See DETAILS ABOUT TRIGGER COMPUTATION for more information.

       BACKWARD	SCANNING

       Sometimes,  it  is necessary to specify a date as being a set amount of
       time before another date.  For example, the  last  Monday  in  a	 given
       month  is computed as the first Monday in the next month, minus 7 days.
       The back	specification in the reminder is used in this case:

	    REM	Mon 1 -7 MSG Last Monday of every month.

       A back is specified with	one or two  dashes  followed  by  an  integer.
       This  causes Remind to move "backwards" from what would normally	be the
       trigger date.  The difference between --7 and -7	will be	explained when
       the OMIT	keyword	is described.

       ADVANCE WARNING

       For some	reminders, it is appropriate to	receive	advance	warning	of the
       event.  For example, you	may wish to be reminded	of someone's  birthday
       several days in advance.	 The delta portion of the REM command achieves
       this.   It is specified as one or two "+" signs followed	by a number n.
       Again, the difference between the "+" and "++" forms will be  explained
       under  the  OMIT	keyword.  Remind will trigger the reminder on computed
       trigger date, as	well as	on each	of the n days before the event.	  Here
       are some	examples:

	    REM	6 Jan +5 MSG Remind me of birthday 5 days in advance.

       The  above  example would be triggered every 6th	of January, as well as
       the 1st through 5th of January.

       PERIODIC	REMINDERS

       We have already seen some built-in mechanisms for certain types of  pe-
       riodic  reminders.   For	 example,  an  event occurring every Wednesday
       could be	specified as:

	    REM	Wed MSG	Event!

       However,	events that do not repeat daily, weekly, monthly or yearly re-
       quire another approach.	The repeat component of	the REM	command	 fills
       this  need.  To use it, you must	completely specify a date (year, month
       and day,	and optionally weekday); this is the start date	of the repeti-
       tion period.  The repeat	component is an	asterisk followed by a	number
       specifying the repetition period	in days.

       For example, suppose you	get paid every second Wednesday, and your last
       payday was Wednesday, 28	October, 1992.	You can	use:

	    REM	28 Oct 1992 *14	MSG Payday

       This issues the reminder	every 14 days, starting	from 28	Oct 1992.  You
       can  use	 delta	and back with repeat.  Note, however, that the back is
       used only to compute the	starting date; thereafter,  the	 reminder  re-
       peats  with the specified period.  Similarly, if	you specify a weekday,
       it is used only to calculate the	starting date, and does	not affect the
       repetition period.

       SCANFROM	and FROM

       The SCANFROM and	FROM keywords  are  for	 advanced  Remind  programmers
       only,  and will be explained in the section "DETAILS ABOUT TRIGGER COM-
       PUTATION" near the end of this manual.  Note that SCANFROM is available
       only in versions	of Remind from 03.00.04	up.  FROM  is  available  only
       from 03.01.00 and later.

       PRIORITY

       The  PRIORITY  keyword must be followed by a number from	0 to 9999.  It
       is used in calendar mode	and when sorting reminders.  If	two  reminders
       have  the same trigger date and time, then they are sorted by priority.
       If the PRIORITY keyword is not supplied,	a default priority of 5000  is
       used.   (This  default  can be changed by adjusting the system variable
       $DefaultPrio.  See the section "SYSTEM  VARIABLES"  for	more  informa-
       tion.)

       EXPIRY DATES

       Some  reminders	should	be issued periodically for a certain time, but
       then expire.  For example, suppose you have a class every  Friday,  and
       that your last class is on 11 December 1992.  You can use:

	    REM	Fri UNTIL 11 Dec 1992 MSG Class	today.

       Another	example:  Suppose you have jury	duty from 30 November 1992 un-
       til 4 December 1992.  The following reminder  will  issue  the  message
       every day of your jury duty, as well as 2 days ahead of time:

	    REM	1992-11-30 *1 +2 UNTIL 1992-12-04 MSG Jury duty

       Note that the repeat of *1 is necessary;	without	it, the	reminder would
       be issued only on 30 November (and the two days preceding.)

       As  a  special  case, you can use the THROUGH keyword instead of	*1 and
       UNTIL.  The following two REM commands are equivalent:

	    REM	1992-11-30 *1 +2 UNTIL 1992-12-04 MSG Jury duty

	    REM	1992-11-30 +2 THROUGH 1992-12-04 MSG Jury duty

       If you have an expiry date via the use of THROUGH or UNTIL, then	Remind
       will never trigger the reminder after the expiry	date.  For example, if
       you have	this:

	       OMIT 2021-01-08
	       REM 2021-01-01 THROUGH 2021-01-08 AFTER MSG Test

       the reminder will not be	triggered on 2021-01-08, and nor  will	it  be
       triggered  on  2021-01-09; even though the AFTER	keyword	would normally
       move the	8th's reminder to the 9th, the expiry date of 2021-01-08 over-
       rides that.

       THE ONCE	KEYWORD

       Sometimes, it is	necessary to ensure that reminders are run  only  once
       on a given day.	For example, compare the following two reminders:

	       REM Fri RUN do_backup
	       REM Fri ONCE RUN	do_backup

       The first will be run every time	you invoke Remind on a Friday, whereas
       the second will be run only the first time you invoke Remind on a given
       Friday.

       If you run Remind from your .login script, for example, and log in sev-
       eral times per day, the do_backup program in the	first reminder will be
       run each	time you log in.  If, however, you use the ONCE	keyword	in the
       reminder,  the  Remind  checks  the  last  access  date of the reminder
       script.	If it is the same as the current date, Remind assumes that  it
       has  already been run, and will not issue reminders containing the ONCE
       keyword.

       Note that if you	view or	edit your reminder  script,  the  last	access
       date  will  be updated, and the ONCE keyword will not operate properly.
       You can fix this	by setting a timestamp file for	Remind	to  track  the
       last-run	 date;	see the	documentation of $OnceFile in the SYSTEM VARI-
       ABLES section.  If you use standard input as your  Remind  input	 file,
       then you	must use $OnceFile for the ONCE	keyword	to work	properly.

       If  you	start Remind with the -o option, then the ONCE keyword will be
       ignored and any $OnceFile will be ignored.

       LOCALLY OMITTING	WEEKDAYS

       The OMIT	portion	of the REM command is used to "omit" certain days when
       counting	the delta or back.  It is specified  using  the	 keyword  OMIT
       followed	 by  a	list of	weekdays.  Its action is best illustrated with
       examples:

	    REM	1 +1 OMIT Sat Sun MSG Important	Event

       This reminder is	normally triggered on the first	 of  every  month,  as
       well as the day preceding it.  However, if the first of the month falls
       on a Sunday or Monday, then the reminder	is triggered starting from the
       previous	Friday.	 This is because the delta of +1 does not count	Satur-
       day  or Sunday when it counts backwards from the	trigger	date to	deter-
       mine how	much advance warning to	give.

       Contrast	this with the use of "++1" in  the  above  command.   In  this
       case,  the reminder is triggered	on the first of	each month, as well as
       the day preceding it.  The omitted days are counted.

	    REM	1 -1 OMIT Sat Sun MSG Last working day of month

       Again, in the above example, the	back of	-1 normally causes the trigger
       date to be the last day of the month.  However,	because	 of  the  OMIT
       clause,	if  the	 first	of  the	month falls on a Sunday	or Monday, the
       trigger date is moved backwards past the	weekend	to  Friday.   (If  you
       have  globally  omitted	holidays, the reminder will be moved back past
       them, also.  See	"The OMIT command" for more details.)

       By comparison, if we had	used "--1", the	reminder would be triggered on
       the last	day of the month, regardless of	the OMIT.

       If you locally omit weekdays but	also have  globally-omitted  weekdays,
       then  the  list	of omitted weekdays is the union of the	two.  Consider
       this example:

	       OMIT Sat	Sun
	       REM 15 OMIT Fri Sat MSG Whatever

       In the REM command, the effective list of omitted weekdays will be Fri-
       day, Saturday and Sunday.

       COMPUTED	LOCAL OMITS

       The OMITFUNC phrase of the REM command allows you to supply a  function
       that  determines	 whether or not	a date is omitted.  Note that OMITFUNC
       must be given just the name of a	user-defined function; it  can't  take
       an arbitrary expression or the name of a	built-in function.

       The function is passed a	single parameter of type DATE, and must	return
       a non-zero integer if the date is considered "omitted" and 0 otherwise.
       Here's an example:

	       FSET _third(x) (day(x) %	3) || \
			      (wkdaynum(x) == 0) || \
			      (wkdaynum(x) == 6)
	       REM OMITFUNC _third AFTER MSG Working day divisible by 3

       In  the example above, the reminder is triggered	every Monday to	Friday
       whose day-of-month number is divisible by three.	 Here's	how it works:

       o      The OMITFUNC _third portion causes all days for which  _third(x)
	      returns  non-zero	 to  be	considered "omitted".  This causes all
	      days whose day-of-month number is	not a multiple of three	to  be
	      omitted.	 Note that _third also returns non-zero	if the weekday
	      is Sunday	or Saturday.

       o      The AFTER	keyword	causes the reminder to be moved	after a	 block
	      of omitted days.

       The combination of OMITFUNC and AFTER keyword causes the	reminder to be
       issued on all days whose	day-of-month number is divisible by three, but
       not on Saturday or Sunday.

       Note  that if you use OMITFUNC, then a local OMIT is ignored as are all
       global OMITs.  If you want to omit specific weekdays, your  omit	 func-
       tion will need to test for them specifically.  If you want to take into
       account	the  global OMIT context, then your omit function will need to
       test for	that explicitly	(using the isomitted() function.)

       Note that an incorrect OMITFUNC might cause all days to	be  considered
       omitted.	  For  that reason, when Remind	searches through omitted days,
       it terminates the search	after the SATISFY  iteration  limit  (command-
       line option -x.)

       ADDING TRIGGER DATES TO THE OMIT	CONTEXT

       If  the ADDOMIT keyword appears in a REM	command, then the trigger date
       (if one could be	calculated) is automatically  added  to	 the  list  of
       global OMITs.

       The command:

	       REM ... whatever	... ADDOMIT MSG	Foo

       is identical in behavior	to the sequence:

	       REM ... whatever	... SATISFY 1
	       IF trigvalid()
		   OMIT	[trigdate()] MSG Foo
	       ENDIF

       TIMED REMINDERS

       Timed  reminders	 are  those that have an AT keyword followed by	a time
       and optional tdelta and trepeat.	 The time may be specified in  24-hour
       format,	with  0:00 representing	midnight, 12:00	representing noon, and
       23:59 representing one minute to	midnight.  Alternatively,  it  may  be
       specified  in  common "AM/PM" format; in	this case, the hour must range
       from 1 to 12.  12:00am represents midnight,  12:00pm  represents	 noon,
       and  11:59pm represents one minute to midnight.	The "am" and "pm" por-
       tions are case-insensitive and the "m" is optional.

       You can use either a colon or a period to separate the hours  from  the
       minutes.	 That is, 13:39	and 13.39 are equivalent.

       Remind  treats  timed  reminders	 specially.  If	the trigger date for a
       timed reminder is the same as the current system	date, the reminder  is
       queued  for  later activation.  When Remind has finished	processing the
       reminder	file, it puts itself in	the background,	 and  activates	 timed
       reminders  when	the system time	reached	the specified time.  Note that
       if you use the NOQUEUE modifier in the REM command, then	 this  queuing
       and  background	activation is not performed.  NOQUEUE is useful	if you
       want a time to be associated with a reminder (eg, in the	calendar)  but
       are not interested in a popup reminder happening	at the specified time.

       If the trigger date is not the same as the system date, the reminder is
       not queued.

       For  example, the following reminder, triggered every working day, will
       emit a message telling you to leave at 5:00pm:

	    REM	Mon Tue	Wed Thu	Fri AT 17:00 MSG Time to leave!

       The following reminder will be triggered	on Thursdays and Fridays,  but
       will only be queued on Fridays:

	    REM	Fri ++1	AT 1:00PM MSG Lunch at 1pm Friday.

       The  tdelta  and	 trepeat have the same form as a repeat	and delta, but
       are specified in	minutes.  For example, this reminder will be triggered
       at 12:00pm as well as 45	minutes	before:

	    REM	AT 12:00 +45 MSG Example

       The following will be issued starting at	10:45, every half  hour	 until
       11:45, and again	at noon.

	    REM	AT 12:00 +75 *30 MSG Example2

       The  "+75" means	that the reminder is issued starting 75	minutes	before
       noon; in	other words, at	10:45.	The *30	specifies that the reminder is
       subsequently to be issued every 30 minutes.  Note that the reminder  is
       always issued at	the specified time, even if the	tdelta is not a	multi-
       ple  of	the  trepeat.	So  the	 above	example	 is issued at 10:45am,
       11:15am,	11:45am, and 12:00pm.  Note that in  the  time	specification,
       there is	no distinction between the "+" and "++"	forms of tdelta.

       Normally,  Remind  will	issue  timed reminders as it processes the re-
       minder script, as well as queuing them for later.  If you do  not  want
       Remind  to  issue the reminders when processing the script, but only to
       queue them for later, use the -a	command-line option.  If  you  do  not
       want reminders to be queued for later, use the -q command-line option.

       Normally, Remind	forks a	background process to handle queued reminders.
       If you want Remind to remain in the foreground, use the -f command-line
       option.	 This  is  useful, for example,	in .xinitrc scripts, where you
       can use the command:

	    remind -fa myreminders &

       This ensures that when  you  exit  X-Windows,  the  Remind  process  is
       killed.

       WARNING ABOUT TIMED REMINDERS

       Note:  If you use user-defined functions	or variables (described	later)
       in the bodies of	timed reminders, then when the timed reminders are ac-
       tivated,	 the variables and functions have the definitions that were in
       effect at the end of the	reminder script.  These	 definitions  may  not
       necessarily  be	those that were	in effect at the time the reminder was
       queued.	In addition, the OMIT context is whatever was in effect	at the
       end of the reminder script, which may not necessarily be	 the  same  as
       when the	REM command was	first processed.

       THE SCHED AND WARN KEYWORDS

       The  SCHED  keyword  allows more	precise	control	over the triggering of
       timed reminders,	and the	WARN keyword allows precise control  over  the
       advance triggering of all types of reminders.  However, discussion must
       be  deferred until after	expressions and	user-defined functions are ex-
       plained.	 See the subsection "PRECISE SCHEDULING" further on.

       TAG, INFO AND DURATION

       The TAG keyword lets you	"tag" certain  reminders.   This  facility  is
       used by certain back-ends or systems built around Remind, such as TkRe-
       mind.   These back-ends have specific rules about tags; see their docu-
       mentation for details.

       The TAG keyword is followed by a	tag consisting of up to	48 characters.
       You can have as many TAG	clauses	as you like in a given REM  statement.
       A tag can contain any character except for whitespace and a comma.

       If  you	supply the -y option to	Remind,	then any reminder that lacks a
       TAG will	have one synthesized.  The synthesized	tag  consists  of  the
       characters  "__syn__" followed by the hexadecimal representation	of the
       MD5 sum of the REM command line.	 This lets  you	 give  a  more-or-less
       unique identifier to each distinct REM command.

       The  INFO  keyword is similar to	TAG but	is intended to convey metadata
       about an	event, such as its location.  Back-ends	will  have  their  own
       rules   about  which  info_strings  they	 recognize,  and  must	ignore
       info_strings they don't recognize. Note that INFO must be followed by a
       quoted string; you can include newlines in the string by	supplying them
       as "\n".

       An INFO string must be of the form "Header:  Value".   The  header  can
       consist of any printable	character, but cannot contain whitespace.  The
       value can consist of any	characters you like.  Space may	not appear be-
       fore the	colon, but can appear afterwards; such space is	not considered
       to  be  part of the value.  If there is more than one INFO string for a
       given reminder, there cannot be any duplicate headers.  Case is ignored
       when determining	if a header is a duplicate of an existing one.

       For example, a hypothetical back-end might let you set the location and
       description of a	reminder like this:

	       REM 26 Feb 2025 INFO "Location: Boardroom #2" \
			       INFO "Description: Go over latest pull requests"	\
			       MSG Engineering meeting

       The DURATION keyword makes sense	only for timed reminders; it specifies
       the duration of an event.  For example, if you have a 90-minute meeting
       starting	at 1:00pm, you could use any of	the following:

	       REM 5 March 2021	AT 13:00 DURATION 1:30 MSG Meeting
	       REM 5 March 2021	AT 13:00 DURATION 90 MSG Meeting
	       REM 5 March 2021	AT 1:00pm DURATION 1:30	MSG Meeting
	       REM 5 March 2021	AT 1:00pm DURATION 90 MSG Meeting

       For long-duration reminders, it is convenient  to  use  expressions  to
       simplify	 writing  the  DURATION.  For example, if you are away from 20
       Feb 2023	through	23 Feb 2023 (a total of	4 days)	you could write:

	       REM 20 Feb AT 00:00 DURATION [4*24]:00 MSG away
	       REM 20 Feb AT 00:00 DURATION [4*24*60] MSG away

       Note that duration is specified either as hours:minutes or just as min-
       utes specified as an integer.

       If you specify a	duration of 00:00 or 0,	then Remind behaves exactly as
       if no DURATION at all had been present.	Although  durations  specified
       as  hours:minutes  look superficially like a time-of-day, they are not;
       the hours component is not limited to the range 00-23.

SYNTACTIC SUGAR	FOR REM
       The REM command has syntactic sugar  to	let  you  express  common  re-
       minders.	 The following pairs of	reminders are equivalent:

	       REM First Monday	April MSG Foo
	       REM Mon 1 April	      MSG Foo

	       REM Second Monday May  MSG Bar
	       REM Mon 8 May	      MSG Bar

	       REM Third Monday	MSG Third Monday of every month
	       REM Mon 15 MSG Third Monday of every month

	       REM Fourth Sunday June 2025 MSG Fourth Sunday in	June 2025
	       REM Sun 22 June 2025 MSG	Fourth Sunday in June 2025

	       REM Last	Monday MSG Last	Monday of every	month
	       REM Mon 1 --7 MSG Last Monday of	every month

	       REM Last	Monday April MSG Last Monday of	every April
	       REM Mon 1 May --7 MSG  Last Monday of every April

	       REM Last	Monday December	2025 MSG Last Monday of	Dec 2025
	       REM Monday 1 Jan	2026 --7 MSG Last Monday of Dec	2025

       Note that Last effectively adjusts the month and	year, if necessary, to
       make the	reminder trigger on the	correct	date.

       The keyword IN is completely ignored, so	you can	write (for example):

	       REM Second Monday in May	MSG foo
	       REM Last	Monday in December 2025	MSG Bar

       An  alternate form of back makes	writing	reminders easier.  The follow-
       ing groups of reminders are equivalent:

	       REM ~~1 MSG Last	day of every month
	       REM Lastday MSG	Last day of every month
	       REM 1 --1 MSG Last day of every month

	       REM May ~~1 MSG Last day	of May
	       REM Lastday May MSG Last	day of May
	       REM 1 June --1 MSG Last day of May

	       REM Dec 2025 ~~1	MSG Last day of	December 2025
	       REM Lastday Dec 2025 MSG	Last day of December 2025
	       REM 1 Jan 2026 --1 MSG Last day of December 2025

	       REM Apr ~1 OMIT SAT SUN MSG Last	workday	of April
	       REM Lastworkday April OMIT SAT SUN MSG Last workday of April
	       REM 1 May -1 OMIT SAT SUN MSG Last workday of April

	       REM Apr ~~7 MSG Seventh-last day	of April
	       REM 1 May --7 MSG Seventh-last day of April

	       REM Apr ~2 OMIT SAT SUN MSG Second-last workday of April
	       REM 1 May -2 OMIT SAT SUN MSG Second-last workday of April

       As we see, "Lastday" is equivalent to ~~1 and "Lastworkday" to ~1.

       Note that the First/Second/Third/Fourth/Last keywords and the ~ and  ~~
       form of back imply a value for the day of the month; as such, they can-
       not    be    combined	with	a   day.    Additionally,   First/Sec-
       ond/Third/Fourth/Last must have at least	one weekday name.  The follow-
       ing are illegal:

	       REM First Monday	3 June MSG Huh?
	       REM April 3 ~~1 MSG What?
	       REM Second June MSG Where's the weekday???

THE SUBSTITUTION FILTER
       Before being processed, the body	of a REM command is passed  through  a
       substitution filter.  The filter	scans for sequences "%x" (where	"x" is
       any  letter and certain other characters) and performs substitutions as
       shown below.  (All dates	refer to the trigger date of the reminder.)

       %a     is replaced with "on weekday, day	month, year"
	      For example, consider the	reminder:

	      REM 18 Oct 1990 +4 MSG Meeting with Bob %a.

	      On 16 October 1990, it would print "Meeting with Bob  on	Thurs-
	      day, 18 October, 1990."

	      On 17 October 1990, it would print "Meeting with Bob tomorrow."

	      On 18 October 1990, it would print "Meeting with Bob today."

       %b     is  replaced  with "in diff day's	time" where diff is the	actual
	      number of	days between the current date and  the	trigger	 date.
	      (OMITs have no effect.)
	      For example, consider:

	      REM 18 Oct 1990 +4 MSG Meeting with Bob %b.

	      On  16 October 1990, it would print "Meeting with	Bob in 2 days'
	      time."

	      On 17 October 1990, it would print "Meeting with Bob tomorrow."

	      On 18 October 1990, it would print "Meeting with Bob today."

       %c     is replaced with "on weekday"
	      Example: REM 18 Oct 1990 +4 MSG Meeting with Bob %c.

	      On 16 October 1990, it would print "Meeting with Bob  on	Thurs-
	      day."

	      On 17 October 1990, it would print "Meeting with Bob tomorrow."

	      On 18 October 1990, it would print "Meeting with Bob today."

       %d     is replaced with "day", the day of the month.

       %e     is replaced with "on dd-mm-yyyy"

       %f     is replaced with "on mm-dd-yyyy"

       %g     is replaced with "on weekday, day	month"

       %h     is replaced with "on dd-mm"

       %i     is replaced with "on mm-dd"

       %j     is replaced with "on weekday, month day-th, year"	 This form ap-
	      pends  the characters "st", "nd",	"rd" or	"th" to	the day	of the
	      month, as	appropriate.

       %k     is replaced with "on weekday, month day-th"

       %l     is replaced with "on yyyy-mm-dd"

       %m     is replaced with "month",	the name of the	month.

       %n     is replaced with the number (1 to	12) of the month.

       %o     is replaced with " (today)" if and only if  the  current	system
	      date is the same as the date being used by Remind	as the current
	      date.   Recall  that you can specify a date for Remind to	use on
	      the command line.	 This substitution is not generally useful  in
	      a	 REM  command,	but  is	useful in a BANNER command.  (See "The
	      BANNER Command.")

       %p     is replaced with "s" if the diff between the  current  date  and
	      the  trigger  date  is not 1.  You can use this to construct re-
	      minders like:
	      REM 1 Jan	+4 MSG %x day%p	to go before New Year!

       %q     is replaced with "'s" if the diff	between	the trigger  date  and
	      the  current  date  is  1.   Otherwise, it is replaced with "s'"
	      This can be used as follows:
	      REM 1 Jan	+4 MSG New Year	in %x day%q time!

       %r     is replaced with the day of the month (01	to 31) padded  with  a
	      leading zero if needed to	pad to two digits.

       %s     is  replaced  with "st", "nd", "rd" or "th" depending on the day
	      of the month.

       %t     is replaced with the number of the month (01 to  12)  padded  to
	      two digits with a	leading	zero.

       %u     is replaced with "on weekday, day-th month, year"	 This is simi-
	      lar  to  %a except that "st", "nd", "rd" or "th" is added	to the
	      day as appropriate.

       %v     is replaced with "on weekday, day-th month"

       %w     is replaced with "weekday", the name of the day of the week.

       %x     is replaced with the diff	between	the current date and the trig-
	      ger date.	 The diff is defined as	the actual number of days  be-
	      tween these two dates; OMITs are not counted.  (Strict date sub-
	      traction is performed.)

       %y     is replaced with "year", the year	of the trigger date.

       %z     is replaced with "yy", the last two digits of the	year.

       %(any_text)
	      is  replaced  with the lookup of any_text	in the translation ta-
	      ble.  It is the equivalent of [_("any_text")] but	is more	conve-
	      nient to type.

       %<any_text>
	      is replaced with the  INFO  value	 associated  with  the	header
	      any_text	or  the	empty string if	no such	INFO value exists.  It
	      is the equivalent	of [triginfo("any_text")] but is  more	conve-
	      nient to type.

       %_     (percent-underscore)  is	replaced  with a newline.  You can use
	      this to achieve multi-line reminders.  Note that calendar	 back-
	      ends vary	in how they handle multi-line reminders:

	      o	     Running remind -c preserves newlines in the terminal cal-
		     endar output.

	      o	     rem2pdf  preserves	newlines if remind is invoked with the
		     -pp or -ppp option.

	      o	     rem2html preserves	newlines if remind is invoked with the
		     -pp option.

	      o	     tkremind preserves	newlines.

	      o	     rem2ps converts newlines to spaces.  But rem2ps is	depre-
		     cated; use	rem2pdf	instead.

	      o	     The "simple calendar" formats (ie,	remind's -s, -n	and -p
		     options) convert newlines to spaces.

	      All calendar back-ends collapse  multiple	 spaces	 to  a	single
	      space and	multiple newlines to a single newline.

       %1     is  replaced  with "now",	"m minutes from	now", "m minutes ago",
	      "h hours from now", "h hours ago", "h hours and m	 minutes  from
	      now"  or "h hours	and m minutes ago", as appropriate for a timed
	      reminder.	 Note that unless you specify the -a option, timed re-
	      minders will be triggered	like  normal  reminders,  and  thus  a
	      timed  reminder  that  occurred  earlier in the day may be trig-
	      gered.  This causes the need for the "...ago" forms.

       %2     is replaced with "at hh:mmam" or "..pm" depending	on the AT time
	      of the reminder.

       %3     is replaced with "at hh:mm" in 24-hour format.

       %4     is replaced with "mm" where mm is	the number of minutes  between
	      "now"  and  the time specified by	AT.  If	the AT time is earlier
	      than the current time, then the result is	negative.

       %5     is replaced with "ma" where ma is	the absolute value of the num-
	      ber produced by %4.

       %6     is replaced with "ago" or	"from now", depending on the relation-
	      ship between the AT time and the current time.

       %7     is replaced with the number of hours between the AT time and the
	      current time.  It	is always non-negative.

       %8     is replaced with the number of minutes between the AT  time  and
	      the current time,	after the hours	(%7) have been subtracted out.
	      This is a	number ranging from 0 to 59.

       %9     is replaced with "s" if the value	produced by %8 is not 1.

       %0     is replaced with "s" if the value	produced by %7 is not 1.

       %!     is replaced with "is" if the current time	is before the AT time,
	      or "was" if it is	after.

       %@     is similar to %2 but displays the	current	time.

       %#     is similar to %3 but displays the	current	time.

       %"     (percent-doublequote - ")	is removed.  This sequence is not used
	      by  the  substitution  filter,  but is used to tell Remind which
	      text to include in a calendar entry when the -c, -s or -p	option
	      is chosen.  See "CALENDAR	MODE"

       Notes:

       o      Remind normally prints a blank line after	each reminder; if  the
	      last  character  of  the body is "%", the	blank line will	not be
	      printed.	You can	globally suppress the  extra  blank  lines  by
	      setting $AddBlankLines to	0.

       o      Substitutions  a,	 b, c, e, f, g,	h, i, j, k, l, u and v all are
	      replaced with "today" if the current  date  equals  the  trigger
	      date,  or	 "tomorrow"  if	 the trigger date is one day after the
	      current date.  Thus, they	are  not  the  same  as	 substitutions
	      built up from the	simpler	%w, %y,	etc.  sequences.

       o      The  a,  c, e, f,	g, h, i, j, k, l, u, v,	2, and 3 substitutions
	      may be preceded by an asterisk (for example, %*c)	 which	causes
	      the  word	 "at"  or  "on"	that would normally be included	in the
	      output to	be omitted.

       o      Any of the substitutions dealing with time (0 through 9 and '!')
	      produce undefined	results	if used	in a reminder  that  does  not
	      have  an AT keyword.  Also, if a reminder	has a delta and	may be
	      triggered	on several days, the  time  substitutions  ignore  the
	      date.  Thus, the %1 substitution may report that a meeting is in
	      15  minutes,  for	 example, even though it may only be in	2 days
	      time, because a delta has	triggered the reminder.	 It is	recom-
	      mended  that  you	 use  the time substitutions only in timed re-
	      minders with no delta that are designed to be queued  for	 timed
	      activation.

       o      Capital  letters	can  be	 used in the substitution sequence, in
	      which case the first character of	the substituted	string is cap-
	      italized (if it is normally a lower-case letter.)

       o      All other	characters following a "%" sign	are simply copied.  In
	      particular, to get a "%" sign out, use "%%"  in  the  body.   To
	      start  the  body of a reminder with a space, use "% ", since Re-
	      mind normally scans for the first	non-space  character  after  a
	      MSG, CAL or RUN token.

THE OMIT COMMAND
       In addition to being a keyword in the REM command, OMIT is a command in
       its own right.  Its syntax is:

	      OMIT weekday [weekday...]

	      or:

	      OMIT [day] month [year]

	      or:

	      OMIT [day1] month1 [year1] THROUGH [day2]	month2 [year2]

       The OMIT	command	is used	to "globally" omit certain days	(usually holi-
       days).	These  globally-omitted	 days  are  skipped by the "-" and "+"
       forms of	back and delta,	but not	by the "--" and	"++" forms.  Some  ex-
       amples:

	   OMIT	Saturday Sunday
	   OMIT	1 Jan
	   OMIT	7 Sep 1992
	   OMIT	15 Jan THROUGH 14 Feb
	   OMIT	May	# Equivalent to	OMIT May 1 THROUGH May 31
	   OMIT	25 Dec THROUGH 4 Jan
	   OMIT	2023-05-03 THROUGH 2023-05-12
	   OMIT	Jun THROUGH July  # Equivalent to OMIT Jun 1 THROUGH July 31

       The  first example omits	every Saturday and Sunday.  This is useful for
       reminders that shouldn't	trigger	on weekends.

       The second example specifies a holiday that occurs  on  the  same  date
       each year - New Year's Day.

       The  third  example specifies a holiday that changes each year -	Labour
       Day.  For these types of	holidays, you must create an OMIT command  for
       each  year.   (Later, in	the description	of expressions and some	of the
       more advanced features of Remind, you will see how to automate this for
       some cases.)

       As with the REM command,	you can	use shorthand  specifiers  for	dates;
       the following are equivalent:

	    OMIT 7 Sep 1992
	    OMIT 1992-09-07

       For convenience,	you can	use a delta and	MSG or RUN keyword in the OMIT
       command.	 The following sequences are equivalent:

	    OMIT 1 Jan
	    REM	1 Jan +4 MSG New year's	day is %b!

	    and

	    OMIT 1 Jan +4 MSG New year's day is	%b!

       The  THROUGH  keyword  lets you conveniently OMIT a range of days.  For
       example,	the following sequences	are equivalent:

	    OMIT 3 Jan 2011
	    OMIT 4 Jan 2011
	    OMIT 5 Jan 2011

	    and

	    OMIT 3 Jan 2011 THROUGH 5 Jan 2011

       Note that Remind	has a compiled-in limit	to the number of  full	OMITs.
       If you omit a range of N	fully-specified	(ie, year included) days, then
       N full OMITs are	used up.  Trying to omit a very	large range may	result
       in the error "Too many full OMITs"

       You  can	make a THROUGH OMIT do double-duty as a	REM command as long as
       both dates are fully specified

	    OMIT 6 Sep 2010 THROUGH 10 Sep 2010	MSG Vacation

       If you use a THROUGH clause, then either	the year must be supplied  be-
       fore  and after the THROUGH, or it must be missing before and after the
       THROUGH.	 The following are legal:

	   OMIT	25 Dec THROUGH 6 Jan
	   OMIT	25 Dec 2024 THROUGH 6 Jan 2025

       But the following are not:

	   OMIT	25 Dec THROUGH 6 Jan 2025
	   OMIT	25 Dec 2024 THROUGH 6 Jan

       You can debug your global OMITs with the	following command:

	    OMIT DUMP

       The OMIT	DUMP command prints the	current	global omits to	standard  out-
       put.

       THE BEFORE, AFTER AND SKIP KEYWORDS

       Normally,  days	that  are omitted, whether by a	global OMIT command or
       the local OMIT or OMITFUNC keywords in a	REM statement, only affect the
       counting	of the -back or	the +delta.  For example, suppose you  have  a
       meeting	every Wednesday.  Suppose, too,	that you have indicated	11 Nov
       as a holiday:

	    OMIT 11 Nov	+4 MSG Remembrance Day
	    REM	Wed +1 MSG Code	meeting	%b.

       The above sequence will issue a reminder	about a	meeting	for 11	Novem-
       ber 1992, which is a Wednesday.	This is	probably incorrect.  There are
       three options:

       BEFORE This  keyword  moves  the	 reminder  to before any omitted days.
	      Thus, in the above example, use of BEFORE	would cause the	 meet-
	      ing reminder to be triggered on Tuesday, 10 November 1992.

       AFTER  This  keyword  moves the reminder	to after any omitted days.  In
	      the above	example, the meeting reminder would  be	 triggered  on
	      Thursday,	12 November 1992.

       SKIP   This keyword causes the reminder to be skipped completely	on any
	      omitted  days.   Thus,  in the above example, the	reminder would
	      not be triggered on 11 November  1992.   However,	 it  would  be
	      triggered	as usual on the	following Wednesday, 18	November 1992.

       The  BEFORE  and	 AFTER keywords	move the trigger date of a reminder to
       before or after a block of omitted  days,  respectively.	  Suppose  you
       normally	 run  a	backup on the first day	of the month.  However,	if the
       first day of the	month is a weekend or holiday, you run the  backup  on
       the first working day following the weekend or holiday.	You could use:

	    REM	1 OMIT Sat Sun AFTER RUN do_backup

       Let's  examine  how  the	trigger	date is	computed.  The 1 specifies the
       first day of the	month.	The local OMIT keyword causes the  AFTER  key-
       word  to	 move  the reminder forward past weekends.  Finally, the AFTER
       keyword will keep moving	the reminder forward until it has  passed  any
       holidays	specified with global OMIT commands.

THE DO,	INCLUDE	AND SYSINCLUDE COMMANDS
       Remind allows you to include other files	in your	reminder script, simi-
       lar  to	the C preprocessor #include directive.	For example, you might
       organize	different reminders into different files like this:

	       INCLUDE holidays.rem
	       INCLUDE birthdays.rem
	       INCLUDE "quote files with spaces.rem"

       INCLUDE files can be nested up to a depth of 8.	As shown above,	 if  a
       filename	 has spaces in it (not recommended!) you can use double-quotes
       around the filename.

       If you specify a	filename of "-"	in the INCLUDE	command,  Remind  will
       begin reading from standard input.

       If you specify a	directory as the argument to INCLUDE, then Remind will
       process	all  files  (but  not  subdirectories!)	in that	directory that
       match the shell pattern "*.rem".	 The files are processed in sorted or-
       der; the	sort order matches that	used by	 the  shell  when  it  expands
       "*.rem".

       Note that the file specified by an INCLUDE command is interpreted rela-
       tive  to	 the  current working directory	of the Remind process.	If you
       want to include a file relative to the directory	 containing  the  cur-
       rently-processing  file,	 use  DO instead.  For example,	if the current
       file is /home/user/.reminders/foo.rem and Remind's working directory is
       /home/user, then:

	   # Read /home/user/.reminders/bar.rem
	   DO bar.rem

	   # Read /usr/share/bar.rem - absolute	path
	   DO /usr/share/bar.rem

	   # Read /home/user/bar.rem
	   INCLUDE bar.rem

	   # Read /usr/share/bar.rem - absolute	path
	   INCLUDE /usr/share/bar.rem

       Arguably, the INCLUDE command should have worked	the way	DO does	 right
       from  the start,	but changing it	would have broken backward-compatibil-
       ity, hence the introduction of DO.

       Note that if the	currently-processing reminders file was	specified as a
       symbolic	link to	a file that is not in the same directory as  the  sym-
       bolic link itself, DO will fail.	 Remind	does not resolve the real path
       of symbolic links, so you should	avoid using symbolic links to files.

       The  SYSINCLUDE	command	 is  similar  to DO, but it looks for relative
       pathnames under	the  system  directory	containing  standard  reminder
       scripts.	 For this version of Remind, the system	directory is "/usr/lo-
       cal/share/remind".

THE RUN	COMMAND
       If  you include other files in your reminder script, you	may not	always
       entirely	trust the contents of the other	files.	For example, they  may
       contain	RUN-type  reminders that could be used to access your files or
       perform undesired actions.  The RUN command can restrict	this:  If  you
       include	the command RUN	OFF in your top-level reminder script, any re-
       minder or expression that would normally	execute	a  system  command  is
       disabled.   RUN	ON  will  re-enable  the execution of system commands.
       Note that the RUN ON command can	only be	used  in  your	top-level  re-
       minder  script;	it  will not work in any files accessed	by the INCLUDE
       command.	 This is to protect you	from someone placing a RUN ON  command
       in  an  included	file.  However,	the RUN	OFF command can	be used	at top
       level or	in an included file.

       If you run Remind with the -r command-line option,  RUN-type  reminders
       and  the	 shell() function will be disabled, regardless of any RUN com-
       mands in	the reminder script.  However, any command supplied  with  the
       -k option will still be executed.

       In  addition,  Remind  contains a few other security features.  It will
       not read	a file that is group- or world-writable.  It will not run set-
       uid.  If	it reads a file	you don't own, it will	disable	 RUN  and  the
       shell()	function.   And	 if it is run as root, it will only read files
       owned by	root.

       Note that if Remind reads standard input, it does not attempt to	 check
       the  ownership of standard input, even if it is coming from a file, and
       hence does not disable RUN and shell() in this situation.

THE EXPR COMMAND
       Remind lets you completely disable expression evaluation.   This	 could
       be  useful  if  you are running Remind on a somewhat-untrustworthy file
       that is not expected to contain	expressions.   To  disable  expression
       evaluation, use:

	       EXPR OFF

       If  Remind encounters an	expression while EXPR OFF is in	effect,	it re-
       turns an	error

       To re-enable expression evaluation, use:

	       EXPR ON

       As with RUN ON, EXPR ON can be used only	in the top-level  script,  not
       in an included file.

THE INCLUDECMD COMMAND
       Remind allows you to execute a shell command and	evaluate the output of
       that  command  as  if it	were an	included file.	For example, you could
       have scripts that extract reminders out of a database and print them on
       stdout as REM commands.	Here is	an example:

	    INCLUDECMD extract_reminders_for dfs

       We assume that the command "extract_reminders_for"  extracts  reminders
       out  of a central database for the named	user.  Another use-case	of IN-
       CLUDECMD	is if you have your reminders stored in	a file in some non-Re-
       mind format; you	can write a command that  transforms  them  to	Remind
       format  and  then Remind	can "include" the file with an appropriate IN-
       CLUDECMD	command.

       Note that if RUN	is disabled, then INCLUDECMD will fail with the	 error
       message "RUN disabled"

       INCLUDECMD  passes  the	rest of	the line to popen(3), meaning that the
       command is executed by the shell.  As such, shell  meta-characters  may
       need  escaping or arguments quoting, depending on what you're trying to
       do.  Remind itself does not perform any	modification  of  the  command
       line (apart from	the normal [expr] expression-pasting mechanism).

       If  the	command	 passed	 to INCLUDECMD begins with an exclamation mark
       "!", then Remind	disables RUN for the output of the  command.   If  you
       are  running  a	command	whose output you don't quite trust, you	should
       prefix it with "!" so that any RUN commands it emits fail.

       An INCLUDECMD command counts towards the	INCLUDE	 nesting  depth.   For
       any  given Remind run, a	given INCLUDECMD command is only executed once
       and the results are cached.  For	example, if you	generate  a  calendar,
       each  unique INCLUDECMD command is run just once, not once for each day
       of the produced calendar.  "Uniqueness" is determined by	looking	at the
       command that will be passed to the shell, so if (for example) your  IN-
       CLUDECMD	 uses expression-pasting that results in differences depending
       on the value of today(),	then each unique version of the	 command  will
       be executed once.

       If  a  given reminder file contains more	than one identical INCLUDECMD,
       only the	first one will actually	be executed.  All subsequent identical
       ones will use the cached	output from the	first one.

THE BANNER COMMAND
       When Remind first issues	a reminder, it prints a	message	like this:

	    Reminders for Friday, 30th October,	1992 (today):

       (The banner is not printed if any of the	calendar-producing options  is
       used, or	if the -k option is used.)

       The BANNER command lets you change the format.  It should appear	before
       any REM commands.  The format is:

	      BANNER format

       The  format  is	similar	 to  the  body of a REM	command.  It is	passed
       through the substitution	filter,	with an	implicit trigger of  the  cur-
       rent system date.  Thus,	the default banner is equivalent to:

	    BANNER Reminders for %w, %d%s %m, %y%o:

       You can disable the banner completely with BANNER %.  Or	you can	create
       a custom	banner:

	    BANNER Hi -	here are your reminders	for %y-%t-%r:

CONTROLLING THE	OMIT CONTEXT
       Sometimes,  it is necessary to temporarily change the global OMITs that
       are in force for	a few reminders.  Three	commands allow you to do this:

       PUSH-OMIT-CONTEXT
	      This command saves the  current  global  OMITs  on  an  internal
	      stack.

       CLEAR-OMIT-CONTEXT
	      This  command  clears  all of the	global OMITs, starting you off
	      with a "clean slate."

       POP-OMIT-CONTEXT
	      This command restores the	global OMITs that were	saved  by  the
	      most recent PUSH-OMIT-CONTEXT.

       For example, suppose you	have a block of	reminders that require a clear
       OMIT  context,  and that	they also introduce unwanted global OMITs that
       could interfere with later reminders.   You  could  use	the  following
       fragment:

	    PUSH-OMIT-CONTEXT	# Save the current context
	    CLEAR-OMIT-CONTEXT	# Clean	the slate
	    # Block of reminders goes here
	    POP-OMIT-CONTEXT	# Restore the saved omit context

EXPRESSIONS
       In  certain contexts, to	be described later, Remind will	accept expres-
       sions for evaluation.  Remind expressions resemble C  expressions,  but
       operate on different types of objects.

       DATA TYPES

       Remind expressions operate on five types	of objects:

       INT    The  INT data type consists of the integers representable	in one
	      machine word.  The INT data type	corresponds  to	 the  C	 "int"
	      type.

       STRING The  STRING  data	type consists of strings of characters.	 It is
	      somewhat comparable to a C character array, but more closely re-
	      sembles the string type in BASIC.

       TIME   The TIME data type is used for two different purposes:  To  rep-
	      resent a time of day with	one-minute precision or	to represent a
	      duration with one-minute precision.  The context of where	a TIME
	      is used determines whether it is interpreted as a	time of	day or
	      a	duration.

	      In  contexts where a TIME	represents a time of day, it may range
	      from 00:00 to 23:59 and is stored	internally as an integer  from
	      0	to 1439	representing the number	of minutes since midnight.

	      In  contexts where a TIME	represents a duration, there is	no up-
	      per limit	on the hour component (beyond that imposed by the  re-
	      striction	that a duration	expressed in minutes must fit into the
	      signed  integer  type  of	your CPU architecture.)	 Internally, a
	      duration is stored as an integer number of minutes.

       DATE   The DATE data type consists  of  dates  (later  than  1  January
	      1990.)   Internally,  DATE  objects  are stored as the number of
	      days since 1 January 1990.

       DATETIME
	      The DATETIME data	type consists of a  date  and  time  together.
	      Internally, DATETIME objects are stored as the number of minutes
	      since midnight, 1	January	1990.  You can think of	a DATETIME ob-
	      ject as being the	combination of DATE and	TIME parts.

       CONSTANTS

       The following examples illustrate constants in Remind expressions:

       INT constants
	      12, 36, -10, 0, 1209

       STRING constants
	      "Hello there", "This is a	test", "\nHello\tThere", ""

	      Note  that  the  empty string is represented by "".  Remind sup-
	      ports the	escape sequences "\a", "\b", "\f",  "\n",  "\r",  "\t"
	      and  "\v"	 which have the	same meanings as their counterparts in
	      C.  It also supports "\xAB" where	A and B	are  hexadecimal  dig-
	      its;  this  operates just	as in C.  The "\x" must	be followed by
	      one or two hex digits; the escape	sequence "\x00"	is not permit-
	      ted.

	      To include a quote in a string, use "\"".	 Any  other  character
	      preceded	by  a backslash	is inserted into the string as-is, but
	      the backslash itself is removed.	To include a  backslash	 in  a
	      string, use "\\".

       TIME constants
	      12:33, 0:01, 14:15, 16:42, 12.16,	13.00, 1.11, 4:30PM, 12:20am

	      Note  that TIME constants	may be written in 24-hour format or in
	      common "AM/PM" format.  If you use "AM/PM" format, then the hour
	      can range	from 1 to 12.  Either a	period or colon	can be used to
	      separate the minutes from	the hours.  However, Remind will  con-
	      sistently	 output	times in 24-hour format	using only one separa-
	      tor character.  (The output separator  character	is  chosen  at
	      compile-time.)

	      If  the TIME is used where Remind	expects	a time-of-day (for ex-
	      ample, in	an AT clause), then it can be written in 24-hour  for-
	      mat  (ranging  from  00:00  to 23:59) or 12-hour format (ranging
	      from 12:00am to 11:59pm).	 If the	TIME is	used where Remind  ex-
	      pects  a	duration,  it must not have an am or pm	suffix and the
	      hour can be as large as you want,	so long	as the total number of
	      minutes in the duration fits in a	signed integer variable.

	      For convenience, a TIME constant may  be	surrounded  by	single
	      quotes  to  match	 DATE and DATETIME constants, but these	quotes
	      are optional.  That is, 12:56 and	 '12:56'  represent  the  same
	      TIME constant.

       DATE constants
	      DATE  constants  are  expressed as 'yyyy/mm/dd' or 'yyyy-mm-dd',
	      and the single quotes must be supplied.  This distinguishes date
	      constants	from division or subtraction of	integers.  Examples:

	      '1993/02/22', '1992-12-25', '1999/01/01'

	      Note that	DATE values are	printed	without	the quotes.   Although
	      either '-' or '/'	is accepted as a date separator	on input, when
	      dates are	printed, only one will be used.	 The choice of whether
	      to  use '-' or '/' is made at compile-time.  Note	also that ver-
	      sions of Remind prior to 03.00.01	 did  not  support  date  con-
	      stants.	In  those  versions,  you  must	create dates using the
	      date() function.	Also, versions prior to	03.00.02 did not  sup-
	      port the '-' date	separator.

       DATETIME	constants
	      DATETIME	constants  are	expressed  similarly to	DATE constants
	      with the addition	of an "@HH:MM" part,  optionally  followed  by
	      "am" or "pm".  For example:

	      '2008-04-05@23:11',    '1999/02/03@14:06',   '2001-04-07@08:30',
	      '2020-01-01@3:20pm'

	      DATETIME values are printed without  the	quotes.	  Notes	 about
	      date  and	 time separator	characters for DATE and	TIME constants
	      apply also to DATETIME constants.

       ZERO VALUES AND TRUE/FALSE

       All types have an associated zero value,	which is treated as  false  by
       the  IF command,	the IIF	function, and the logical operators.  The zero
       values are:

	      INT - 0

	      DATE - '1990-01-01'

	      TIME - 00:00

	      DATETIME - '1990-01-01@00:00'

	      STRING - "" (the empty string)

       Any value other than the	zero value is treated as true.

       OPERATORS

       Remind has the following	operators.  Operators on the  same  line  have
       equal  precedence, while	operators on lower lines have lower precedence
       than those on higher lines.  The	operators approximately	correspond  to
       C operators.

	    !  -	    (unary logical negation and	arithmetic negation)
	    *  /  %	    (multiplication, division, modulus)
	    +  -	    (addition/concatenation, subtraction)
	    <  <=  >  >=    (comparisons)
	    ==	!=	    (equality and inequality tests)
	    &&		    (logical AND)
	    ||		    (logical OR)

       DESCRIPTION OF OPERATORS

       !      Logical  negation.   Can be applied to any type.	If the operand
	      is non-zero, returns 0.  Otherwise, returns 1.

       -      Unary minus.  Can	be applied to an INT.  Returns the negative of
	      the operand.

       *      Multiplication.  Returns the  product  of	 two  INTs.   Alterna-
	      tively,  if  one	argument is a STRING and the other an INT, re-
	      turns a STRING consisting	of the INT number of  repeats  of  the
	      original STRING.	In this	case, the INT argument cannot be nega-
	      tive.

       /      Integer  division.  Returns the quotient of two INTs, discarding
	      the remainder.

       %      Modulus.	Returns	the remainder upon dividing  one  INT  by  an-
	      other.

       +      Has several uses.	 These are:

	      INT + INT	- returns the sum of two INTs.

	      INT + TIME or TIME + INT - returns a TIME	obtained by adding INT
	      minutes to the original TIME.  The result	will always range from
	      00:00 through 23:59.

	      TIME + TIME treats the second TIME parameter as a	duration, con-
	      verting  it  to  an integer number of minutes past midnight, and
	      then performs addition as	with TIME + INT.

	      INT + DATE or DATE + INT - returns a DATE	obtained by adding INT
	      days to the original DATE.

	      INT + DATETIME or	DATETIME + INT - returns a  DATETIME  obtained
	      by adding	INT minutes to the original DATETIME.

	      DATETIME	+ TIME or TIME + DATETIME treats the TIME parameter as
	      a	duration, converting it	to an integer number of	 minutes  past
	      midnight,	and then performs addition as with DATETIME + INT.

	      STRING  +	STRING - returns a STRING that is the concatenation of
	      the two original STRINGs.

	      STRING + anything	or anything + STRING - converts	the non-STRING
	      argument to a STRING, and	then performs concatenation.  See  the
	      coerce() function.

       -      Has several uses.	 These are:

	      INT - INT	- returns the difference of two	INTs.

	      DATE - DATE - returns (as	an INT)	the difference in days between
	      two DATEs.

	      TIME  - TIME - returns (as an INT) the difference	in minutes be-
	      tween two	TIMEs.

	      DATETIME - DATETIME - returns (as	an INT)	the difference in min-
	      utes between two DATETIMEs.

	      DATE - INT - returns a DATE that is INT days  earlier  than  the
	      original DATE.

	      TIME - INT - returns a TIME that is INT minutes earlier than the
	      original TIME.

	      DATETIME	- INT -	returns	a DATETIME that	is INT minutes earlier
	      than the original	DATETIME.

	      DATETIME - TIME -	coerces	the TIME to an INT and	then  performs
	      subtraction as above.

       <, <=, >, and >=
	      These  are  the comparison operators.  They can take operands of
	      any type,	but both operands must be of the same type.  The  com-
	      parison operators	return 1 if the	comparison is true, or 0 if it
	      is  false.   Note	 that  string comparison is done following the
	      lexical ordering of characters on	your system,  and  that	 upper
	      and lower	case are distinct for these operators.

       ==, != ==  tests	 for  equality,	returning 1 if its operands are	equal,
	      and 0 if they are	not.  != tests for inequality.

	      If the operands are not of the same type,	== returns  0  and  !=
	      returns 1.  Again, string	comparisons are	case-sensitive.

       &&     This is the logical AND operator.	 Returns the second operand if
	      both   operands  are  non-zero.	Otherwise,  returns  whichever
	      operand is zero.	Operands can be	any type and "zero" is	inter-
	      preted as	appropriate for	each operand's type.

       ||     This  is	the logical OR operator.  It returns the first operand
	      that is non-zero;	if both	operands are zero,  then  returns  the
	      second  operand.	 Operands can be any type and "zero" is	inter-
	      preted as	appropriate for	each operand's type.

       NOTES

       If the result of	an addition, subtraction or  multiplication  operation
       would  not fit in a C "int" type, Remind	issues a "Number too high" er-
       ror.  Unlike C, integer operations will not simply give the  wrong  an-
       swer in case of overflow.

       Operators  of equal precedence are always evaluated from	left to	right,
       except where parentheses	dictate	otherwise.  This is important, because
       the enhanced "+"	operator is not	necessarily associative.  For example:

	    1 +	2 + "string" + 3 + 4  yields "3string34"
	    1 +	(2 + "string") + (3 + 4)  yields "12string7"
	    12:59 + 1 +	"test"	yields "13:00test"
	    12:59 + (1 + "test")  yields "12:591test"

       The logical operators are so-called short-circuit  operators,  as  they
       are in C.  This means that if the first operand of || is	true, then the
       second operand is not evaluated.	 Similarly, if the first operand of &&
       is false, then the second operand is not	evaluated.

       VARIABLES

       Remind  allows  you  to assign values to	variables.  The	SET command is
       used as follows:

       SET var expr

       Var is the name of a variable.  It must start with a letter  or	under-
       score,  and  consist only of letters, digits and	underscores.  Only the
       first 64	characters of a	variable name are significant.	Variable names
       are not case sensitive; thus, "Afoo" and	"afOo" are the same  variable.
       Examples:

	    SET	a 10 + (9*8)
	    SET	b "This	is a test"
	    SET	mydir getenv("HOME")
	    SET	time 12:15
	    SET	date today()

       Note  that variables themselves have no type.  They take	on the type of
       whatever	you store in them.

       Variables set with SET or on  the  command-line	with  -ivar=expr  have
       global scope.

       To delete a variable, use the UNSET command:

       UNSET var [var...]

       For example, to delete all the variables	declared above,	use:

	    UNSET a b mydir time date

       SYSTEM VARIABLES

       In  addition  to	the regular user variables, Remind has several "system
       variables" that are used	to query or control the	operating state	of Re-
       mind.  System variables are available starting from version 03.00.07 of
       Remind.

       All system variables begin with a dollar	sign '$'.  They	can be used in
       SET commands and	expressions just as regular variables can.  All	system
       variables always	hold values of a specified type.   In  addition,  some
       system  variables  cannot be modified, and you cannot create new	system
       variables.  System variables can	be initialized	on  the	 command  line
       with  the -i option, but	you may	need to	quote them to avoid having the
       shell interpret the dollar sign.	 System	variable names are  not	 case-
       sensitive.

       The  following  system variables	are defined.  Those marked "read-only"
       cannot be changed with the SET command.	All system variables hold val-
       ues of type INT,	unless otherwise specified.

       $AddBlankLines
	      If set to	1 (the default), then Remind normally prints  a	 blank
	      line  after  the	banner	and  each reminder.  (This can be sup-
	      pressed by ending	the reminder or	banner with a  single  percent
	      sign.)   If  $AddBlankLines  is  set  to 0, then Remind does not
	      print the	blank line.  In	this case, ending a  reminder  with  %
	      has  no  effect.	 If you	do want	a blank	line after a reminder,
	      end it with %_ to	insert a newline.

       $CalcUTC
	      If 1 (the	default), then Remind uses C library functions to cal-
	      culate the number	of minutes between local  and  Universal  Time
	      Coordinated.   This affects astronomical calculations (sunrise()
	      for example.)  If	0, then	you must supply	the number of  minutes
	      between local and	Universal Time Coordinated in the $MinsFromUTC
	      system variable.

       $CalMode	(read-only)
	      If  non-zero,  then  the	-c  option was supplied	on the command
	      line.

       $CalType	(read-only, STRING type)
	      If the -c, -s or -p command-line options were  used,  then  this
	      variable has the value "monthly".	 If -c+, -s+ or	-p+ were used,
	      then "weekly".  Otherwise, "none".

       $Daemon (read-only)
	      If  "daemon mode"	-z was invoked,	contains the number of minutes
	      between wakeups.	If not running in daemon mode, contains	0.  In
	      server mode (either -z0 or -zj), contains	-1.

       $DateSep	(STRING	type)
	      This variable can	be set only to "/" or "-".  It holds the char-
	      acter used to separate portions of a date	when Remind  prints  a
	      DATE or DATETIME value.

       $DedupeReminders
	      If  this	variable is set	to 1, then Remind will suppress	dupli-
	      cate reminders.  A given reminder	is considered to be  a	dupli-
	      cate  of	a  previous one	if it has the exact same trigger date,
	      trigger time, and	body.  By default, this	variable is set	 to  0
	      and Remind does not suppress duplicate reminders.

	      As an example, consider the following reminder file:

		      SET $DedupeReminders 1
		      REM Wednesday MSG	Phooey
		      REM 20 MSG Phooey

	      On  Wednesday,  20  November 2024, only one "Phooey" will	be is-
	      sued.  In	December  of  2024,  "Phooey"  will  be	 issued	 every
	      Wednesday	as well	as on Friday, 20 December 2024

	      If  you  set  $DedupeReminders  to  0, then Remind does not even
	      track reminders to detect	duplicates.   Consider	the  following
	      example:

		      SET $DedupeReminders 0
		      REM Wednesday MSG	Hello
		      SET $DedupeReminders 1
		      REM Wednesday MSG	Hello

	      Every Wednesday, Remind will issue two "Hello" reminders.
	      Because $DedupeReminders was 0 when the first "Hello" was	issued,	it
	      won't be tracked for potential duplicates.

	      Duplicates are detected after all	variable expansion and substitutions
	      have been	done.  Consider	the following:

		      SET $DedupeReminders 1
		      set a "foo"
		      REM MSG [a]
		      set a "bar"
		      REM MSG [a]
		      set a "foo"
		      REM MSG [a]

	      The first	REM will trigger and print "foo".  The second will trigger and
	      print "bar".  The	third will not trigger because it's a duplicate	of the
	      first "foo".

       $DefaultColor (STRING type)
	      This variable can	be set to a string that	has the	form of	three
	      space-separated numbers.	Each number must be an integer from 0 to
	      255, or all three	numbers	must be	-1.  The default value of
	      $DefaultColor is "-1 -1 -1", which suppresses default coloring
	      of MSG-type reminders.  If you set $DefaultColor to any other
	      value, then all MSG-, MSF- and CAL-type reminders	are effectively
	      converted	into SPECIAL COLOR reminders whose color value is specified
	      by $DefaultColor.

	      Unlike other system variables, the value of $DefaultColor	is
	      not preserved between calendar iterations; rather, it is reset
	      to "-1 -1	-1" at the start of each iteration.

       $DefaultPrio
	      The default priority assigned to reminders without a PRIORITY
	      clause.  You can set this	as required to adjust the priorities of
	      blocks of	reminders without having to type priorities for	individual
	      reminders.  At startup, $DefaultPrio is set to 5000; it can range
	      from 0 to	9999.

       $DefaultDelta
	      You can set this variable	to a number from 0 through 10000.  If set to
	      a	non-zero number, then Remind triggers any REM statement
	      that lacks a delta as if it had a	delta of ++$DefaultDelta.
	      By default, $DefaultDelta	is zero.

       $DefaultTDelta
	      The default time delta used if no	+N is given in an AT clause.  This
	      is normally 0, but can be	set with the -tt option	or explicitly
	      set in your script.  If $DefaultDelta is non-zero, you can use an
	      explicit delta of	+0 in an AT clause to countermand the default delta.

       $DeltaOverride (read-only)
	      If non-zero, corresponds to the n	argument given to a
	      -tn command-line option.

       $DontFork (read-only)
	      If non-zero, then	the -c option was supplied on the command line.

       $DontTrigAts (read-only)
	      The number of times that the -a option was supplied on the
	      command line.

       $DontQueue (read-only)
	      If non-zero, then	the -q option was supplied on the command line.

       $EndSent	(STRING	type)
	      Contains a list of characters that end a sentence.  The MSF
	      keyword inserts two spaces after these characters.  Initially,
	      $EndSent is set to ".!?" (period,	exclamation mark, and
	      question mark.)

       $EndSentIg (STRING type)
	      Contains a list of characters that should	be ignored when	MSF
	      decides whether or not to	place two spaces after a sentence.  Initially,
	      is set to	"'>)]}"+CHAR(34) (single-quote,	greater-than, right
	      parenthesis, right bracket, right	brace, and double-quote.)

	      For example, the default values work as follows:

		   MSF He said,	"Huh! (Two spaces will follow this.)"  Yup.

	      because  the  final  parenthesis	and quote are ignored (for the
	      purposes of spacing) when	they follow a period.

       $ExpressionTimeLimit
	      If set to	a non-zero value n, than  any  expression  that	 takes
	      longer  than  n seconds to evaluate will be aborted and an error
	      returned.	 This is to  prevent  maliciously-crafted  expressions
	      for creating a denial-of-service.	 In an included	file, $Expres-
	      sionTimeLimit  can  only	be lowered from	its current value.  In
	      the top-level file, it can be set	to any value,  including  zero
	      to disable the time limit.

       $FirstIndent
	      The number of spaces by which to indent the first	line of	a MSF-
	      type reminder.  The default is 0.

       $FoldYear
	      The  standard Unix library functions may have difficulty dealing
	      with dates later than 2037.  If this variable is set to 1,  then
	      the  UTC	calculations  "fold back" years	later than 2037	before
	      using the	Unix library functions.	  For  example,	 to  find  out
	      whether  or not daylight saving time is in effect	in June, 2077,
	      the year is "folded back"	to 2010, because both years begin on a
	      Monday, and both are non-leapyears.  The rules for daylight sav-
	      ing time are thus	presumed to be identical for both  years,  and
	      the  Unix	 library  functions can	handle 2010.  By default, this
	      variable is 0.  Set it to	1 if the sun or	UTC  functions	misbe-
	      have for years greater than 2037.

       $FormWidth
	      The  maximum  width of each line of text for formatting MSF-type
	      reminders.  The default is the width of the terminal in columns,
	      minus 8, but clamped at a	minimum	of 20 and a  maximum  of  500.
	      If  standard output is not a terminal, then the default is 72.If
	      an MSF-type reminder contains a word too long  to	 fit  in  this
	      width,  it  will	not be truncated - the width limit will	be ig-
	      nored.

       $HushMode (read-only)
	      If non-zero, then	the -h option  was  supplied  on  the  command
	      line.

       $IgnoreOnce (read-only)
	      If  non-zero,  then  the	-o  option was supplied	on the command
	      line, or implicitly enabled for  some  other  reason.   In  this
	      case, ONCE directives will be ignored.

       $InfDelta (read-only)
	      If  non-zero,  then  the	-t  option was supplied	on the command
	      line, with no n argument.

       $IntMax (read-only)
	      The largest representable	INT.  On a machine with	32-bit	signed
	      integers	using  twos-complement	representation,	 this  will be
	      2147483647.

       $IntMin (read-only)
	      The smallest representable INT.  On a machine with 32-bit	signed
	      integers using  twos-complement  representation,	this  will  be
	      -2147483648.

       $Latitude (STRING type)
	      The  latitude  of	your location, expressed as a string that is a
	      floating-point number.  Because Remind does not  have  a	native
	      floating-point  type, we need to express it as a string.	$Lati-
	      tude can range from "-90.0" to  "90.0",  with  positive  numbers
	      representing  points  north  of the equator and negative numbers
	      representing south.  Note	that regardless	of your	locale,	$Lati-
	      tude is always interpreted in the	"C" locale and	as  such,  the
	      decimal point must be a period (".").

       $Longitude (STRING type)
	      The  longitude of	your location, expressed as a string that is a
	      floating-point number.  Because Remind does not  have  a	native
	      floating-point type, we need to express it as a string.  $Longi-
	      tude  can	 range from "-180.0" to	"180.0", with positive numbers
	      representing points east of the Greenwich	Meridian and  negative
	      numbers representing west.  Note that regardless of your locale,
	      $Longitude  is always interpreted	in the "C" locale and as such,
	      the decimal point	must be	a period (".").

	      For example, the coordinates of the Statue  of  Liberty  in  New
	      York City	are approximately set by:

		  SET $Latitude	  "40.68933"
		  SET $Longitude "-74.04454"

       $LatDeg,	$LatMin, $LatSec (DEPRECATED)
	      These  specify the latitude of your location.  $LatDeg can range
	      from -90 to 90, and the others from -59 to 59.   Northern	 lati-
	      tudes  are  positive;  southern ones are negative.  For southern
	      latitudes, all three components should be	negative.  These three
	      variables	are deprecated;	you should use $Latitude instead.

       $Location (STRING type)
	      This is a	string specifying the name of your  location.	It  is
	      usually  the  name of your town or city.	It can be set to what-
	      ever you like, but good style indicates that it should  be  kept
	      consistent with the latitude and longitude system	variables.

       $LongDeg, $LongMin, $LongSec (DEPRECATED)
	      These  specify  the  longitude  of  your location.  $LongDeg can
	      range from -180 to 180.  Western longitudes are positive;	 east-
	      ern  ones	 are  negative.	 Note that all three components	should
	      have the same sign: All positive for western longitudes and  all
	      negative	for eastern longitudes.	 Note that for historical rea-
	      sons, the	sign for longitude is different	from the usual conven-
	      tion!  If	you find the longitude of your location	from a	search
	      engine,  you will	most likely need to invert the sign to have it
	      work correctly with Remind. These	 three	variables  are	depre-
	      cated;  you should use $Longitude	instead.  Note also that $Lon-
	      gitude uses the standard convention of negative for western lon-
	      gitudes and positive for eastern ones.

	      The latitude and longitude information is	required for the func-
	      tions sunrise() and sunset().  Default values  can  be  compiled
	      into  Remind,  or	you can	SET the	correct	values at the start of
	      your reminder scripts.

	      Note that	setting	any of $LongDec, $LongMin and $LongSec updates
	      $Longitude  correspondingly,  and	 setting  $Longitude   updates
	      $LongDeg,	 $LongMin and $LongSec.	 Similar rules apply to	$Lati-
	      tude, $LatDeg, $LatMin and $LatSec.

       $MaxLateMinutes
	      This variable controls how Remind	reacts	to  a  computer	 being
	      suspended	 and  then  woken.   Normally,	if a timed reminder is
	      queued and then the computer suspended, and then the computer is
	      woken after the timed reminder's trigger time, Remind will trig-
	      ger the timer anyway, despite the	fact that the trigger time has
	      already passed.

	      If you set $MaxLateMinutes to a non-zero integer between	1  and
	      1440,  then Remind will not trigger a timed reminder whose trig-
	      ger time is more than $MaxLateMinutes minutes in the past.

	      Note that	Remind uses the	value of $MaxLateMinutes  that	is  in
	      effect  when  it has finished reading the	reminder file and puts
	      itself  in  the	background.    Generally,   you	  should   set
	      $MaxLateMinutes  once  near  the	beginning  of the file and not
	      change it	after that.

       $MaxSatIter
	      The maximum number of iterations for  the	 SATISFY  clause  (de-
	      scribed later.)  Must be at least	10.

       $MaxStringLen
	      A	limit on the longest string that Remind	will allow you to cre-
	      ate.  The	default	is 65535.  If you set $MaxStringLen to 0 or to
	      -1,  then	 remind	 will  allow  you  to  create arbitrarily-long
	      strings, at least	until it runs out of memory.  We do not	recom-
	      mend setting $MaxStringLen to 0 or -1 because it is very easy to
	      write code that DOSes Remind in that case.

       $MinsFromUTC
	      The number of minutes between Universal Time Coordinated and lo-
	      cal time.	 If $CalcUTC is	 non-zero,  this  is  calculated  upon
	      startup  of  Remind.  Otherwise, you must	set it explicitly.  If
	      $CalcUTC is zero,	then $MinsFromUTC is used in the  astronomical
	      calculations.  You must adjust it	for daylight saving time your-
	      self.  Also, if you want to initialize $MinsFromUTC using	the -i
	      command-line option, you must also set $CalcUTC to 0 with	the -i
	      option.

       $NextMode (read-only)
	      If  non-zero,  then  the	-n  option was supplied	on the command
	      line.

       $MaxFullOmits (read-only)
	      The maximum number of full OMITs	allowed	 (a  compiled-in  con-
	      stant.)

       $MaxPartialOmits	(read-only)
	      The  maximum number of partial OMITs allowed (a compiled-in con-
	      stant.)

       $NumFullOmits (read-only)
	      The number of full OMITs in the current OMIT context.

       $NumPartialOmits	(read-only)
	      The number of partial OMITs in the current OMIT context.

       $NumQueued (read-only)
	      Contains the number of reminders queued so  far  for  background
	      timed triggering.

       $NumTrig	(read-only)
	      Contains the number of reminders triggered for the current date.
	      One  use	for  this variable is as follows:  Suppose you wish to
	      shade in the box of a PostScript calendar	whenever a holiday  is
	      triggered.   You	could  save the	value of $NumTrig in a regular
	      variable prior to	executing a block of  holiday  reminders.   If
	      the  value  of  $NumTrig after the holiday block is greater than
	      the saved	value, then at least one holiday  was  triggered,  and
	      you  can execute the command to shade in the calendar box.  (See
	      the section "Calendar Mode".)

	      Note that	$NumTrig is affected only by REM commands; triggers in
	      IFTRIG commands do not affect it.

       $OnceFile (STRING type)
	      If you set this variable to a non-empty string, then rather than
	      using the	file access date to determine whether or not to	run  a
	      ONCE-type	reminder, Remind will maintain a timestamp in the file
	      $OnceFile.   This	is more	reliable than using the	access date of
	      the reminder file.

	      If $OnceFile does	not exist, then	it will	be created  the	 first
	      time  a ONCE keyword is processed.  The file must	be writable by
	      the current user.	 If you	try to set $OnceFile after a ONCE  re-
	      minder  has  already been	processed, Remind will issue a warning
	      and ignore the attempt to	set $OnceFile.

       $ParseUntriggered
	      A	flag indicating	whether	or not Remind should fully  parse  REM
	      statements that are not triggered.  0 means to skip parsing them
	      and 1 (the default) means	to parse them.

	      For example, if we have the following REM	statement:

			  REM 2020-01-01 MSG ["bad_expression" * 2]

	      Then  by	default,  Remind will fully parse the line and issue a
	      "Type mismatch" error even if the	 reminder  is  not  triggered.
	      However,	if $ParseUntriggered is	set to 0, then Remind will not
	      issue the	error except on	2020-01-01, when the reminder is trig-
	      gered.

	      Setting $ParseUntriggered	to 0 may in some  cases	 slightly  im-
	      prove  performance,  at  the risk	of not catching	errors until a
	      reminder is triggered.

       $PrefixLineNo (read-only)
	      If non-zero, then	the -l option  was  supplied  on  the  command
	      line.

       $PSCal (read-only)
	      If  non-zero,  then  the	-p  option was supplied	on the command
	      line.

       $RunOff (read-only)
	      If non-zero, the RUN directives are disabled.

       $SimpleCal (read-only)
	      Set to a non-zero	value if either	of the -p or  -s  command-line
	      options was supplied.

       $SortByDate (read-only)
	      Set  to  0  if no	-g option is used, 1 if	sorting	by date	in as-
	      cending order, or	2 if sorting by	date in	descending order.

       $SortByPrio (read-only)
	      Set to 0 if no -g	option is used,	1 if sorting  by  priority  in
	      ascending	 order,	 or 2 if sorting by priority in	descending or-
	      der.

       $SortByTime (read-only)
	      Set to 0 if no -g	option is used,	1 if sorting by	 time  in  as-
	      cending order, or	2 if sorting by	time in	descending order.

       $SubsIndent
	      The number of spaces by which all	lines (except the first) of an
	      MSF-type reminder	should be indented.  The default is 0.

       $SuppressImplicitWarnings
	      Normally,	 Remind	 issues	a warning if a line begins with	an un-
	      known token and is treated as a REM command, or if a REM command
	      is missing a type	and is treated as a MSG-type  reminder.	  Set-
	      ting  $SuppressImplicitWarnings  to 1 suppresses these warnings.
	      The default is 0 and we do not recommend disabling the warnings.

       $SuppressLRM
	      Normally,	when Remind is run with	the -c option in a  UTF-8  lo-
	      cale,  it	emits a	left-to-right mark sequence after printing day
	      names or reminders.  Some	terminals render this incorrectly,  so
	      you can use:

		  SET $SuppressLRM 1

	      at  the top of your reminder file	to suppress the	LRM sequences,
	      or you can invoke	Remind with the	option '-i$SuppressLRM=1'.

       $SysInclude (read-only, STRING type)
	      A	directory path containing  standard  reminder  scripts.	  Cur-
	      rently,  Remind  ships with some standard	holiday	files and lan-
	      guage packs.  The	value of $SysInclude is	 "/usr/local/share/re-
	      mind" on this installation.

       $T (read-only, DATE type)
	      Exactly equivalent to trigdate().	 (See BUILT-IN FUNCTIONS.)

       $Td (read-only)
	      Equivalent to day(trigdate()).

       $Tm (read-only)
	      Equivalent to monnum(trigdate()).

       $Tw (read-only)
	      Equivalent to wkdaynum(trigdate()).

       $Ty (read-only)
	      Equivalent to year(trigdate()).

       $Tt (read-only, TIME type)
	      Equivalent to trigtime().

       $TimeSep	(STRING	type)
	      This variable can	be set only to ":" or ".".  It holds the char-
	      acter  used  to separate portions	of a time when Remind prints a
	      TIME or DATETIME value.

       $UntimedFirst (read-only)
	      Set to 1 if the -g option	is used	with a fourth  sort  character
	      of "d"; set to 0 otherwise.

       $U (read-only, DATE type)
	      Exactly equivalent to today().  (See BUILT-IN FUNCTIONS.)

       $Ud (read-only)
	      Equivalent to day(today()).

       $Um (read-only)
	      Equivalent to monnum(today()).

       $Uw (read-only)
	      Equivalent to wkdaynum(today()).

       $Uy (read-only)
	      Equivalent to year(today()).

       $UseVTColors (read-only)
	      Set to 1 if the -@ or -cc	options	were used; 0 otherwise.

       $UseBGVTColors (read-only)
	      Set to 1 if the -@,,1 option was used; 0 otherwise.

       $Use256Colors (read-only)
	      Set to 1 if the -@1 option was used; 0 otherwise.

       $UseTrueColors (read-only)
	      Set to 1 if the -@2 option was used; 0 otherwise.

       $TerminalBackground (read-only)
	      Returns  -1 if the terminal background color could not be	deter-
	      mined, 0 if it was found to be dark (or was  specified  as  dark
	      with the -@,0 option) or 1 if it was found to be light (or spec-
	      ified  as	 light with the	-@,1 option.)  The terminal background
	      is considered to be "dark" if the	average	of the red, green  and
	      blue  components is at most 85 out of 255, and if	the maximum of
	      any component is at most 128 out of 255.

       Note:  If any of	the calendar modes are in effect, then the  values  of
       $Daemon,	 $DontFork,  $DontTrigAts, $DontQueue, $HushMode, $IgnoreOnce,
       $InfDelta, and $NextMode	are not	meaningful.

       BUILT-IN	FUNCTIONS

       Remind has a plethora of	built-in functions.  The syntax	for a function
       call is the same	as in C	- the function name,  followed	a  comma-sepa-
       rated  list  of arguments in parentheses.  Function names are not case-
       sensitive.  If a	function takes no arguments, it	must  be  followed  by
       "()"  in	 the  function call.  Otherwise, Remind	will interpret it as a
       variable	name, and probably not work correctly.

       In the descriptions below, short	forms are used	to  denote  acceptable
       types for the arguments.	 The characters	"i", "s", "d", "t" and "q" de-
       note  INT, STRING, DATE,	TIME and DATETIME arguments, respectively.  If
       an argument can be one of several types,	the  characters	 are  concate-
       nated.  For example, "di_arg" denotes an	argument that can be a DATE or
       an INT.	"x_arg"	denotes	an argument that can be	of any type.  The type
       of  the	argument is followed by	an underscore and an identifier	naming
       the argument.

       The built-in functions are:

       _(s_message)
	      Returns the translation table entry for message.	If there is no
	      such translation table entry, then returns  message  unmodified.
	      For example, consider this sequence:

		      TRANSLATE	"Goodbye" "Tot ziens"
		      SET a _("Goodbye")

	      After those two lines have been executed,	the variable a will be
	      set  to  "Tot ziens".  See the section THE TRANSLATION TABLE for
	      more information.

	      In the body of a reminder, the substitution sequence %(text)  is
	      (almost)	the equivalent of [_("text")].	Therefore, the follow-
	      ing reminders are	almost equivalent:

		      REM MSG %(Goodbye)
		      REM MSG [_("Goodbye")]

	      The only difference is that if _("Goodbye") contains a  %	 sign,
	      then  that  result  will be run through the substitution filter,
	      whereas in the first reminder, it	will not.  That	is because the
	      second REM command performs expression  pasting  followed	 by  a
	      substitution  filter  pass,  while  the  first  one performs the
	      translation as part of the substitution  filter  (and  does  not
	      make a second substitution filter	pass.)

       abs(i_num)
	      Returns the absolute value of num.

       access(s_file, si_mode)
	      Tests  the  access permissions for the file file.	 Mode can be a
	      string, containing a mix of the characters "rwx" for read, write
	      and execute permission testing.  Alternatively, mode  can	 be  a
	      number  as  described  in	 the  UNIX access(2) system call.  The
	      function returns 0 if the	file can be accessed with  the	speci-
	      fied mode, and -1	otherwise.

       adawn([dq_date])
	      Returns  the  time of "astronomical dawn"	on the specified date.
	      If date is omitted, defaults to today().	If a  datetime	object
	      is supplied, only	the date component is used.

       adusk([dq_date])
	      Returns  the  time  of  "astronomical twilight" on the specified
	      date.  If	date is	omitted, defaults to today().

       ampm(tq_time [,s_am [,s_pm [,i_lz]]])
	      Returns a	STRING that is the result of converting	time (which is
	      either a TIME or a DATETIME object) to "AM/PM" format.  The  op-
	      tional  arguments	 am and	pm are the strings to append in	the AM
	      and PM case, respectively; they default to "AM" and  "PM".   The
	      optional argument	lz specifies whether or	not the	hour should be
	      padded to	two digits with	a leading zero.	 If lz is zero,	then a
	      leading 0	is not added; otherwise, the hour is padded out	to two
	      digits  with  a  leading	zero.  If not supplied,	lz defaults to
	      zero.

	      The function obeys the system variables $DateSep,	 $TimeSep  and
	      $DateTimeSep when	formatting its output.	Here are some examples
	      of its output:

		      ampm(0:22)		 returns "12:22AM"
		      ampm(17:45, "am",	"pm")	 returns "5:45pm"
		      ampm(17:45, "am",	"pm", 1) returns "05:45pm"
		      ampm('2020-03-14@21:34')	 returns "2020-03-14@9:34PM"

       ansicolor(i_red,	i_green, i_blue	[,i_bg [,i_clamp]])
	      Returns  a  STRING  that	contains  an  ANSI escape sequence for
	      changing the terminal text color.	 The parameters	red, green and
	      blue are integers	from 0 to 255 specifying the value of the  re-
	      spective	color  component.  As a	special	case, all three	values
	      can be -1, in which case the ANSI	sequence "ESC[0m" is returned,
	      which resets all text attributes to normal.

	      The string returned by ansicolor depends on the color mode  that
	      Remind  is  running in, as specified by the -@ option.  If color
	      mode is not enabled, then	ansicolor  always  returns  the	 empty
	      string.  Otherwise, it returns the escape	sequence that best ap-
	      proximates the color according to	the -@ color mode.

	      The  optional bg argument	is either 0 or 1.  If 0	(the default),
	      then the foreground color	is set.	 If  1,	 then  the  background
	      color is set.  Note that setting the background color only works
	      in 256-color or true-color mode.

	      The  optional  clamp  argument  is either	0 or 1.	 If 0 (the de-
	      fault), then colors are not adjusted based on the	terminal back-
	      ground color.  If	1, then	Remind	attempts  to  adjust  dark  or
	      bright  colors so	they have enough contrast to be	visible	in the
	      terminal.

	      The first	three arguments	may alternatively be  specified	 as  a
	      string  consisting  of three space-separated numbers, as in this
	      example: "128 128	0"

	      As  a  special  case,  ansicolor("")  is	equivalent  to	 ansi-
	      color(-1,-1,-1)  and returns the ANSI sequence to	reset all text
	      attributes to normal.

	      Note that	inserting ANSI color sequences in calendar  mode  will
	      produce garbled results.	Therefore, we recommend	defining func-
	      tions  such  as  the  ones below that return the empty string in
	      calendar mode:

		      IF $CalMode
			  FSET fg(r,g,b) ""
			  FSET bg(r,g,b) ""
		      ELSE
			  FSET fg(r,g,b) ansicolor(r,g,b)
			  FSET bg(r,g,b) ansicolor(r,g,b,1)
		      ENDIF
		      REM [fg(255,0,0)][bg(64,64,64)]Red on Gray[fg(-1,-1,-1)] in normal mode
		      REM SPECIAL COLOR	0 255 0	Green in normal	and calendar mode

	      If you use the ansicolor function, don't	forget	to  reset  the
	      color  back to normal with ansicolor(-1,-1,-1) or	subsequent re-
	      minders will continue to be colored.

       args(s_fname)
	      Returns the number of arguments  expected	 by  the  user-defined
	      function	fname,	or -1 if no such user-defined function exists.
	      Note that	this function examines	only  user-defined  functions,
	      not built-in functions.  Its main	use is to determine whether or
	      not  a  particular user-defined function has been	defined	previ-
	      ously.  The args() function is available only in versions	of Re-
	      mind from	03.00.04 and up.

       asc(s_string)
	      Returns an INT that is the ASCII code of the first character  in
	      string.	As  a  special	case,  asc("")	returns	 0.  For UTF-8
	      strings, this will return	the UTF-8 byte with which  the	string
	      begins, which is not likely to be	very useful (and may indeed be
	      negative on machines where char is a signed type.)

       baseyr()
	      Returns  the "base year" that was	compiled into Remind (normally
	      1990.)  All dates	are stored internally as the  number  of  days
	      since 1 January of baseyr().

       char(i_i1 [,i_i2...])
	      This  function can take any number of INT	arguments.  It returns
	      a	STRING consisting of the bytes specified by the	arguments.  It
	      is easy to create	invalid	UTF-8 sequences; char does  not	 check
	      for  this.   Note	 that  none  of	the arguments can be 0,	unless
	      there is only one	argument.  As a	special	case, char(0)  returns
	      "".

       choose(i_index, x_arg1 [,x_arg2...])
	      Choose  must  take at least two arguments, the first of which is
	      an INT.  If index	is n, then the nth subsequent argument is  re-
	      turned.  If index	is less	than 1,	then arg1 is returned.	If in-
	      dex is greater than the number of	subsequent arguments, then the
	      last argument is returned.  Examples:

		 choose(0, "foo", 1:13,	1000) returns "foo"
		 choose(1, "foo", 1:13,	1000) returns "foo"
		 choose(2, "foo", 1:13,	1000) returns 1:13
		 choose(3, "foo", 1:13,	1000) returns 1000
		 choose(4, "foo", 1:13,	1000) returns 1000

	      Note  that  only	the  first  argument and the chosen result are
	      evaluated.  Any non-chosen arguments will	not be evaluated.

       coerce(s_type, x_arg)
	      This function converts arg to the	specified type,	if  such  con-
	      version  is  possible.   Type  must  be  one of "INT", "STRING",
	      "DATE", "TIME" or	"DATETIME" (case-insensitive).	The conversion
	      rules are	as follows:

	      If arg is	already	of the type  specified,	 it  is	 returned  un-
	      changed.

	      If  type is "STRING", then arg is	converted to a string consist-
	      ing of its printed representation.

	      If type is "DATE", then an INT arg is converted by  interpreting
	      it as the	number of days since 1 January baseyr().  A STRING arg
	      is  converted  by	 attempting to read it as if it	were a printed
	      date.  A DATETIME	is converted to	a date by  dropping  the  time
	      component.  A TIME arg cannot be converted to a date.

	      If  type is "TIME", then an INT arg is converted by interpreting
	      it as the	number of minutes since	midnight.   A  STRING  arg  is
	      converted	by attempting to read it as if it were a printed time.
	      A	 DATETIME  is  converted to a time by dropping the date	compo-
	      nent.  A DATE arg	cannot be converted to a time.

	      If type is "DATETIME", then an INT arg is	 converted  by	inter-
	      preting  it  as  the number of minutes since midnight, 1 January
	      baseyr().	 A STRING is converted by attempting to	read it	as  if
	      it  were a printed datetime.  Other types	cannot be converted to
	      a	datetime.

	      If type is "INT",	then DATE, TIME	 and  DATETIME	arguments  are
	      converted	 using	the  reverse of	procedures described above.  A
	      STRING arg is converted by parsing it as an integer.

       columns([s_arg])
	      If called	with no	arguments, columns() behaves  as  follows:  If
	      standard	output	is a TTY, returns the width of the terminal in
	      columns.	If standard output is not  a  TTY,  attempts  to  open
	      "/dev/tty"  to obtain the	terminal size.	If this	fails, returns
	      -1.

	      If called	with a single string  argument,	 columns(str)  returns
	      the  number of columns str will occupy if	printed	to a terminal.
	      ANSI color-changing sequences occupy zero	columns	 whereas  some
	      Unicode  characters  occupy two columns.	columns(str) takes all
	      of that into account.  Note that if Remind was compiled  without
	      Unicode support, columns(str) returns a type mismatch error.

       current()
	      Returns  the  current  date and time as a	DATETIME object.  This
	      may be the actual	date and time, or may be  the  date  and  time
	      supplied on the command line.

       date(i_y, i_m, i_d)
	      The  date()  function returns a DATE object with the year, month
	      and day components specified by y, m and d.

       datepart(dq_datetime)
	      Returns a	DATE object representing the date portion of datetime.

       datetime(args)
	      The datetime() function can take anywhere	from two to five argu-
	      ments.  It always	returns	a DATETIME generated  from  its	 argu-
	      ments.

	      If  you  supply  two arguments, the first	must be	a DATE and the
	      second a TIME.

	      If you supply three arguments, the first must be a DATE and  the
	      second  and  third must be INTs.	The second and third arguments
	      are interpreted as hours and minutes and converted to a TIME.

	      If you supply four arguments, the	first three must be INTs,  in-
	      terpreted	 as the	year, month and	day.  The fourth argument must
	      be a TIME.

	      Finally, if you supply five arguments, they must all be INTs and
	      are interpreted as year, month, day, hour	and minute.

       dawn([dq_date])
	      Returns the time of "civil dawn" on the specified	date.  If date
	      is omitted, defaults to today().	If a datetime object  is  sup-
	      plied, only the date component is	used.

       day(dq_date)
	      This  function  takes a DATE or DATETIME as an argument, and re-
	      turns an INT that	is the day-of-month component of date.

       daysinmon(i_m, i_y)
	      Returns the number of days in month m (1-12) of the year y.

       defined(s_var)
	      Returns 1	if the variable	named by var is	defined, or 0 if it is
	      not.
	      Note that	defined() takes	a STRING argument; thus, to  check  if
	      variable X is defined, use:

			defined("X")

	      and not:

			defined(X)

	      The  second  example will	attempt	to evaluate X, and will	return
	      an error if it is	undefined or not of type STRING.

       dosubst(s_str [,d_date [,t_time]]) or dosubst(s_str [,q_datetime])
	      Returns a	STRING that is the result of passing str  through  the
	      substitution  filter described earlier.  The parameters date and
	      time (or datetime) establish the effective trigger date and time
	      used by the substitution filter.	If date	and time are  omitted,
	      they default to today() and now().

	      Note that	if str does not	end with "%", a	newline	character will
	      be added to the end of the result.  Also,	calling	dosubst() with
	      a	 date  that is in the past (i.e., if date < today()) will pro-
	      duce undefined results.

	      Dosubst()	is only	available starting from	 version  03.00.04  of
	      Remind.

       dusk([dq_date])
	      Returns  the time	of "civil twilight" on the specified date.  If
	      date is omitted, defaults	to today().

       easterdate([dqi_arg])
	      If arg is	an INT,	then returns the date of Easter	Sunday for the
	      specified	year.  If arg is a DATE	or DATETIME, then returns  the
	      date  of the next	Easter Sunday on or after arg.	(The time com-
	      ponent of	a datetime is ignored.)	 If arg	is  omitted,  then  it
	      defaults to today().

	      Note  that  easterdate computes the Western Easter.  For the Or-
	      thodox Easter date, see orthodoxeaster.

       escape(s_string [,i_add_quotes])
	      Returns a	STRING that is the same	as the input string, but  with
	      all  special  characters	backslashed-escaped.  For example, the
	      following	command:

		      set a escape("foo" + char(10) + "bar")

	      will set a to "foo\nbar" where "\n" is the literal sequence  "\"
	      followed by "n".	This is	useful if you want to compute a	string
	      in  a  pasted-in	expression  that  Remind  will then parse as a
	      quoted string again, such	as in a	TRANSLATE command or  an  INFO
	      clause.

	      If the optional add_quotes argument is supplied and is non-zero,
	      then  the	return value from escape will include surrounding dou-
	      ble-quotes.

       evaltrig(s_trigger [,dq_start])
	      Evaluates	trigger	as if it were a	REM or IFTRIG trigger specifi-
	      cation and returns the trigger date as a DATE (or	as a  DATETIME
	      if there is an AT	clause.)  Returns a negative INT if no trigger
	      could be computed.

	      Normally,	 evaltrig  finds a trigger date	on or after today.  If
	      you supply the start  argument,  then  it	 scans	starting  from
	      there.

	      For example, the expression:

		evaltrig("Mon 1", '2008-10-07')

	      returns '2008-11-03', since that is the first date on or after 7
	      October 2008 that	satisfies "Mon 1".

	      If  you want to see how many days	it is from the first Monday in
	      October, 2008 to the first Monday	in November, 2008, use:

		evaltrig("Mon 1", '2008-11-01')	- evaltrig("Mon	1", '2008-10-01')

	      and the answer is	28.  The trigger argument to evaltrig can have
	      all the usual trigger clauses (OMIT, AT, SKIP, etc.) but	cannot
	      have a SATISFY, MSG, etc.	reminder-type clause.

       filedate(s_filename)
	      Returns the modification date of filename.  If filename does not
	      exist,  or  its  modification  date is before the	year baseyr(),
	      then 1 January of	baseyr() is returned.

       filedatetime(s_filename)
	      Returns the modification date and	time of	filename.  If filename
	      does not exist, or its modification  date	 is  before  the  year
	      baseyr(),	then midnight, 1 January of baseyr() is	returned.

       filedir()
	      Returns  the  directory  that  contains  the  current file being
	      processed.  It may be a relative or absolute  pathname,  but  is
	      guaranteed  to  be correct for use in an INCLUDE command as fol-
	      lows:

		 INCLUDE [filedir()]/stuff

	      This includes the	file "stuff" in	the same directory as the cur-
	      rent file	being processed.  Note	that  this  workaround	is  no
	      longer necessary because DO stuff	will achieve the same goal.

	      Note  that if the	currently-processing reminders file was	speci-
	      fied as a	symbolic link, then filedir()  returns	the  directory
	      containing  the  symbolic	 link and not the directory containing
	      the target of the	symbolic link.	You should  avoid  using  sym-
	      bolic  links to files unless both	the symbolic link and its tar-
	      get happen to be in the same directory.

       filename()
	      Returns (as a  STRING)  the  name	 of  the  current  file	 being
	      processed	by Remind.  Inside included files, returns the name of
	      the included file.

       getenv(s_envvar)
	      Similar  to  the getenv(2) system	call.  Returns a string	repre-
	      senting the value	of the specified  environment  variable.   Re-
	      turns  ""	if the environment variable is not defined.  Note that
	      the names	of environment variables are generally case-sensitive;
	      thus, getenv("HOME") is not the same as getenv("home").

       hebdate(i_day, s_hebmon [,idq_yrstart [,i_jahr [,i_aflag]]])
	      Support for Hebrew dates - see the section "THE HEBREW CALENDAR"

       hebday(dq_date)
	      Support for Hebrew dates - see the section "THE HEBREW CALENDAR"

       hebmon(dq_date)
	      Support for Hebrew dates - see the section "THE HEBREW CALENDAR"

       hebyear(dq_date)
	      Support for Hebrew dates - see the section "THE HEBREW CALENDAR"

       hour(tq_time)
	      Returns the hour component of time.

       htmlescape(s_str)
	      Returns a	modified copy  of  str	where  "<"  is	replaced  with
	      "&lt;";  ">"  is	replaced  with "&gt;" and "&" is replaced with
	      "&amp;"

       htmlstriptags(s_str)
	      Returns a	modified copy of str where HTML	tags are stripped out.
	      The stripping algorithm is fairly	 naive;	 the  function	starts
	      stripping	 characters  when  it  encounters  a  "<" and it stops
	      stripping	when it	encounters a ">".

       iif(x_test1, x_arg1, [x_test2, x_arg2,...], x_default)
	      If test1 is true,	returns	arg1.  Otherwise, if  test2  is	 true,
	      returns  arg2,  and  so  on.   If	 all of	the test arguments are
	      false, returns default.  Note that only those  arguments	needed
	      to  determine the	final result are evaluated.  This function ac-
	      cepts an odd number of arguments - note that  prior  to  version
	      03.00.05	of  Remind, it accepted	3 arguments only.  The 3-argu-
	      ment version of iif() is compatible with	previous  versions  of
	      Remind.

       index(s_search, s_target	[,i_start)
	      Returns  an  INT	that  is  the location of target in the	string
	      search.  The first character of a	string is numbered 1.  If tar-
	      get does not exist in search, then 0 is returned.

	      The optional parameter start specifies the position in search at
	      which to start looking for target.

       isany(arg1 [,arg2, ..., argN]);
	      Returns 1	if the first argument arg1 is equal to any of the sub-
	      sequent arguments	arg2 through argN; returns 0 otherwise.	  Also
	      returns 0	if called with only one	argument.

	      As an example, the following two expressions are equivalent:

		      (a == b) || (a ==	c) || (a == d) || (a ==	e)

		      isany(a, b, c, d,	e)

       isdst([d_date [,t_time]]) or isdst(q_datetime)
	      Returns  a  positive number if daylight saving time is in	effect
	      on the specified date and	time.  Date defaults  to  today()  and
	      time defaults to midnight.

	      Note  that  this	function is only as reliable as	the C run-time
	      library  functions.   It	is  available  starting	 with  version
	      03.00.07 of Remind.

       isleap(idq_arg)
	      Returns 1	if arg is a leap year, and 0 otherwise.	 Arg can be an
	      INT,  DATE  or  DATETIME	object.	 If a DATE or DATETIME is sup-
	      plied, then the year component is	used in	the test.

       isomitted(dq_date)
	      Returns 1	if date	is omitted, given the current global OMIT con-
	      text.  Returns 0 otherwise.  (If a datetime  is  supplied,  only
	      the  date	 part  is used.)  Note that any	local OMIT or OMITFUNC
	      clauses are not taken into account by this function.

       language()
	      Returns a	STRING naming the compiled-in  language	 supported  by
	      Remind.	Remind	used  to support compiled-in support for other
	      languages, but now all localization is  done  at	run-time.   As
	      such,  this function always returns "English".  However, the ex-
	      pression _("LANGID") returns the two-character ISO 639  language
	      code  of any language pack in effect, assuming the language pack
	      author has written the localization correctly!

       localtoutc(q_datetime)
	      Given a DATETIME object interpreted in the local time zone,  re-
	      turn a DATETIME object that expresses the	same time in UTC.

       lower(s_string)
	      Returns  a  STRING with all upper-case characters	in string con-
	      verted to	lower-case.

       max(x_arg1 [,x_arg2...)
	      Can take any number of arguments,	and returns the	maximum.   The
	      arguments	 can be	of any type, but must all be of	the same type.
	      They are compared	as with	the > operator.

       min(x_arg1 [,x_arg2...)
	      Can take any number of arguments,	and returns the	minimum.   The
	      arguments	 can be	of any type, but must all be of	the same type.
	      They are compared	as with	the < operator.

       minsfromutc([d_date [,t_time]]) or minsfromutc(q_datetime)
	      Returns the number of minutes from  Universal  Time  Coordinated
	      (formerly	 GMT)  to  local  time on the specified	date and time.
	      Date defaults to today() and time	defaults to midnight.  If  lo-
	      cal  time	is before UTC, the result is negative.	Otherwise, the
	      result is	positive.

	      Note that	this function is only as reliable as  the  C  run-time
	      library  functions.   It	is  available  starting	 with  version
	      03.00.07 of Remind.

       minute(tq_time)
	      Returns the minute component of time.

       mon(dqi_arg)
	      If arg is	of DATE	or DATETIME type, returns a string that	 names
	      the month	component of the date.	If arg is an INT from 1	to 12,
	      returns a	string that names the month.

       monnum(dq_date)
	      Returns an INT from 1 to 12, representing	the month component of
	      date.

       moondate(i_phase	[,d_date [,t_time]]) or	moondate(i_phase, q_datetime)
	      This  function  returns  the date	of the first occurrence	of the
	      phase phase of the moon on or after date and  time.   Phase  can
	      range  from 0 to 3, with 0 signifying new	moon, 1	first quarter,
	      2	full moon, and 3 third quarter.	 If date is  omitted,  it  de-
	      faults to	today().  If time is omitted, it defaults to midnight.

	      For  example,  the  following  returns the date of the next full
	      moon:

			SET fullmoon moondate(2)

       moontime(i_phase	[,d_date [,t_time]]) or	moontime(i_phase, q_datetime)
	      This function returns the	time of	the first  occurrence  of  the
	      phase  phase  of	the moon on or after date and time.  Phase can
	      range from 0 to 3, with 0	signifying new moon, 1 first  quarter,
	      2	 full  moon,  and 3 third quarter.  If date is omitted,	it de-
	      faults to	today().  If time is omitted, it defaults to midnight.
	      Moontime() is intended to	be  used  in  conjunction  with	 moon-
	      date().  The moondate() and moontime() functions are accurate to
	      within  a	 couple	 of  minutes of	the times in "Old Farmer's Al-
	      manac" for Ottawa, Ontario.

	      For example, the following returns the date and time of the next
	      full moon:

			MSG Next full moon at [moontime(2)] on [moondate(2)]

       moondatetime(i_phase [,d_date [,t_time]]) or moondatetime(i_phase,
       q_datetime)
	      This function is similar to moondate and moontime, but returns a
	      DATETIME result.

       moonphase([d_date [,t_time]]) or	moonphase(q_datetime)
	      This function returns the	phase of the moon on  date  and	 time,
	      which  default  to  today() and midnight,	respectively.  The re-
	      turned value is an integer from 0	to 359,	representing the phase
	      of the moon in degrees.  0 is a new moon,	180 is a full moon, 90
	      is first-quarter,	etc.

       moonrise([d_date])
	      This function returns a DATETIME result giving the date and time
	      of the first moonrise on or after	midnight on date.  If date  is
	      not supplied, it defaults	to today().

	      Note  that  it is	not uncommon for a day to have no moonrise, so
	      the date part of the return value	may not	be  the	 same  as  the
	      date argument.  So if you	want a calendar	of moonrise times, you
	      could use	something like this:

		  SET mr moonrise()
		  IF datepart(mr) == today()
		      REM NOQUEUE [mr] MSG Moon	rises at %3.
		  ELSE
		      REM MSG No moonrise today
		  ENDIF

       moonrisedir([d_date])
	      This  function  returns  an INT result giving the	direction from
	      which the	moon will rise on the first moonrise on	or after  mid-
	      night on date.  If date is not supplied, it defaults to today().
	      The  return  value ranges	from 0 to 359, where 0 is North, 90 is
	      East, 180	is South and 270 is West.

       moonset([d_date])
	      This function is analogous to moonrise() but returns  the	 DATE-
	      TIME of the next moonset on or after midnight on date.

       moonsetdir([d_date])
	      This  function is	analogous to moonrisedir() but returns the di-
	      rection of moonset.

       multitrig(s_trig1 [,s_trig2, [... s_trigN]])
	      multitrig	evaluates each string as a trigger, similar  to	 eval-
	      trig,  and returns the earliest trigger date that	is on or after
	      today().	multitrig is similar to	trig  but  has	the  following
	      difference:

	      trig  returns  the  first	trigger	date that would	have triggered
	      today, whereas multitrig returns the earliest trigger date later
	      than today, regardless of	whether	it would have triggered	today.

	      If no trigger can	be computed that is later than	today(),  then
	      multitrig	returns	1990-01-01.

	      Consider	the following examples,	assuming that today is Sunday,
	      24 March 2024:

		 # Returns 1990-01-01 because neither would trigger today
		 SET a trig("Mon", "Wed")

		 # Returns 2024-03-25 because it's the earlier trigger date
		 SET a multitrig("Mon",	"Wed")

		 # Returns 2024-03-27 because it's the first that would	trigger	today
		 SET a trig("Wed +3", "Mon +3")

		 # Returns 2024-03-25 because it's the earlier trigger date
		 SET a multitrig("Wed +3", "Mon	+3")

		 # Returns 1990-01-01 because all triggers have	expired
		 SET a multitrig("2000", "2022", "1998", "2023")

	      In general, multitrig works better  with	the  Remind  algorithm
	      than  trig  and should be	used most of the time.	As an example,
	      this reminder is issued at the end of each quarter:

		      REM [multitrig("Mar 31", "Jun 30", "Sep 30", "Dec	31")] +7 MSG \
		      %"End of [ord($Tm/3)] quarter%" is %b.

	      If you want the last working day of each quarter,	you could use:

		      PUSH-OMIT-CONTEXT
		      OMIT Sat Sun
		      REM [multitrig("Mar ~1", "Jun ~1", "Sep ~1", "Dec	~1")] +7 MSG \
		      %"Last working day of [ord($Tm/3)] quarter%" is %b.
		      POP-OMIT-CONTEXT

	      Note that	unlike evaltrig, multitrig always returns a  DATE  and
	      never  a DATETIME.  Including an AT clause in a trigger supplied
	      to multitrig will	result in an error.

       ndawn([dq_date])
	      Returns the time of "nautical dawn" on the specified  date.   If
	      date  is	omitted, defaults to today().  If a datetime object is
	      supplied,	only the date component	is used.

       ndusk([dq_date])
	      Returns the time of "nautical twilight" on the  specified	 date.
	      If date is omitted, defaults to today().

       nonomitted(dq_start, dq_end [, i_step] [,s_wkday...])
	      This  function  returns  the  number of non-omitted days between
	      start and	end.  If start is non-omitted,	then  it  is  counted.
	      end is never counted.

	      Note  that  if  end is less than start, the arguments are	effec-
	      tively swapped, so counting always begins	from the older date.

	      If the third argument to nonomitted is an	INT, then it  must  be
	      greater  than  zero,  and	 is considered to be the step by which
	      nonomitted counts.  For example the following expression:

		      nonomitted('2023-07-01', '2023-07-29', 7)

	      returns the number of non-omitted	Saturdays from	2023-07-01  up
	      to   (but	 not  including)  2023-07-29.	(Both  2023-07-01  and
	      2023-07-29 are Saturdays.)

	      If no step argument is supplied, then a step of 1	is used.

	      In addition to using the global OMIT context, you	can supply ad-
	      ditional arguments that are names	of  weekdays  to  be  omitted.
	      However,	in  a  REM  command,  any local	OMITFUNC clause	is not
	      taken into account by this function.

	      For example, the following line sets a to	11 (assuming no	global
	      OMITs):

		   set a nonomitted('2007-08-01', '2007-08-16',	"Sat", "Sun")

	      because Thursday,	16 August 2007 is the 11th  working  day  (not
	      counting Saturday	and Sunday) after Wednesday, 1 August 2007.

	      nonomitted has various uses.  For	example, many schools run on a
	      six-day cycle and	the day	number is not incremented on holidays.
	      Suppose  the  school year	starts with Day	1 on 4 September 2007.
	      The following reminder will label	day numbers in a calendar:

		 IF today() >= '2007-09-04'
		     set daynum	nonomitted('2007-09-04', today(), "Sat", "Sun")
		     REM OMIT SAT SUN SKIP CAL Day [(daynum % 6) + 1]
		 ENDIF

	      Obviously, the answer you	get from  nonomitted  depends  on  the
	      global  OMIT context.  If	you use	movable	OMITs, you may get in-
	      consistent results.

	      Here is a	more complex use for nonomitted.  My  garbage  collec-
	      tion  follows two	interleaved 14-day cycles: One Friday, garbage
	      and paper	recycling ("Black Box")	are collected.	The next  Fri-
	      day,  garbage  and plastic recycling ("Blue Box")	are collected.
	      If any of	Monday-Friday is a holiday, collection is delayed  un-
	      til the Saturday.	 Here's	a way to encode	these rules:

		 fset _garbhol(x) wkdaynum(x) == 5 && nonomitted(x-4, x+1) < 5
		 REM 12	November 1999 *14 AFTER	OMITFUNC _garbhol MSG Black Box
		 REM 19	November 1999 *14 AFTER	OMITFUNC _garbhol MSG Blue Box

	      Here's  how it works:  The _garbhol(x) user-defined function re-
	      turns 1 if and only if (1) x is a	Friday and  (2)	 there	is  at
	      least one	OMITted	day from the previous Monday up	to and includ-
	      ing the Friday.

	      The first	REM statement sets up the 14-day black-box cycle.  The
	      AFTER keyword makes it move collection to	the Saturday if	_garb-
	      hol  returns  1.	 The  second  REM statement sets up the	14-day
	      blue-box cycle with a similar adjustment made by AFTER  in  con-
	      junction with _garbhol.

       now()  Returns  the  current  system time, as a TIME type.  This	may be
	      the actual time, or a time supplied on the command line.

       ord(i_num)
	      Returns a	string that is the ordinal number num.	 For  example,
	      ord(2) returns "2nd", and	ord(213) returns "213th".

       orthodoxeaster([dqi_arg])
	      If  arg is an INT, then returns the date of Orthodox Easter Sun-
	      day for the specified year.  If arg is a DATE or DATETIME,  then
	      returns  the date	of the next Orthodox Easter Sunday on or after
	      arg.  (The time component	of a datetime is ignored.)  If arg  is
	      omitted, then it defaults	to today().

	      Note  that orthodoxeaster	computes the Orthodox Easter.  For the
	      Western Easter date, see easterdate.

       ostype()
	      Returns "UNIX".  Remind used to run on OS/2 and MS-DOS, but does
	      not any longer.

       pad(x_arg, s_padstr, i_len [, i_right])
	      Converts the first argument arg to a string  if  necessary,  and
	      then  if it is shorter than len characters, pads to to len char-
	      acters using as many copies (including partial copies) of	padstr
	      as necessary.  By	default, the string  is	 left-padded,  but  if
	      right is supplied	and non-zero, the string will be right-padded.

	      Here are some examples:

		  pad(3, "0", 2)	-->  "03"
		  pad(465, "0",	2)	-->  "465"
		  pad("foo", " ", 5)	-->  "	foo"
		  pad("foo", " ", 5, 1)	-->  "foo  "
		  pad("foo", "bar", 11)	-->  "barbarbafoo"

       plural(i_num [,s_str1 [,s_str2]])
	      Can  take	 from one to three arguments.  If one argument is sup-
	      plied, returns "s" if num	is not 1, and "" if num	is 1.

	      If two arguments are supplied, returns str1 + "s"	if num is  not
	      1.  Otherwise, returns str1.

	      If  three	 arguments are supplied, returns str1 if num is	1, and
	      str2 otherwise.

       psmoon(i_phase [,i_size [,s_note	[,i_notesize]]])
	      [DEPRECATED] Returns a STRING consisting of PostScript  code  to
	      draw  a  moon in the upper-left hand corner of the calendar box.
	      Phase specifies the phase	of the moon, and is 0  (new  moon),  1
	      (first quarter), 2 (full moon) or	3 (third quarter).  If size is
	      specified,  it  controls	the  radius  of	the moon in PostScript
	      units (1/72 inch.)  If it	is not specified or is	negative,  the
	      size of the day-number font is used.

	      For  example, the	following four lines place moon	symbols	on the
	      PostScript calendar:

			REM [moondate(0)] PS [psmoon(0)]
			REM [moondate(1)] PS [psmoon(1)]
			REM [moondate(2)] PS [psmoon(2)]
			REM [moondate(3)] PS [psmoon(3)]

	      If note is specified, the	text is	used to	annotate the moon dis-
	      play.  The font is the same font used for	calendar entries.   If
	      notesize is given, it specifies the font size to use for the an-
	      notation,	 in  PostScript	units (1/72 inch.)  If notesize	is not
	      given, it	defaults to the	size used for calendar	entries.   (If
	      you  annotate  the  display, be careful not to overwrite the day
	      number --	Remind does not	check for this.)  For example, if  you
	      want  the	time of	each new moon displayed, you could use this in
	      your reminder script:

		   REM [moondate(0)] PS	[psmoon(0, -1, moontime(0)+"")]

	      Note how the time	is coerced to a	string	by  concatenating  the
	      null string.

       psshade(i_gray) or psshade(i_red, i_green, i_blue)
	      [DEPRECATED]  Returns  a STRING that consists of PostScript com-
	      mands to shade a calendar	box.  Num can range from 0 (completely
	      black) to	100 (completely	white.)	 If three arguments are	given,
	      they specify red,	green  and  blue  intensity  from  0  to  100.
	      Here's an	example	of how to use this:

			REM Sat	Sun PS [psshade(95)]

	      The  above  command  emits  PostScript code to lightly shade the
	      boxes for	Saturday and Sunday in a PostScript calendar.

	      Note that	psmoon and psshade are deprecated; instead you	should
	      use the SPECIAL SHADE and	SPECIAL	MOON reminders as described in
	      "Out-of-Band Reminders."

       realcurrent()
	      Returns  (as  a  DATETIME) the true date and time	of day as pro-
	      vided by the operating system.  This  is	in  contrast  to  cur-
	      rent(), which may	return a time supplied on the command line.

       realnow()
	      Returns  the  true time of day as	provided by the	operating sys-
	      tem.  This is in contrast	to now(), which	may return a time sup-
	      plied on the command line.

       realtoday()
	      Returns the date as provided by the operating system.   This  is
	      in contrast to Remind's concept of "today", which	may be changed
	      if  it  is  running in calendar mode, or if a date has been sup-
	      plied on the command line.

       rows() If standard output is a TTY, returns the height of the  terminal
	      in  rows.	  If  standard	output	is not a TTY, attempts to open
	      "/dev/tty" to obtain the terminal	size.  If this fails,  returns
	      -1.

       sgn(i_num)
	      Returns  -1  if  num is negative,	1 if num is positive, and 0 if
	      num is zero.

       shell(s_cmd [,i_maxlen])
	      Executes cmd as a	system command,	 and  returns  the  first  511
	      characters of output resulting from cmd.	Any whitespace charac-
	      ter in the output	is converted to	a space.  Note that if RUN OFF
	      has  been	executed, or the -r command-line option	has been used,
	      shell() will result in an	error, and cmd will not	be executed.

	      If maxlen	is specified, then shell() returns  the	 first	maxlen
	      characters  of output (rather than the first 511).  If maxlen is
	      specified	as a negative number, then it defaults to the value of
	      the system variable $MaxStringLen.

       shellescape(s_str)
	      Returns str with all shell metacharacters	such as	" ", "*",  etc
	      escaped with a backslash.	 For example:

	       SET a shellescape("a b*?	c&d$e")

	      will set a to:

	       "a\ b\*\?\ c\&d\$e"

       slide(d_start, i_amt [, i_step] [,s_wkday...])
	      This  function is	the inverse of nonomitted.  It adds amt	(which
	      can be negative) chunks of step  days  to	 start,	 not  counting
	      omitted days.  If	step is	not supplied, then it is assumed to be
	      1.   Note	 that  only every stepth day is	tested to see if it is
	      omitted.	The optional wkday arguments  are  additional  weekday
	      names to omit.

	      Consider this example:

		   OMIT	14 May 2009
		   SET a slide('2009-05-13', 5,	"Sat", "Sun")

	      In  this	case, a	is set to 2009-05-21.  That's because we slide
	      forward by 5 days, not including Thursday, May  14  or  Saturday
	      and Sunday, May 16 and 17.  You can go backwards,	too, so:

		   OMIT	14 May 2009
		   SET a slide('2009-05-21', -5, "Sat",	"Sun")

	      takes a back to 2009-05-13.

	      Now consider this	example:

		      OMIT 14 May 2009
		      SET a slide('2009-05-07',	2, 7)

	      This sets	a to '2009-05-28' because we skip ahead	two weeks, not
	      counting	a week where the day we	land on	happens	to be omitted.
	      Contrast with this:

		      OMIT 13 May 2009
		      SET a slide('2009-05-07',	2, 7)

	      which sets a to '2009-05-21'.  Although 2009-05-13  is  omitted,
	      we don't "land" on it as we step forward in chunks of 7 days, so
	      we never see that	it is omitted.

       soleq(i_which [,	dqi_start])
	      The  soleq function computes solstices and equinoxes.  The which
	      parameter	ranges from 0 to 3, and	specifies which	event  we  are
	      interested in: 0 is the March equinox; 1 is the June solstice; 2
	      is the September equinox and 3 is	the December solstice.

	      The optional start parameter can either be an integer specifying
	      the  year	 of the	event we are interested	in, or a DATE or DATE-
	      TIME object; if the latter, then soleq returns the  first	 event
	      on or after the date part	of the start parameter (it ignores the
	      time  component  if  start is a DATETIME.)  If start is not sup-
	      plied, then it defaults to today().

	      The return value of soleq() is a DATETIME	object specifying  the
	      date and time of the solstice or equinox in the local time zone.
	      It  should  be  accurate	to within 3 minutes or so in the worst
	      case.

	      See the included file $SysInclude/seasons.rem  for  examples  of
	      how to use soleq().

       stdout()
	      Returns  a string	representing where Remind's standard output is
	      going.  The return values	are one	of  the	 following:  "TTY"  if
	      standard-output  is  a terminal, "BLOCKDEV" if it	is a block de-
	      vice (very unlikely), "CHARDEV" if it is a character device (eg,
	      /dev/null), "DIR"	if it is a directory (very  unlikely),	"PIPE"
	      if  it is	a pipe or FIFO,	"SYMLINK" if it	is a symlink (very un-
	      likely), "SOCKET"	if it is a socket, or "UNKNOWN"	 if  it	 could
	      not be determined.

	      The purpose of stdout() is mostly	to distinguish between TTY and
	      non-TTY  output; you may wish to change or disable colors	if the
	      output is	not going to a TTY.

       strlen(s_str)
	      Returns the length of str.  If the length	of str is too large to
	      represent	as an integer, emits a "Number too high" error.	  Note
	      that  strlen  returns the	number of bytes	in the string, not the
	      number of	characters.  These numbers  are	 the  same  for	 ASCII
	      strings, but may be different for	UTF-8 strings.

       substr(s_str, i_start [,i_end])
	      Returns  a STRING	consisting of all characters in	str from start
	      up to and	including end.	Characters are numbered	 from  1.   If
	      end is not supplied, then	it defaults to the length of str.

       sunrise([dq_date])
	      Returns  a  TIME indicating the time of sunrise on the specified
	      date (default today().)  In high latitudes, there	may be no sun-
	      rise on a	particular day,	in which case  sunrise()  returns  the
	      INT 0 if the sun never sets, or 1440 if it never rises.

       sunset([dq_date])
	      Returns  a  TIME	indicating the time of sunset on the specified
	      date (default today().)  In high latitudes, there	may be no sun-
	      set on a particular day, in which	case sunset() returns the  INT
	      0	if the sun never rises,	or 1440	if it never sets.

	      The  functions  sunrise()	and sunset() are based on an algorithm
	      in "Almanac for Computers	for the	year 1978" by L.  E.  Doggett,
	      Nautical	Almanac	 Office,  USNO.	 They require the latitude and
	      longitude	to be specified	 by  setting  the  appropriate	system
	      variables.   (See	"System	Variables".)  The sun functions	should
	      be accurate to within about 4 minutes for	latitudes  lower  than
	      60  degrees.   The functions are available starting from version
	      03.00.07 of Remind.

       time(i_hr, i_min)
	      Creates a	TIME with the hour and minute components specified  by
	      hr and min.

       timepart(tq_datetime)
	      Returns a	TIME object representing the time portion of datetime.

       timezone([dq_datetime])
	      Returns  a  string  representing the local time zone name	of the
	      given DATETIME.  If no argument is  supplied,  Remind  uses  the
	      value of current().  If a	DATE rather than DATETIME is supplied,
	      Remind uses a time part of 00:00.

       today()
	      Returns Remind's notion of "today."  This	may be the actual sys-
	      tem date,	or a date supplied on the command line,	or the date of
	      the calendar entry currently being computed.

       trig(s_1	[,s_2, ...])
	      For each string argument s_n, trig evaluates s_n as if it	were a
	      REM or IFTRIG trigger specification.  If the trigger would trig-
	      ger  today,  then	 the  trigger  date is returned	and no further
	      triggers are evaluated.  If none of the triggers	would  trigger
	      today, then the zero date	1990-01-01 is returned.
	      trig  also  has  a  zero-argument	form; this returns the trigger
	      date of the most recent trig function that returned  a  non-zero
	      trigger date.

	      trig  can	be used	to make	more sophisticated versions of IFTRIG.
	      For example, if you have meetings	every Monday in	June and July,
	      and you want warnings 3 days in advance, you could use:

		  REM [trig("Mon Jun +3", "Mon July +3")] +3 MSG Meeting %b

	      NOTE: We need to repeat the +3 delta outside of the  trig	 func-
	      tion for advance warning to work properly.  This is because trig
	      returns  a  date constant	(the trigger date) and the REM command
	      does not know the	details	of trig's arguments.

	      Note that	because	Remind has  short-circuit  logical  operators,
	      something	like:

		  SET a	trig("Mon +7") || trig("Fri +7")

	      would  set the value of trig() to	the date of the	following Mon-
	      day.  Because trig("Mon +7") always returns true,	the logical-OR
	      operator does not	bother evaluating trig("Fri +7") which	there-
	      fore does	not set	trig().

	      Important	Note:  Because trig() always returns an	absolute date,
	      it  will not work	properly with a	SATISFY	clause.	 Consider this
	      reminder:

		  REM [trig("Mar", "Apr")] SATISFY [$Td	== 15] MSG 15 Mar or April

	      If we run	Remind on 5 March 2022,	we might  expect  the  trigger
	      date  to	be  calculated as 15 March 2022... but that's not what
	      happens.	Instead, the trig function is evaluated	first, and  it
	      returns  2022-03-05.   So	as far as Remind is concerned, the REM
	      statement	becomes:

		  REM 2022-03-05 SATISFY [$Td == 15] MSG 15 Mar	or April

	      and the SATISFY expression is never true.	 So: Do	not mix	trig()
	      and SATISFY.

       trigdate()
	      Returns the calculated trigger date of the last  REM  or	IFTRIG
	      command.	 If  used  in  the body	of a REM command, returns that
	      command's	trigger	date.  If the most recent REM command did  not
	      yield a computable trigger date, returns the integer 0.

       trigdatetime()
	      Similar to trigdate(), but returns a DATETIME if the most	recent
	      triggerable  REM	command	 had an	AT clause.  If there was no AT
	      clause, returns a	DATE.  If no trigger could  be	computed,  re-
	      turns  the  integer 0.  See "MULTI-DAY EVENTS" for more informa-
	      tion.

       trigeventstart()
	      Returns a	DATETIME representing the start	 of  the  most	recent
	      triggerable REM command that had an AT clause.  For events with-
	      out  a  DURATION	or that	do not span multiple days, returns the
	      same as trigdatetime().  If the REM command did not have	an  AT
	      clause,  returns the integer -1 (and differs from	trigdatetime()
	      in this respect.)	 See "MULTI-DAY	EVENTS"	for more information.

       trigeventduration()
	      Returns a	TIME representing the  duration	 of  the  most	recent
	      triggerable  REM	command	 that had an AT	and a DURATION clause.
	      If the event does	not span multiple days,	returns	the same thing
	      as trigduration().  If the REM command lacked an AT or  DURATION
	      clause,  returns	-1.   See "MULTI-DAY EVENTS" for more informa-
	      tion.

       trigback()
	      Returns the "back" amount	of the last  REM  or  IFTRIG  command.
	      Returns a	positive integer N if the "back" is of the form	-N, or
	      a	 negative  integer  if	it is of the form --N.	If there is no
	      "back", then returns 0.

       trigdelta()
	      Returns the "delta" amount of the	last REM  or  IFTRIG  command.
	      Returns  a  positive integer N if	the "delta" is of the form +N,
	      or a negative integer if it is of	the form ++N.  If there	is  no
	      "delta", then returns 0.

       trigtimedelta()
	      Similar  to  trigdelta(),	 but  returns the delta	used in	the AT
	      clause of	a timed	reminder.

       trigrep()
	      Returns the "repeat" amount of the last REM or  IFTRIG  command.
	      Returns  a positive integer N if the "repeat" is of the form *N.
	      If there is no "repeat", then returns 0.

       trigtimerep()
	      Similar to trigrep(), but	returns	the  repeat  used  in  the  AT
	      clause of	a timed	reminder.

       trigduration()
	      Returns  (as  a TIME type) the DURATION parameter	of a timed re-
	      minder.  If there	is no DURATION parameter, returns the  integer
	      -1.  See "MULTI-DAY EVENTS" for more information.

       trigpriority()
	      Returns the PRIORITY of the last REM or IFTRIG command.

       triguntil()
	      Returns  (as a DATE type)	the UNTIL parameter of the last	REM or
	      IFTRIG command.  If there	was no UNTIL  parameter,  returns  the
	      integer  -1.   If	there is a THROUGH parameter, that will	be re-
	      turned by	triguntil() since "THROUGH yyyy-mm-dd" is simply  syn-
	      tactic sugar for "*1 UNTIL yyyy-mm-dd".

       trigscanfrom()
	      Returns  (as a DATE type)	the SCANFROM parameter of the last REM
	      or IFTRIG	command.  If there was no SCANFROM parameter,  returns
	      the  integer  -1.	  Note	that FROM and SCANFROM interact; a re-
	      minder that has a	"FROM yyyy-mm-dd" parameter will act as	if  it
	      has a SCANFROM parameter whose value is the maximum of "yyyy-mm-
	      dd" and today.

       trigfrom()
	      Returns  (as  a DATE type) the FROM parameter of the last	REM or
	      IFTRIG command.  If there	was no FROM parameter, returns the in-
	      teger -1.

       triginfo(s_header)
	      Returns a	STRING that is	the  INFO  item	 associated  with  the
	      header  header.	The header should not contain a	colon.	Header
	      name comparisons are case-insensitive.

	      For example, the following will assign "At home" to the variable
	      a	and the	empty string to	variable b:

		      REM INFO "Location: At home" MSG test
		      SET a triginfo("location")
		      SET b triginfo("no_such_header")

       trigger(d_date [,t_time [,i_utcflag]]) or trigger(q_datetime
       [,i_utcflag])
	      Returns a	string suitable	for use	in a REM command or a SCANFROM
	      or UNTIL clause, allowing	you to calculate trigger dates in  ad-
	      vance.  Note that	in earlier versions of Remind, trigger was re-
	      quired  to  convert  a date into something the REM command could
	      consume.	However, in this version of Remind, you	can  omit  it.
	      Note  that  trigger() always returns its result in English, even
	      for non-English versions of Remind.  Normally, the date and time
	      are the local date and time; however, if	utcflag	 is  non-zero,
	      the  date	 and  time  are	interpreted as UTC times, and are con-
	      verted to	local time.  Examples:

		   trigger('1993/04/01')

	      returns "1 April 1993",

		   trigger('1994/08/09', 12:33)

	      returns "9 August	1994 AT	12:33",	as does:

		   trigger('1994/08/09@12:33').

	      Finally:

		   trigger('1994/12/01', 03:00,	1)

	      returns "30 November 1994	AT 22:00" for EST, which  is  5	 hours
	      behind UTC.  The value for your time zone	may differ.

       trigtags()
	      Returns  a  comma-separated list of the TAGs associated with the
	      most recent REM command that was triggered.  Returns  the	 empty
	      string  if there were no TAGs.  If there are multiple tags, they
	      are each separated by a single comma, not	a comma	and a space.

       trigtime()
	      Returns the time of the last REM command with an AT clause.   If
	      the  last	 REM did not have an AT	clause,	returns	the integer 0.
	      If a REM command has an AT clause	with a DURATION, then you  can
	      compute the end time as trigtime() + trigduration().

       trigvalid()
	      Returns  1  if the value returned	by trigdate() is valid for the
	      most recent REM command, or 0 otherwise.	Sometimes REM commands
	      cannot calculate a trigger date.	For example, the following REM
	      command can never	be triggered:

		 REM Mon OMIT Mon SKIP MSG Impossible!

       typeof(x_arg)
	      Returns "STRING",	"INT", "DATE", "TIME" or "DATETIME", depending
	      on the type of arg.

       tzconvert(q_datetime, s_srczone [,s_dstzone])
	      Converts datetime	from the time zone named  by  srczone  to  the
	      time  zone named by dstzone.  If dstzone is omitted, the default
	      system time zone is used.	 The return value is a DATETIME.  Time
	      zone names are system-dependent; consult your  operating	system
	      for legal	values.	 Here is an example:

	   tzconvert('2007-07-08@01:14', "Canada/Eastern", "Canada/Pacific")

		 returns

	   2007-07-07@22:14

       upper(s_string)
	      Returns  a  STRING with all lower-case characters	in string con-
	      verted to	upper-case.

       utctolocal(q_datetime)
	      Given a DATETIME object interpreted in UTC,  return  a  DATETIME
	      object that expresses the	same time in the local time zone.

       value(s_varname [,x_default])
	      Returns  the  value  of  the  specified  variable.  For example,
	      value("X"+"Y") returns the value of variable XY, if  it  is  de-
	      fined.  If XY is not defined, an error results.

	      However,	if you supply a	second argument, it is returned	if the
	      varname is not defined.  The expression value("XY", 0) will  re-
	      turn  0  if  XY is not defined, and the value of XY if it	is de-
	      fined.

       version()
	      Returns a	string specifying the version of Remind.  For  version
	      05.03.05,	returns	"05.03.05".  It	is guaranteed that as new ver-
	      sions  of	 Remind	 are released, the value returned by version()
	      will strictly increase, according	to the rules for string	order-
	      ing.

       weekno([dq_date,	[i_wkstart, [i_daystart]]])
	      Returns the week number of the year.  If no arguments  are  sup-
	      plied, returns the ISO 8601 week number for today().  If one ar-
	      gument  date  is supplied, then returns the ISO 8601 week	number
	      for that date.  If two arguments are supplied, then wkstart must
	      range from 0 to 6, and represents	the  first  day	 of  the  week
	      (with  0 being Sunday and	6 being	Saturday.).  If	wkstart	is not
	      supplied,	then it	defaults to 1.	If the third argument daystart
	      is supplied, then	it specifies when Week 1 starts.  If  daystart
	      is  less than or equal to	7, then	Week 1 starts on the first wk-
	      start on or after	January	daystart.  Otherwise, Week 1 starts on
	      the first	wkstart	on or after December  daystart.	  If  omitted,
	      daystart defaults	to 29 (following the ISO 8601 definition.)

       wkday(dqi_arg)
	      If  arg is a DATE	or DATETIME, returns a string representing the
	      day of the week of the date.  If arg is an INT from 0 to 6,  re-
	      turns the	corresponding weekday ("Sunday"	to "Saturday").

       wkdaynum(dq_date)
	      Returns a	number from 0 to 6 representing	the day-of-week	of the
	      specified	 date.	 (0 represents Sunday, and 6 represents	Satur-
	      day.)

       year(dq_date)
	      Returns a	INT that is the	year component of date.

MULTI-DAY EVENTS
       If you specify a	start time with	AT and a duration with	DURATION,  you
       can  create  events  that  span	multiple days.	Consider these two REM
       statements:

	   REM 1991-02-13 AT 16:00 DURATION 72:00 MSG 72-hour event
	   REM 1991-02-13 THROUGH 1991-02-16 AT	16:00 MSG Four events

       The first statement creates a single event that starts on  13  February
       1991 at 16:00 and runs through 16 February 1991 at 16:00

       The  second statements creates four separate events that	start at 16:00
       on 13, 14, 15 and 16 February 1991 and have indefinite duration.

       Remind handles multi-day	events specially.  These are the rules:

       On the first day	of a multi-day event, trigdatetime() will  return  the
       starting	date and time of the event, and	trigduration() will return the
       original	DURATION.

       On each subsequent day of a multi-day event, trigdatetime() will	return
       midnight	on the day in question,	and trigduration() will	return the re-
       maining duration.  Consider this	example:

	   #!/bin/sh
	   remind - 12 feb 1991	'*6' <<'EOF'
	   BANNER %
	   REM 1991-02-13 AT 16:00 DURATION 72:00 SATISFY 1
	   set a trigdatetime()
	   set b trigduration()
	   set c trigeventstart()
	   set d trigeventduration()
	   MSG now=[today()] dt=[a] dur=[b] estart=[c] edur=[d]%
	   EOF

       The output is:

       now=1991-02-12 dt=1991-02-13@16:00 dur=72:00 estart=1991-02-13@16:00 edur=72:00
       now=1991-02-13 dt=1991-02-13@16:00 dur=72:00 estart=1991-02-13@16:00 edur=72:00
       now=1991-02-14 dt=1991-02-14@00:00 dur=64:00 estart=1991-02-13@16:00 edur=72:00
       now=1991-02-15 dt=1991-02-15@00:00 dur=40:00 estart=1991-02-13@16:00 edur=72:00
       now=1991-02-16 dt=1991-02-16@00:00 dur=16:00 estart=1991-02-13@16:00 edur=72:00
       now=1991-02-17 dt=1991-02-13@16:00 dur=72:00 estart=-1 edur=-1

       As  you see, the	trigdatetime() and trigduration() functions return the
       start time and duration of the remaining	portion	of a multi-day	event,
       whereas trigeventstart and trigeventduration always return the original
       start  and  duration of the multi-day event.  Note also that the	return
       value  for  expired  reminders  is  not	 reliable;   the   fact	  that
       trigeventstart  and  trigeventduration return -1	in that	case is	an im-
       plementation artifact.

       SELF-OVERLAPPING	EVENTS

       A multi-day event has the possibility of	 "overlapping  itself".	  When
       this happens, Remind prefers the	later event (only one copy of an event
       is ever triggered for a given date.)  Consider this example:

	  #!/bin/sh
	  remind - '*5'	10 Feb 1991 <<'EOF'

	  BANNER %
	  REM MON at 0:00 DURATION 192:0 MSG [today()] [trigeventstart()] [trigduration()]%

	  EOF

       The output is:

	  1991-02-10 1991-02-04@00:00 48:00
	  1991-02-11 1991-02-11@00:00 192:00
	  1991-02-12 1991-02-11@00:00 168:00
	  1991-02-13 1991-02-11@00:00 144:00
	  1991-02-14 1991-02-11@00:00 120:00

       Although	 the  event  from  1991-02-04  still  has  24  hours  left  on
       1991-02-11, the fresh occurrence	on 1991-02-11 takes precedences	and is
       the one that is triggered.

       I do not	recommend constructing self-overlapping	multi-day events.

EXPRESSION PASTING
       An extremely powerful feature of	Remind is  its	macro  capability,  or
       "expression pasting."

       In  almost  any	situation where	Remind is not expecting	an expression,
       you can "paste" an expression in.  To do	this, surround the  expression
       with square brackets.  For example:

	    REM	[mydate] MSG foo

       This  evaluates	the  expression	"mydate", where	"mydate" is presumably
       some pre-computed variable, and then "pastes" the result	into the  com-
       mand-line for the parser	to process.

       If  you	want a literal "[" character for some reason, simply use "[[".
       For example:

	       REM MSG Here are	[[square] brackets!

       A formal	description of this is:	 When Remind encounters	a  "pasted-in"
       expression,  it	evaluates  the expression, and coerces the result to a
       STRING.	It then	substitutes the	string for the	pasted-in  expression,
       and  continues  parsing.	 Note, however,	that expressions are evaluated
       only once, not recursively.  Thus, writing:

	    ["[a+b]"]

       causes Remind to	read the token "[a+b]".	 It does not interpret this as
       a pasted-in expression.	In fact, the only way to get a	literal	 left-
       bracket into a reminder is to use ["["].

       You  can	 use expression	pasting	almost anywhere.  However, there are a
       few exceptions:

       o      If Remind	is expecting an	expression, as in the SET command,  or
	      the IF command, you should not include square brackets.  For ex-
	      ample, use:

		 SET a 4+5
       and not:
		 SET a [4+5]

       o      You cannot use expression	pasting	for the	first token on a line.
	      For example, the following will not work:

		 ["SET"] a 1

	      This restriction is because Remind must be able to unambiguously
	      determine	 the  first  token of a	line for the flow-control com-
	      mands (to	be discussed later.)

	      In fact, if Remind cannot	determine the first token on  a	 line,
	      it  assumes  that	it is a	REM command.  If expression-pasting is
	      used, Remind assumes it is a REM command.	 Thus,	the  following
	      three commands are equivalent:

			REM 12 Nov 1993	AT 13:05 MSG BOO!
			12 Nov 1993 AT 13:05 MSG BOO!
			[12] ["Nov " + 1993] AT	[12:05+60] MSG BOO!

       o      You  cannot  use	expression-pasting to determine	the type (MSG,
	      CAL, etc.) of a REM command.  You	can paste  expressions	before
	      and  after  the MSG, etc.	keywords, but cannot do	something like
	      this:

		      REM ["12 Nov 1993	AT 13:05 " + "MSG" + " BOO!"]

	      However, as an escape hatch, the sequence	SPECIAL	type means the
	      same thing as just type where type is one	of MSG,	MSF, RUN, CAL,
	      PS and PSFILE.  This lets	you do something like this:

		      SET type "MSG"
		      REM 12 Nov 2024 SPECIAL [type] Hello

	      You can use this to control the types of your reminders based on
	      variables	you set, how Remind is invoked,	etc.

       COMMON PITFALLS WITH EXPRESSION PASTING

       Remember	that extra spaces are  not  inserted  when  an	expression  is
       pasted.	Thus, something	like:

	    REM[expr]MSG[expr]

       will probably fail.

       If  you use an expression to calculate a	delta or back, ensure that the
       result is a positive number.  Something like:

	    REM	+[mydelta] Nov 12 1993 MSG foo

       will fail if mydelta happens to be negative.

FLOW CONTROL COMMANDS
       Remind has commands that	control	the flow of a reminder	script.	  Nor-
       mally,  reminder	 scripts  are processed	sequentially.  However,	IF and
       related commands	allow you to process  files  conditionally,  and  skip
       sections	that you don't want interpreted.

       THE IF COMMAND

       The IF command has the following	form:

	    IF expr
		 t-command
		 t-command...
	    ELSE
		 f-command
		 f-command...
	    ENDIF

       Note  that the commands are shown indented for clarity.	Also, the ELSE
       portion can be omitted.	IF commands can	be nested up to	a small	limit,
       probably	around 8 or 16 levels of nesting, depending on your system.

       If the expr evaluates to	a non-zero INT,	a DATE that is not 1990-01-01,
       a TIME that is not 00:00, a DATETIME that is not	1990-01-01@00:00, or a
       non-null	STRING,	then the IF portion is considered true,	and the	t-com-
       mands are executed.  If expr evaluates to zero or null, then the	f-com-
       mands (if the ELSE portion is present) are executed.

       Examples:

	    IF defined("want_hols")
		 INCLUDE /usr/share/remind/holidays
	    ENDIF

	    IF today() > '1992/2/10'
		 set missed_ap "You missed it!"
	    ELSE
		 set missed_ap "Still have time..."
	    ENDIF

       THE IFTRIG COMMAND

       The IFTRIG command is similar to	an IF command, except that it computes
       a trigger (as in	the REM	command), and evaluates	to true	 if  a	corre-
       sponding	REM command would trigger.  Examples:

	    IFTRIG 1 Nov
		 ; Executed on 1 Nov
	    ELSE
		 ; Executed except on 1	Nov
	    ENDIF

	    IFTRIG 1 -1	OMIT Sat Sun +4
		 ; Executed on last working day	of month,
		 ; and the 4 working days preceding it
	    ELSE
		 ; Executed except on above days
	    ENDIF

       Note  that the IFTRIG command computes a	trigger	date, which can	be re-
       trieved with the	trigdate() function.  You can use all  of  the	normal
       trigger	components,  such as UNTIL, delta, etc.	in the IFTRIG command.
       However,	you cannot use a type specifier	such as	CAL, MSG  or  SATISFY;
       attempting to do	so yields a parse error.

USER-DEFINED FUNCTIONS
       In addition to the built-in functions, Remind allows you	to define your
       own functions.  The FSET	command	does this for you:

       FSET fname(args)	expr

       Fname  is the name of the function, and follows the convention for nam-
       ing variables.  Args is a comma-separated list of arguments,  and  expr
       is  an expression.  Args	can be empty, in which case you	define a func-
       tion taking no parameters.  Here	are some examples:

	    FSET double(x) 2*x
	    FSET yeardiff(date1, date2)	year(date1) - year(date2)
	    FSET since(x) ord($Ty - x)

       The last	function is useful in birthday reminders.  For example:

	    REM	1 Nov +12 MSG Dean's [since(1984)] birthday is %b.

       Dean was	born in	1984.  The above example, on 1	November  1992,	 would
       print:

	    Dean's 8th birthday	is today.

       Similarly,  the function	is useful in anniversary reminders.  For exam-
       ple:

	       REM 4 June MSG [since(1989)] anniversary	of the Tienanmen Square	massacre

       Notes:

       o      If you access a variable in expr that is not in the list of  ar-
	      guments, the global value	(if any) is used.

       o      Function and parameter names are significant to 64 characters.

       o      The value() function always accesses the global value of a vari-
	      able, even if it has the same name as an argument.  For example:

			fset func(x) value("x")
			set x 1
			set y func(5)

	      The above	sequence sets y	to 1, which is the global value	of x.

       o      User-defined functions may call other functions, including other
	      user-defined  functions.	 Recursive calls are allowed, but they
	      must terminate (for example, by using a  short-circuit  operator
	      or  function  that breaks	the recursion) or an error will	result
	      after a certain maximum number of	recursive calls	 (by  default,
	      1000.)

       o      If a user-defined	function has the same name as a	built-in func-
	      tion,  it	is ignored and the built-in function is	used.  To pre-
	      vent conflicts with future versions of Remind (which may	define
	      more  built-in functions), you may wish to name all user-defined
	      functions	beginning with an underscore.

       To delete a user-defined	function, use FUNSET.  This takes a space-sep-
       arated list of user-defined functions to	delete.	  For  example,	 after
       the command:

	       FUNSET myfunc1 otherfunc	thirdfunc

       it  is  guaranteed that no user-defined functions named myfunc1,	other-
       func or thirdfunc will exist.  Remind does not issue an	error  if  you
       try to FUNSET a nonexistent user-defined	function; it simply does noth-
       ing in that case.

       You  can	 rename	 a user-defined	function with FRENAME.	This takes two
       names:  An old name and a new name.  Consider this command:

	       FRENAME func_a func_b

       If func_a does not exist, the command unsets func_b if it  is  defined.
       However,	 if func_a exists, then	it is renamed to func_b, and func_a is
       no longer defined.  If func_b was defined prior to the FRENAME command,
       then that old definition	is lost.

       FRENAME is useful if you	want to	save and restore the definition	 of  a
       user-defined function.  For example, you	might want to define a msgpre-
       fix  function  for  a block of reminders, but not permanently overwrite
       any existing definition.	 You could do something	like this:

	       FRENAME msgprefix saved_msgprefix
	       FSET msgprefix(x) "My new prefix: "
	       INCLUDE block_of_reminders.rem
	       FRENAME saved_msgprefix msgprefix

       The file	block_of_reminders.rem would be	executed with the
       msgprefix function defined above.  After	the second FRENAME,
       msgprefix would be restored to its previous definition if
       it had one, or simply unset if it was not previously defined.

       If either argument to the FRENAME command is the	name of	a built-in
       function, the command fails with	an error message and does nothing.

       If you define a user-defined function and then later on redefine	it,
       Remind will issue a warning.  If	you do not want	this warning,
       then use	FUNSET to remove the existing definition before	you
       redefine	the function.

PRECISE	SCHEDULING
       The WARN	keyword	allows precise control over advance warning in a  more
       flexible	manner than the	delta mechanism.  It should be followed	by the
       name of a user-defined function,	warn_function.

       If  a warn_function is supplied,	then it	must take one argument of type
       INT.  Remind ignores any	delta, and instead calls warn_function succes-
       sively with the arguments 1, 2, 3, ...

       Warn_function's return value n is interpreted as	follows:

       o      If n is positive,	then the reminder is triggered exactly n  days
	      before its trigger date.

       o      If n is negative,	then it	is triggered n days before its trigger
	      date, not	counting OMITted days.

       As  an  example,	suppose	you wish to be warned of American Independence
       Day 5, 3, and 1 days in advance.	 You could use this:

	    FSET _wfun(x) choose(x, 5, 3, 1, 0)
	    REM	4 July WARN _wfun MSG American Independence Day	is %b.

       NOTES

       1      If an error occurs during	the evaluation of warn_function,  then
	      Remind  stops  calling  it and simply issues the reminder	on its
	      trigger date.

       2      If the absolute-values of	the return values of warn_function are
	      not monotonically	decreasing, Remind stops calling it and	issues
	      the reminder on its trigger date.

       3      Warn_function should (as a matter	of good	style) return 0	as the
	      final value in its sequence of return values.   However,	a  re-
	      minder  will always be triggered on its trigger date, regardless
	      of what warn_function does.

       Similarly to WARN, the SCHED keyword allows precise  control  over  the
       scheduling  of timed reminders.	It should be followed by the name of a
       user-defined function, sched_function.

       If a scheduling function	is supplied, then it must take one argument of
       type INT.  Rather than using the	AT time, time delta, and time  repeat,
       Remind  calls  the scheduling function to determine when	to trigger the
       reminder.  The first time the reminder is queued, the scheduling	 func-
       tion  is	called with an argument	of 1.  Each time the reminder is trig-
       gered, it is re-scheduled by calling the	scheduling function again.  On
       each call, the argument is incremented by one.

       The return value	of the scheduling function must	be an INT or  a	 TIME.
       If  the return value is a TIME, then the	reminder is re-queued to trig-
       ger at that time.  If it	is a positive integer n, then the reminder  is
       re-queued  to trigger at	the previous trigger time plus n minutes.  Fi-
       nally, if it is a negative integer or zero, then	the  reminder  is  re-
       queued  to  trigger n minutes before the	AT time.  Note that there must
       be an AT	clause for the SCHED clause to do anything.

       Here's an example:

	    FSET _sfun(x) choose(x, -60, 30, 15, 10, 3,	1, 1, 1, 1, 0)
	    REM	AT 13:00 SCHED _sfun MSG foo

       The reminder would first	be triggered at	13:00-60 minutes, or at	12:00.
       It would	next be	triggered 30 minutes later, at 12:30.  Then, it	 would
       be triggered at 12:45, 12:55, 12:58, 12:59, 13:00, 13:01	and 13:02.

       NOTES

       1      If an error occurs during	the evaluation of sched_func, then Re-
	      mind  reverts to using the AT time and the delta and repeat val-
	      ues, and never calls sched_func again.

       2      If processing sched_func yields a	time earlier than the  current
	      system  time,  it	 is repeatedly called with increasing argument
	      until it yields a	value greater than or  equal  to  the  current
	      time.   However, if the sequence of values calculated during the
	      repetition is not	strictly increasing, then  Remind  reverts  to
	      the default behaviour and	never calls sched_func again.

       3      It  is  quite possible using sched_func to keep triggering a re-
	      minder even after	the AT-time.  However, it is not  possible  to
	      reschedule a reminder past midnight - no crossing	of date	bound-
	      aries  is	 allowed.  Also, it is quite possible to not trigger a
	      reminder on the AT time when  you	 use  a	 scheduling  function.
	      However,	if your	scheduling function is terminated (for reasons
	      1	and 2) before the AT time of the reminder, it  will  be	 trig-
	      gered at the AT time, because normal processing takes over.

       4      Your scheduling functions	should (as a matter of good style) re-
	      turn 0 when no more scheduling is	required.  See the example.

       5      All  scheduling  functions are evaluated after the entire	Remind
	      script has been read in.	So whatever function  definitions  are
	      in effect	at the end of the script are used.

THE SATISFY CLAUSE
       The form	of REM that uses SATISFY is as follows:

       REM trigger SATISFY expr

       The  way	 this  works is	as follows:  Remind first calculates a trigger
       date, in	the normal fashion.  Next, it sets trigdate()  to  the	calcu-
       lated  trigger date.  It	then evaluates expr.  If the result is not the
       null string or zero, processing ends.  Otherwise, Remind	 computes  the
       next  trigger  date, and	re-tests expr.	This iteration continues until
       expr evaluates to non-zero or non-null, or until	 the  iteration	 limit
       specified with the -x command-line option is reached.

       If  expr	 is  not satisfied, then trigvalid() is	set to 0 and the error
       message "Can't compute trigger" is issued.  Otherwise,  trigvalid()  is
       set to 1.

       This is really useful only if expr involves a call to the trigdate() or
       related	functions or system variables; otherwise, expr will not	change
       as Remind iterates.  In fact, if	expr is	not a constant	and  does  not
       call  trigdate()	 or related functions or system	variables, then	Remind
       will issue a warning.

       An example of the usefulness of SATISFY:	 Suppose you wish to be	warned
       of every	Friday the 13th.  Your first attempt may be:

	    # WRONG!
	    REM	Fri 13 +2 MSG Friday the 13th is %b.

       But this	won't work.  This reminder triggers on the first Friday	on  or
       after  the 13th of each month.  The way to do it	is with	a more compli-
       cated sequence:

	    REM	13 SATISFY wkdaynum(trigdate())	== 5
	    IF trigvalid()
		 REM [trigdate()] +2 MSG \
		 Friday	the 13th is %b.
	    ENDIF

       You can write the REM statement a little	more concisely:

	    REM	13 SATISFY $Tw == 5

       Let's see how this works.  The SATISFY clause iterates through all  the
       13ths of	successive months, until a trigger date	is found whose day-of-
       week  is	 Friday	 (== 5).  If a valid date was found, we	use the	calcu-
       lated trigger date to set up the	next reminder.

       We could	also have written:

	    REM	Fri SATISFY day(trigdate()) == 13

       but this	would result in	more iterations, since	"Fridays"  occur  more
       often than "13ths of the	month."

       Here  is	 another example: Suppose you want to be reminded of something
       on the 15th of January, April, July, and	October.  You could make  four
       separate	reminders, or you could	use:

	       REM 15 SATISFY [isany($Tm, 1, 4,	7, 10)]	MSG 15th Reminder!

       This  technique of using	one REM	command	to calculate a trigger date to
       be used by another command is quite powerful.  For example, suppose you
       wanted to OMIT Labour day, which	is the first Monday in September.  You
       could use:

	    # Note: SATISFY 1 is an idiom for "do nothing"
	    REM	Mon 1 Sept SATISFY 1
	    OMIT [trigdate()]

       CAVEAT: This only omits the next	Labour Day, not	all Labour Days	in the
       future.	This could cause strange results,  as  the  OMIT  context  can
       change depending	on the current date.  For example, if you use the fol-
       lowing command after the	above commands:

	    REM	Mon AFTER msg hello

       the  result  will  not be as you	expect.	 Consider producing a calendar
       for September, 1992.  Labour Day	was  on	 Monday,  7  September,	 1992.
       However,	 when  Remind gets around to calculating the trigger for Tues-
       day, 8 September, 1992, the OMIT	command	will now  be  omitting	Labour
       Day  for	1993, and the "Mon AFTER" command will not be triggered.  (But
       see the description of SCANFROM in the section "DETAILS	ABOUT  TRIGGER
       COMPUTATION.")

       It  is probably best to stay away from computing	OMIT trigger dates un-
       less you	keep these pitfalls in mind.

       For versions of Remind starting from 03.00.07, you can include  a  MSG,
       RUN, etc. clause	in a SATISFY clause as follows:

	    REM	trigger_stuff SATISFY [expr] MSG body

       Note  that  for this case only, the expr	after SATISFY must be enclosed
       in square brackets.  It must come after all the other components	of the
       trigger,	and immediately	before the MSG,	RUN, etc.  keyword.   If  expr
       cannot be satisfied, then the reminder is not triggered.

       Thus, the "Friday the 13th" example can be expressed more compactly as:

	    REM	13 +2 SATISFY [$Tw == 5] MSG Friday the	13th is	%b.

       And you can trigger a reminder on Mondays, Wednesdays and Thursdays oc-
       curring on odd-numbered days of the month with the following:

	    REM	Mon Wed	Thu SATISFY [$Td %2 ] MSG Here it is!!!

       Note  that  SATISFY  and	 OMITFUNC  can often be	used to	solve the same
       problem,	though in different ways.  Sometimes a SATISFY is cleaner  and
       sometimes an OMITFUNC; experiment and use whichever seems clearer.

POSSIBLY-UNCOMPUTABLE TRIGGERS
       Occasionally,  you  may	wish  to  suppress the "Can't compute trigger"
       warnings	for reminders for which	a trigger  date	 cannot	 be  computed.
       For  example,  the  following reminder is triggered on a	Monday that is
       not a holiday if	the following Tuesday is a holiday:

	       REM Mon SKIP SATISFY [isomitted($T+1)] MSG Work between holidays

       However,	if there are no	Mondays	after today's date  that  satisfy  the
       condition,  Remind  will	 print	the "Can't compute trigger" error.  To
       suppress	this, use the MAYBE-UNCOMPUTABLE keyword:

	       REM MAYBE-UNCOMPUTABLE Mon SKIP SATISFY [isomitted($T+1)] MSG Work between holidays

       It's almost never appropriate to	use MAYBE-UNCOMPUTABLE,	but it is pro-
       vided for those rare occasions when it makes sense.  If you use	MAYBE-
       UNCOMPUTABLE  inside  the evaltrig() function, then untriggerable trig-
       gers return -1.	For example:

	       SET a evaltrig("MAYBE-UNCOMPUTABLE Mon SKIP OMIT	Mon")

       will set	a to -1.

DEBUGGING REMINDER SCRIPTS
       Although	the command-line -d option is useful for debugging, it is  of-
       ten  overkill.	For  example,  if you turn on the -dx option for a re-
       minder file with	many complex expressions, you'll get a huge amount  of
       output.	 The  DEBUG  command allows you	to control the debugging flags
       under program control.  The format is:

       DEBUG [+flagson]	[-flagsoff]

       Flagson and flagsoff consist of strings	of  the	 characters  "extvlfs"
       that  correspond	to the debugging options discussed in the command-line
       options section.	 If preceded with a "+", the  corresponding  group  of
       debugging  options  is  switched	on.  Otherwise,	they are switched off.
       For example, you	could use this sequence	to debug a complicated expres-
       sion:

	    DEBUG +x
	    set	a very_complex_expression(many_args)
	    DEBUG -x

       THE DUMPVARS COMMAND

       The command DUMPVARS displays the values	of variables in	 memory.   Its
       format is:

       DUMPVARS	[var...]

       If you supply a space-separated list of variable	names, the correspond-
       ing variables are displayed.  If	you do not supply a list of variables,
       then all	variables in memory are	displayed.  To dump a system variable,
       put  its	name in	the list of variables to dump.	If you put a lone dol-
       lar sign	in the list of variables to dump, then	all  system  variables
       will be dumped.

       THE ERRMSG COMMAND

       The ERRMSG command has the following format:

       ERRMSG body

       The  body  is  passed through the substitution filter (with an implicit
       trigger date of today())	and printed to the error output	stream.	 Exam-
       ple:

	    IF !defined("critical_var")
		 ERRMSG	You must supply	a value	for "critical_var"
		 EXIT
	    ENDIF

       THE EXIT	COMMAND

       The above example also shows the	use of the EXIT	command.  This	causes
       an  unconditional  exit	from  script processing.  Any queued timed re-
       minders are discarded.  If you are in calendar mode  (described	next),
       then the	calendar processing is aborted.

       If  you supply an INT-type expression after the EXIT command, it	is re-
       turned to the calling program as	the exit status.  Otherwise,  an  exit
       status of 99 is returned.

       THE FLUSH COMMAND

       This  command  simply  consists	of the word FLUSH on a line by itself.
       The command flushes the standard	output and standard error streams used
       by Remind.  This	is not terribly	useful to most people, but may be use-
       ful if you run Remind as	a subprocess of	another	program, and  want  to
       use pipes for communication.

CALENDAR MODE
       If you supply the -c, -s	or -p command-line option, then	Remind runs in
       "calendar  mode."   In  this mode, Remind interprets the	script repeat-
       edly, performing	one iteration through the whole	file for each  day  in
       the  calendar.	Reminders  that	trigger	are saved in internal buffers,
       and then	inserted into the calendar in the appropriate places.

       If you also supply the -a option, then Remind will  not	include	 timed
       reminders in the	calendar.

       The -p option is	used in	conjunction with the Rem2PS program to produce
       a  calendar  in	PostScript format.  For	example, the following command
       will send PostScript code to standard output:

	    remind -p .reminders | rem2ps

       You can print a PostScript calendar by piping this to the lpr command.

       If you have a reminder script called ".reminders", and you execute this
       command:

	    remind -c .reminders jan 1993

       then Remind executes the	script 31 times, once for each day in January.
       Each time it executes the script, it increments the value  of  today().
       Any  reminders  whose trigger date matches today() are entered into the
       calendar.

       MSG and CAL-type	reminders, by default, have their entire body inserted
       into the	calendar.  RUN-type reminders are not normally	inserted  into
       the  calendar.	However,  if  you enclose a portion of the body	in the
       %"...%" sequence, only that portion is inserted.	 For example, consider
       the following:

	    REM	6 Jan MSG %"Dianne's birthday%"	is %b

       In the normal mode, Remind would	print "Dianne's	birthday is today"  on
       6  January.   However,  in  the	calendar mode, only the	text "Dianne's
       birthday" is inserted into the box for 6	January.

       If you explicitly use the %"...%" sequence in a RUN-type	reminder, then
       the text	between	the delimiters is inserted into	the calendar.  If  you
       use  the	 sequence %"%" in a MSG	or CAL-type reminder, then no calendar
       entry is	produced for that reminder.

       PRESERVING VARIABLES

       Because Remind iterates through the script for each day in  the	calen-
       dar,  slow operations may severely reduce the speed of producing	a cal-
       endar.

       For example, suppose you	set the	variables "me" and "hostname" as  fol-
       lows:

	    SET	me shell("whoami")
	    SET	hostname shell("hostname")

       Normally,  Remind  clears  all variables	between	iterations in calendar
       mode.  However, if certain variables are	slow to	compute, and will  not
       change  between	iterations,  you  can "preserve" their values with the
       PRESERVE	command.  Also,	since function definitions are	preserved  be-
       tween  calendar	iterations,  there is no need to redefine them on each
       iteration.  Thus, you could use the following sequence:

	    IF ! defined("initialized")
		 set initialized 1
		 set me	shell("whoami")
		 set hostname shell("hostname")
		 fset func(x) complex_expr
		 preserve initialized me hostname
	    ENDIF

       The operation is	as  follows:   On  the	first  iteration  through  the
       script,	"initialized"  is  not defined.	 Thus, the commands between IF
       and ENDIF are executed.	The PRESERVE command ensures that  the	values
       of  initialized,	 me  and  hostname are preserved for subsequent	itera-
       tions.  On the next iteration, the commands are skipped,	since initial-
       ized has	remained defined.  Thus, time-consuming	operations that	do not
       depend on the value of today() are done only once.

       Most system variables (those whose names	start with '$')	are  automati-
       cally preserved between calendar	iterations.

       Note  that  for	efficiency, Remind caches the reminder script (and any
       INCLUDEd	files) in memory when producing	a calendar.

       Timed reminders are sorted and placed into the calendar in time	order.
       These are followed by non-timed reminders.  Remind automatically	places
       the  time  of  timed reminders in the calendar according	to the -b com-
       mand-line option.  Reminders in calendar	mode are sorted	as if  the  -g
       option had been used; you can change the	sort order in calendar mode by
       explicitly  using  the  -g option to specify a different	order from the
       default.

       REPEATED	EXECUTION

       If you supply a repeat parameter	on the command line, and  do  not  use
       the  -c,	-p, or -s options, Remind operates in a	similar	manner to cal-
       endar mode.  It repeatedly executes the reminder	 script,  incrementing
       today() with each iteration.  The same rules about preserving variables
       and  function definitions apply.	 Note that using repeat	on the command
       line also enables the -q	option and disables any	-z option.  As an  ex-
       ample, if you want to see how Remind will behave	for the	next week, you
       can type:

	    remind .reminders '*7'

       If you want to print the	dates of the next 1000 days, use:

	    (echo 'banner %'; echo 'msg	[today()]%') | remind -	'*1000'

INITIALIZING VARIABLES ON THE COMMAND LINE
       The  -i	option	is  used to initialize variables on the	Remind command
       line.  The format is -ivar=expr,	where expr is  any  valid  expression.
       Note  that  you	may have to use	quotes or escapes to prevent the shell
       from interpreting special characters in expr.  You can have as many  -i
       options	as you want on the command line, and they are processed	in or-
       der.  Thus, if a	variable is defined in one -i option, it  can  be  re-
       ferred to by subsequent -i options.

       Note  that  if  you supply a date on the	command	line, it is not	parsed
       until all options have been processed.  Thus, if	you use	today()	in any
       of the -i expressions, it will return the same value as realtoday() and
       not the date supplied on	the command line.

       Any variables defined on	the command line are  preserved	 as  with  the
       PRESERVE	command.

       You  should  not	 have  any  spaces between the -i option and the equal
       sign; otherwise,	strange	variable names are created that	 can  only  be
       accessed	with the value() or defined() functions.

       You can also define a function on the command line by using:

       -ifunc(args)=definition

       Be sure to protect special characters from shell	interpretation.

MORE ABOUT POSTSCRIPT
       The  PS	and  PSFILE  reminders	pass  PostScript  code directly	to the
       printer.	 They differ in	that the PS-type reminder passes its body  di-
       rectly  to  the PostScript output (after	processing by the substitution
       filter) while the PSFILE-type's body should simply consist of  a	 file-
       name.   The  Rem2PS program will	open the file named in the PSFILE-type
       reminder, and include its contents in the PostScript output.

       The PostScript-type reminders for a particular day are included in  the
       PostScript  output in sorted order of priority.	Note that the order of
       PostScript commands has a major impact on the appearance	of the	calen-
       dars.  For example, PostScript code to shade a calendar box will	oblit-
       erate  code  to draw a moon symbol if the moon symbol code is placed in
       the calendar first.  For	this reason, you should	not provide PS or  PS-
       FILE-type  reminders  with  priorities; instead,	you should ensure that
       they appear in the reminder script in the  correct  order.   PostScript
       code should draw	objects	working	from the background to the foreground,
       so  that	 foreground  objects properly overlay background ones.	If you
       prioritize these	reminders and run the script using descending sort or-
       der for priorities, the PostScript output will not work.

       All of the PostScript code for a	particular date	is enclosed in a save-
       restore pair.  However, if several PostScript-type reminders are	 trig-
       gered for a single day, each section of PostScript is not enclosed in a
       save-restore  pair - instead, the entire	body of	included PostScript is
       enclosed.

       PostScript-type reminders are executed by the PostScript	printer	before
       any regular calendar entries.   Thus,  regular  calendar	 entries  will
       overlay the PostScript-type reminders, allowing you to create shaded or
       graphical backgrounds for particular days.

       Before executing	your PostScript	code, the origin of the	PostScript co-
       ordinate	 system	 is  positioned	 to the	bottom left-hand corner	of the
       "box" in	the calendar representing today().  This location  is  exactly
       in  the	middle	of the intersection of the bottom and left black lines
       delineating the box - you may have to  account  for  the	 thickness  of
       these lines when	calculating positions.

       Several	PostScript  variables are available to the PostScript code you
       supply.	All distance and size variables	are in PostScript units	 (1/72
       inch.)  The variables are:

       LineWidth
	      The width	of the black grid lines	making up the calendar.

       Border The  border  between  the	center of the grid lines and the space
	      used to print calendar entries.  This border is  normally	 blank
	      space.

       BoxWidth	and BoxHeight
	      The  width and height of the calendar box, from center-to-center
	      of the black gridlines.

       InBoxHeight
	      The height from the center of the	bottom black gridline  to  the
	      top  of the regular calendar entry area.	The space from here to
	      the top of the box is used only to draw the day number.

       /DayFont, /EntryFont, /SmallFont, /TitleFont and	/HeadFont
	      The fonts	used to	draw the day numbers,  the  calendar  entries,
	      the  small  calendars,  the calendar title (month, year) and the
	      day-of-the-week headings,	respectively.

       DaySize,	EntrySize, TitleSize and HeadSize
	      The sizes	of the above fonts.  (The size of the  small  calendar
	      font  is not defined here.)  For example,	if you wanted to print
	      the Hebrew date next to the regular day number in	the  calendar,
	      use:

	    REM	PS Border BoxHeight Border sub DaySize sub moveto \
	       /DayFont	findfont DaySize scalefont setfont \
	       ([hebday(today())] [hebmon(today())]) show

	      Note how /DayFont	and DaySize are	used.

       Note  that if you supply	PostScript code, it is possible	to produce in-
       valid PostScript	files.	Always test your PostScript thoroughly with  a
       PostScript viewer before	sending	it to the printer.  You	should not use
       any document structuring	comments in your PostScript code.

DAEMON MODE
       If  you	use  the -z command-line option, Remind	runs in	"daemon	mode".
       In this mode, no	"normal" reminders are issued.	 Instead,  only	 timed
       reminders  are  collected and queued, and are then issued whenever they
       reach their trigger time.

       In addition, Remind wakes up every few minutes to check	the  modifica-
       tion  date on the reminder script (the filename supplied	on the command
       line.)  If Remind detects that the script has changed,  it  re-executes
       itself  in  daemon  mode, and interprets	the changed script.  If	Remind
       was compiled with support for inotify(7), then if the command-line  re-
       minder  script is really	a directory, Remind also re-executes itself if
       any of the files	in the directory is changed.

       In daemon mode, Remind also re-reads the	remind script when it  detects
       that the	system date has	changed.

       In  daemon  mode,  Remind acts as if the	-f option had been used, so to
       run in daemon mode in the background, use:

	    remind -z .reminders &

       If you use sh or	bash, you may have to use the "nohup" command  to  en-
       sure that the daemon is not killed when you log out.

PURGE MODE
       If  you	supply	the -j command-line option, Remind runs	in purge mode.
       In this mode, it	tries to purge expired reminders  from	your  reminder
       files.

       In  purge  mode,	Remind reads your reminder file	and creates a new file
       by appending ".purged" to the original file  name.   Note  that	Remind
       never edits your	original file; it always creates a new .purged file.

       If  you	invoke	Remind	against	 a directory instead of	a file,	then a
       .purged file is created for each	*.rem file in the directory.

       Normally, Remind	does not create	 .purged  files	 for  INCLUDed	files.
       However,	 if  you  supply a numeric argument after -j, then Remind will
       create .purged files for	the specified level of INCLUDE.	 For  example,
       if  you invoke Remind with the argument -j2, then .purged files will be
       created for the file (or	directory) specified on	the command line,  any
       files  included	by  them, and any files	included by those files.  How-
       ever, .purged files will	not be created for third-or-higher  level  IN-
       CLUDE files.

       Determining  which  reminders have expired is extremely tricky.	Remind
       does its	best, but you should always compare the	.purged	 file  to  the
       original	file and hand-merge the	changes	back in.

       Remind annotates	the .purged file as follows:

       An expired reminder is prefixed with:  #!P: Expired:

       In situations where Remind cannot reliably determine that something was
       expired,	 you  may see the following comments inserted before the prob-
       lematic line:

	  #!P: Cannot purge SATISFY-type reminders

	  #!P: The next	IF evaluated false...
	  #!P: REM statements in IF block not checked for purging.

	  #!P: The previous IF evaluated true.
	  #!P: REM statements in ELSE block not	checked	for purging

	  #!P: The next	IFTRIG did not trigger.
	  #!P: REM statements in IFTRIG	block not checked for purging.

	  #!P: Next line has expired, but contains expression...  please verify

	  #!P: Next line may have expired, but contains	non-constant expression

	  #!P! Could not parse next line: Some-Error-Message-Here

       Remind always annotates .purged files with lines	beginning with	"#!P".
       If such lines are encountered in	the original file, they	are not	copied
       to the .purged file.

SORTING	REMINDERS
       The -g option causes Remind to sort reminders by	trigger	date, time and
       priority	before issuing them.  Note that	reminders are still calculated
       in the order encountered	in the script.	However, rather	than being is-
       sued  immediately,  they	 are saved in an internal buffer.  When	Remind
       has finished processing the script, it issues the  saved	 reminders  in
       sorted  order.	The -g option can be followed by up to four characters
       that must all be	"a" or "d".  The first character  specifies  the  sort
       order  by  trigger date (ascending or descending), the second specifies
       the sort	order by trigger time and the third specifies the  sort	 order
       by priority.  If	the fourth character is	"d", the untimed reminders are
       sorted  before  timed  reminders.  The default is to sort all fields in
       ascending order and to sort untimed reminders after timed reminders.

       In ascending order, reminders are issued	with the most imminent	first.
       Descending  order is the	reverse.  Reminders are	always sorted by trig-
       ger date, and reminders with the	same trigger date are then  sorted  by
       trigger	time.	If two reminders have the same date and	time, then the
       priority	is used	to break ties.	Reminders with the same	date, time and
       priority	are issued in the order	they were encountered.

       You can define a	user-defined function called SORTBANNER	that takes one
       DATE-type argument.  In sort mode, the following	sequence happens:

       If Remind notices that the next reminder	to issue has a different trig-
       ger date	from the previous one (or if it	is the first  one  to  be  is-
       sued), then SORTBANNER is called	with the trigger date as its argument.
       The  result is coerced to a string, and passed through the substitution
       filter with the appropriate trigger date.   The	result	is  then  dis-
       played.

       Here's an example - consider the	following fragment:

	    # Switch off the normal banner
	    BANNER %
	    REM	11 March 1993 ++1 MSG Not so important
	    REM	17 March 1993 ++7 MSG Way in the future
	    REM	10 March 1993 MSG Important Reminder
	    REM	11 March 1993 ++1 MSG Not so important - B
	    FSET sortbanner(x) iif(x ==	today(), \
		 "*****	THINGS TO DO TODAY *****", \
		 "-----	Things to do %b	-----")

       Running this with the -gaa option on 10 March 1993 produces the follow-
       ing output:

	    ***** THINGS TO DO TODAY *****

	    Important Reminder

	    ----- Things to do tomorrow	-----

	    Not	so important

	    Not	so important - B

	    ----- Things to do in 7 days' time -----

	    Way	in the future

       You  can	 use  the args() built-in function to determine	whether	or not
       SORTBANNER has been defined.  (This could be used, for example, to pro-
       vide a default definition for SORTBANNER	in a system-wide file included
       at the end of the user's	file.)	Here's an example:

	    # Create a default sortbanner function if it hasn't	already
	    # been defined
	    if args("sortbanner") != 1
		 fset sortbanner(x) "--- Things	to do %b ---"
	    endif

MSGPREFIX() AND	MSGSUFFIX()
       You can define two functions in your script called msgprefix() and msg-
       suffix().  They should each accept one argument,	a  number  from	 0  to
       9999.

       In normal mode, for MSG-	and MSF-type reminders,	the following sequence
       occurs when Remind triggers a reminder:

       o      If  msgprefix() is defined, it is	evaluated with the priority of
	      the reminder as its argument.  The result	is printed.  It	is not
	      passed through the substitution filter.

       o      The body of the reminder is printed.

       o      If msgsuffix() is	defined, it is evaluated with the priority  of
	      the reminder as its argument.  The result	is printed.  It	is not
	      passed through the substitution filter.

       Here's  an  example:   The  following  definition causes	priority-0 re-
       minders to be preceded by "URGENT", and priority-6000 reminders	to  be
       preceded	by "(not important)".

	    fset msgprefix(x) iif(x==0,	"URGENT: ", \
		 x==6000, "(not	important) ", "")

       In  Calendar Mode (with the -c, -s or -p	options), an analogous pair of
       functions named calprefix() and calsuffix() can be defined.  They  work
       with  all  reminders  that produce an entry in the calendar (i.e., CAL-
       and possibly RUN-type reminders as well as MSG-type reminders.)

       NOTES

       Normally, the body of a reminder	is  followed  by  a  carriage  return.
       Thus,  the results of msgsuffix() will appear on	the next line.	If you
       don't want this,	make sure the output of	msgsuffix begins with a	 back-
       space.	This  places  the suffix before	rather than after the carriage
       return.	(The backspace character itself	is stripped out.)  Here	is  an
       example:

	       FSET msgsuffix(x) char(8) + " - suffix on same line"

       If  Remind has problems evaluating msgprefix(), msgsuffix() or sortban-
       ner(), you will see a lot of error messages.  For an example  of	 this,
       define the following:

	    fset msgprefix(x) x/0

COMPILE-TIME SUPPORT FOR OTHER LANGUAGES
       Remind  used  to	 support compile-time localization to other languages,
       but no longer does.  All	localization is	now done at run-time.

RUN-TIME SUPPORT FOR OTHER LANGUAGES
       Remind has run-time support for other languages,	and compile-time  sup-
       port has	been removed in	favour of run-time support.

       A number	of system variables let	you translate various phrases to other
       languages.  These system	variables are:

       $Monday,	$Tuesday, $Wednesday, $Thursday, $Friday, $Saturday, $Sunday
	      Set  each	of these system	variables to a string representing the
	      corresponding day's name in  your	 language.   Strings  must  be
	      valid UTF-8 strings.

       $January, $February, $March, $April, $May, $June, $July,	$August, $Sep-
       tember, $October, $November, $December
	      Set  each	of these system	variables to a string representing the
	      corresponding month's name in your language.   Strings  must  be
	      valid UTF-8 strings.

       $Ago, $Am, $And,	$At, $Hour, $Is, $Minute, $Now,	$On, $Pm, $Today, $To-
       morrow, $Was
	      Set  each	 of  these  system variables to	the translation	of the
	      corresponding English word into your language.   Note  that  $Am
	      and $Pm should be	the translations of "AM" and "PM" (morning and
	      afternoon	time indicators) respectively.

       $Hplu, $Mplu
	      Set  these  to  the  suffix  to  add  to the word	for "hour" and
	      "minute" to make them plural.  In	English, both would be set  to
	      "s".

       $Fromnow
	      Set this to the translation of the English phrase	"from now"

       Note that if you	set any	of the language-related	system variables, they
       should be set in	a section of your script that always is	evaluated.  If
       you  set	 them  inside an IF statement, for example, results are	unpre-
       dictable.

       Note also that the Rem2PS back-end does not support the full  range  of
       UTF-8  characters.  The TkRemind, rem2html and rem2pdf back-ends	all do
       support the full	UTF-8 range.

RUN-TIME MODIFICATION OF THE SUBSTITUTION FILTER
       The system variables mentioned in the previous section  are  not	 typi-
       cally  sufficient to properly translate Remind's	output to another lan-
       guage.  Some languages have complicated rules for AM vs	PM  times  and
       others  have  complex  rules for	making words plural.  Remind therefore
       allows you to define a number of	functions that modify the behavior  of
       the substitution	filter at run-time.  The functions are:

       subst_ampm(h)
	      This  function is	passed a single	integer, namely	an hour	from 0
	      to 23.  It should	return a string	that indicates "AM" or "PM" or
	      even finer gradations in some languages.

       subst_ordinal(d)
	      This function is passed a	single integer,	namely a  day  of  the
	      month  from 1 to 31.  It should return a string that is suffixed
	      to the day number	to turn	it into	an ordinal  number.   In  Eng-
	      lish, for	example, the function might return "st", "nd", "rd" or
	      "th", depending on d.

       subst_N(alt, date, time)
	      This  is	actually a family of functions,	where N	is a letter or
	      number.  This function completely	overrides the substitution se-
	      quence "%N".  The	three arguments	are an integer alt  which,  if
	      non-zero,	 indicates  that  the  alternate-mode substitution se-
	      quence "%*N" was encountered; date which is the trigger date  of
	      the reminder and time which is the trigger time.

       subst_Nx(alt, date, time)
	      Again,  this  is	a  family  of functions.  It is	similar	to the
	      subst_N family except it is only called if date is two  or  more
	      days  away  from	today().   This	is useful if you don't want to
	      override the "today" or "tomorrow" output	for most  substitution
	      sequences.

       Here's  an example of how you might customize your substitution filter.
       Suppose you want	to change the "%b" sequence to substitute "the day af-
       ter tomorrow" for an event two days from	now.  You could	do this:

	   FSET	subst_bx(a,d,t)	iif(d==today()+2, "the day after tomorrow", \
				    "in	" + (d-today())	+ " days' time")
	   REM [today()+3] ++3 MSG Event 1 is %b%
	   REM [today()+2] ++3 MSG Event 2 is %b%
	   REM [today()+1] ++3 MSG Event 3 is %b%
	   REM [today()]   ++3 MSG Event 4 is %b%

       The output of this script is:

	   Event 1 is in 3 days' time
	   Event 2 is the day after tomorrow
	   Event 3 is tomorrow
	   Event 4 is today

       Note how	Event 2's wording was changed from  the	 normal	 "in  2	 days'
       time",  and  note  also that the	"tomorrow" and "today" events used the
       normal substitution---subst_bx is not called for	trigger	days of	 today
       or tomorrow.

       As  a special case, if a	subst_Nx or subst_N function returns the inte-
       ger zero, then the normal substitution mechanism	is  used.   Therefore,
       the previous example could have been written more simply	as:

	   FSET	subst_bx(a,d,t)	iif(d==today()+2, "the day after tomorrow", 0)

       You  can	 define	 your  own  substitution  sequences in addition	to the
       built-in	 ones  as  follows:   If   you	 define	  a   function	 named
       subst_name(alt,	date, time), then the sequence %{name} calls the func-
       tion with alt set to 0 and date and time	to the trigger date and	 time,
       respectively.  The %{name} sequence is replaced with whatever the func-
       tion returns.  The sequence %*{name} is similar,	but calls the function
       with alt	set to 1.

       If  you	use  a %{name} sequence	and the	function subst_name is not de-
       fined or	returns	an error, then %{name}	is  replaced  with  the	 empty
       string.

THE TRANSLATION	TABLE
       To  assist  with	localizing reminder files, Remind maintains a table of
       translations.  This is simple a lookup table that maps one string  (the
       original	 string) to a new string (the translated string.)  When	Remind
       starts executing, the translation table is empty.

       To add a	message	to the translation table, use  the  TRANSLATE  command
       (which  may  be	abbreviated  to	TRANS.)	 The TRANSLATE command must be
       followed	by two quoted strings, separated from each other and from  the
       command	by  whitespace.	 For example, a	Dutch language file might con-
       tain something like this:

	       TRANSLATE "New Moon" "Nieuwe maan"
	       TRANSLATE "First	Quarter" "Eerste kwartier"
	       TRANSLATE "Full Moon" "Volle maan"
	       TRANSLATE "Last Quarter"	"Laatste kwartier"

       To actually use the translation table, make use of the _	built-in func-
       tion, as	follows:

	       REM NOQUEUE [moondatetime(0)] MSG [_("New Moon")] (%2)
	       REM NOQUEUE [moondatetime(1)] MSG [_("First Quarter")] (%2)
	       REM NOQUEUE [moondatetime(2)] MSG [_("Full Moon")] (%2)
	       REM NOQUEUE [moondatetime(3)] MSG [_("Last Quarter")] (%2)

       By using	TRANSLATE and _	judiciously, you can make your reminder	 files
       easy to translate.

       TRANSLATE  has  four additional forms:  If it is	followed by one	quoted
       string instead of two, then Remind deletes the translation table	 entry
       for  that  string.   If it is followed by the keyword DUMP, then	Remind
       dumps all translation table entries to standard output.	And if	it  is
       followed	by CLEAR, then Remind deletes all of the translation table en-
       tries.

       The  fourth form, TRANSLATE GENERATE, dumps all of the strings that can
       be localized (as	a series of TRANSLATE commands)	 to  standard  output.
       Strings	that are already localized are output with their localization;
       strings that are	not localized are output as:

	       TRANSLATE "untranslated"	""

       If you want to add a new	language, you can obtain a skeleton translation
       file by running:

	       echo "TRANSLATE GENERATE" | remind -h - > /tmp/skeleton.rem

       If you have an existing language	file that  is  missing	some  transla-
       tions, you can update it	by running:

	       (echo INCLUDE mylang.rem; echo TRANSLATE	GENERATE) | \
		   remind -h - > /tmp/mylang-update.rem

       and then	editing	mylang-update.rem to add in the	missing	translations.

       If you have some	reminder scripts that use the _() built-in function or
       %(...)  substitution sequence, you can generate a list of needed	TRANS-
       LATE commands by	running:

	       remind -q -n -dq	myscript.rem 2>&1 | grep ^TRANSLATE | sort | uniq

       Note that if you	SET various translation-related	system variables  such
       as  $Monday, $December, $Ago, etc, then Remind also makes a correspond-
       ing translation table entry automatically.  This	is done	for all	of the
       translation-related system variables except for $Hplu and $Mplu.

       The converse applies too; creating a translation	table  for  "December"
       automatically  sets $December.  And if you invoke TRANSLATE CLEAR, then
       all translation-related system variables	are set	to their default  val-
       ues as well.

       The  translation	table always contains a	special	entry LANGID whose de-
       fault value is en.  Translators are encouraged to add a LANGID entry in
       their language files; the value should be the  two-characters  ISO  639
       language	code.

       For  example,  if  you write a translation file for the Dutch language,
       add this	line:

	       TRANSLATE "LANGID" "nl"

       Scripts can use _("LANGID") to query the	translation language  that  is
       in effect.

       The _() function	uses the following procedure to	obtain the translation
       for a string:

	      1	     Look for an exact match.  If found, return.

	      2	     If	 the  original string had an upper-case	letter,	search
		     for the all-lower-case equivalent.	 If  found,  make  the
		     first letter of the result	upper-case and return.

	      3	     If	 the original string started with a lower-case letter,
		     search for	an equivalent whose first letter is upper-case
		     and the rest lower-case.  If found, make the first	letter
		     of	the result lower-case and return.

	      4	     No	translation was	found.	Return the original string.

LANGUAGE PACKS
       Remind ships with a number of language packs, which are simply reminder
       scripts located in [$SysInclude]/lang.  The currently-shipping language
       packs are:

       da.rem (Danish),	de.rem (German), es.rem	 (Spanish),  fr.rem  (French),
       is.rem  (Icelandic),  it.rem  (Italian),	nl.rem (Dutch),	no.rem (Norwe-
       gian), pl.rem (Polish), pt.rem (Portuguese) and ro.rem (Romanian).

       To use a	language pack (in this example,	de.rem), simply	place this  at
       the top of your reminders file:

	   SYSINCLUDE lang/de.rem

       If  you	want  Remind  to try to	find the language pack appropriate for
       your locale settings, use:

	   SYSINCLUDE lang/auto.rem

       You are encouraged to study the language	packs to see how to  translate
       Remind into additional languages.

THE HEBREW CALENDAR
       Remind  has support for the Hebrew calendar, which is a luni-solar cal-
       endar.  This allows  you	 to  create  reminders	for  Jewish  holidays,
       jahrzeits (anniversaries	of deaths) and smachot (joyous occasions.)

       THE HEBREW YEAR

       The  Hebrew  year  has 12 months, alternately 30	and 29 days long.  The
       months are: Tishrey, Heshvan, Kislev, Tevet, Shvat, Adar, Nisan,	 Iyar,
       Sivan,  Tamuz,  Av  and	Elul.	In Biblical times, the year started in
       Nisan, but Rosh Hashana (Jewish New Year) is now	celebrated on the  1st
       and 2nd of Tishrey.

       In  a  cycle  of	19 years, there	are 7 leap years, being	years 3, 6, 8,
       11, 14, 17 and 19 of the	cycle.	In a leap year,	an extra month	of  30
       days is added before Adar.  The two Adars are called Adar A and Adar B.

       For  certain  religious	reasons,  the  year  cannot start on a Sunday,
       Wednesday or Friday.  To	adjust for this, a day is taken	off Kislev  or
       added  to Heshvan.  Thus, a regular year	can have from 353 to 355 days,
       and a leap year from 383	to 385.

       When Kislev or Heshvan is short,	it is called chaser, or	lacking.  When
       it is long, it is called	shalem,	or full.

       The Jewish date changes at sunset.  However,  Remind  will  change  the
       date at midnight, not sunset.  So in the	period between sunset and mid-
       night,  Remind  will  be	a day earlier than the true Jewish date.  This
       should not be much of a problem in practice.

       The computations	for the	Jewish calendar	 were  based  on  the  program
       "hdate"	written	 by Amos Shapir	of the Hebrew University of Jerusalem,
       Israel.	He also	supplied the preceding explanation of the calendar.

       HEBREW DATE FUNCTIONS

       hebday(d_date)
	      Returns the day of the Hebrew month corresponding	 to  the  date
	      parameter.   For	example, 12 April 1993 corresponds to 21 Nisan
	      5753.  Thus, hebday('1993/04/12')	returns	21.

       hebmon(d_date)
	      Returns the name of the Hebrew month corresponding to date.  For
	      example, hebmon('1993/04/12') returns "Nisan".

       hebyear(d_date)
	      Returns the Hebrew year corresponding  to	 date.	 For  example,
	      hebyear('1993/04/12') returns 5753.

       hebdate(i_day, s_hebmon [,id_yrstart [,i_jahr [,i_aflag]]])
	      The hebdate() function is	the most complex of the	Hebrew support
	      functions.   It  can  take  from 2 to 5 arguments.  It returns a
	      DATE corresponding to the	Hebrew date.

	      The day parameter	can range from 1 to 30,	and specifies the  day
	      of the Hebrew month.  The	hebmon parameter is a string that must
	      name  one	 of  the Hebrew	months specified above.	 Note that the
	      month must be spelled out	in full, and use the English translit-
	      eration shown previously.	 You can also  specify	"Adar  A"  and
	      "Adar B."	 Month names are not case-sensitive.

	      The  yrstart parameter can either	be a DATE or an	INT.  If it is
	      a	DATE, then the hebdate() scans for the first Hebrew date on or
	      after that date.	For example:

			hebdate(15, "Nisan", '1990/01/01')

	      returns 1990/03/30, because that is the first occurrence	of  15
	      Nisan on or after	1 January 1990.

	      If yrstart is an INT, it is interpreted as a Hebrew year.	 Thus:

			hebdate(22, "Kislev", 5756)

	      returns  1995/12/15, because that	date corresponds to 22 Kislev,
	      5756.  Note that none of the Hebrew  date	 functions  will  work
	      with dates outside Remind's normal range for dates.

	      If yrstart is not	supplied, it defaults to today().

	      The jahr modifies	the behaviour of hebdate() as follows:

	      If  jahr is 0 (the default), then	hebdate() keeps	scanning until
	      it finds a date that exactly  satisfies  the  other  parameters.
	      For example:

			hebdate(30, "Adar A", 1993/01/01)

	      returns  1995/03/02,  corresponding  to 30 Adar A, 5755, because
	      that is the next occurrence of 30	Adar A after 1 January,	 1993.
	      This  behaviour  is  appropriate for Purim Katan,	which only ap-
	      pears in leap years.

	      If jahr is 1, then the date is modified as follows:

	      o	     30	Heshvan	is converted to	1 Kislev in years when Heshvan
		     is	chaser

	      o	     30	Kislev is converted to 1 Tevet in years	when Kislev is
		     chaser

	      o	     30	Adar A is converted to 1 Nisan in non-leapyears

	      o	     Other dates in Adar A are moved to	the corresponding  day
		     in	Adar in	non-leapyears

	      This behaviour is	appropriate for	smachot	(joyous	occasions) and
	      for some jahrzeits - see "JAHRZEITS."

	      if jahr is 2, then the date is modified as follows:

	      o	     30	 Kislev	 and 30	Heshvan	are converted to 29 Kislev and
		     29	Heshvan, respectively, if the month is chaser

	      o	     30	Adar A is converted to 30 Shvat	in non-leapyears

	      o	     Other dates in Adar A are moved to	the corresponding  day
		     in	Adar in	non-leapyears

	      if  jahr	is not 0, 1, or	2, it is interpreted as	a Hebrew year,
	      and the behaviour	is calculated as described in  the  next  sec-
	      tion, "JAHRZEITS."

	      The  aflag  parameter modifies the behaviour of the function for
	      dates in Adar during leap	years.	The  aflag  is	only  used  if
	      yrstart is a DATE	type.

	      The  aflag only affects date calculations	if hebmon is specified
	      as "Adar".  In leap years, the following algorithm is followed:

	      o	     If	aflag is 0, then the date  is  triggered  in  Adar  B.
		     This is the default.

	      o	     If	 aflag	is  1,	then  the date is triggered in Adar A.
		     This may be appropriate for jahrzeits  in	the  Ashkenazi
		     tradition;	consult	a rabbi.

	      o	     If	 aflag is 2, then the date is triggered	in both	Adar A
		     and Adar B	of  a  leap  year.   Some  Ashkenazim  perform
		     jahrzeit in both Adar A and Adar B.

       JAHRZEITS

       A  jahrzeit  is a yearly	commemoration of someone's death.  It normally
       takes place on the anniversary of the death, but	may be delayed if bur-
       ial is delayed -	consult	a rabbi	for more information.

       In addition, because some months	change length, it is not obvious which
       day the anniversary of a	death is.  The following rules are used:

       o      If the death occurred on 30 Heshvan, and Heshvan in the year af-
	      ter the death is chaser, then the	jahrzeit  is  observed	on  29
	      Heshvan  in  years  when	Heshvan	 is  chaser.   Otherwise,  the
	      jahrzeit is observed on 1	Kislev when Heshvan is chaser.

       o      If the death occurred on 30 Kislev, and Kislev in	the year after
	      the death	is chaser, then	the jahrzeit is	observed on 29	Kislev
	      in  years	when Kislev is chaser.	Otherwise, the jahrzeit	is ob-
	      served on	1 Tevet	when Kislev is chaser.

       o      If the death occurred on 1-29 Adar A, it	is  observed  on  1-29
	      Adar in non-leapyears.

       o      If  the  death occurred on 30 Adar A, it is observed on 30 Shvat
	      in a non-leapyear.

       Specifying a Hebrew year	for the	jahr parameter causes the correct  be-
       haviour	to be selected for a death in that year.  You may also have to
       specify aflag, depending	on your	tradition.

       The jahrzeit information	was supplied by	Frank Yellin, who quoted  "The
       Comprehensive Hebrew Calendar" by Arthur	Spier, and "Calendrical	Calcu-
       lations"	by E. M. Reingold and Nachum Dershowitz.

OUT-OF-BAND REMINDERS
       The  SPECIAL  keyword  is used to transmit "out-of-band"	information to
       Remind backends,	such as	tkremind or Rem2PS.  They are used  only  when
       piping  data from a remind -p line.  (Note that the COLOR special is an
       exception; it downgrades	to the equivalent of MSG  in  Remind's	normal
       mode of operation.)

       The  various  SPECIALs recognized are particular	for each backend; how-
       ever, there are four SPECIALs that all backends should attempt to  sup-
       port.  They are currently supported by Rem2PS, tkremind and rem2html.

       The SHADE special replaces the psshade()	function.  Use it like this:

	    REM	Sat Sun	SPECIAL	SHADE 128
	    REM	Mon SPECIAL SHADE 255 0	0

       The SHADE keyword is followed by	either one or three numbers, from 0 to
       255.   If  one  number  is  supplied, it	is interpreted as a grey-scale
       value from black	(0) to white (255).  If	three  numbers	are  supplied,
       they  are  interpreted  as  RGB	components from	minimum	(0) to maximum
       (255).  The example above shades	weekends a fairly dark grey and	 makes
       Mondays	a  fully-saturated  red.   (These shadings appear in calendars
       produced	by Rem2PS, tkremind and	rem2html.)

       The MOON	special	replaces the psmoon() function.	 Use it	like this:

	    REM	[moondate(0)] SPECIAL MOON 0
	    REM	[moondate(1)] SPECIAL MOON 1
	    REM	[moondate(2)] SPECIAL MOON 2
	    REM	[moondate(3)] SPECIAL MOON 3

       These draw little moons on the various calendars.  The complete	syntax
       of the MOON special is as follows:

	    ...	SPECIAL	MOON phase moonsize fontsize msg

       Phase  is  a  number from 0 to 3, with 0	representing a new moon, 1 the
       first quarter, 2	a full moon and	3 the last quarter.

       moonsize	is the diameter	in PostScript units of the moon	to  draw.   If
       omitted or supplied as -1, the backend chooses an appropriate size.

       fontsize	is the font size in PostScript units of	the msg

       Msg is additional text that is placed near the moon glyph.

       Note  that  only	the Rem2PS backend supports moonsize and fontsize; the
       other backends use fixed	sizes.

       The COLOR special lets you place	colored	 reminders  in	the  calendar.
       Use it like this:

	    REM	... SPECIAL COLOR 255 0	0 This is a bright red reminder
	    REM	... SPECIAL COLOR 0 128	0 This is a dark green reminder

       You  can	 spell	COLOR either the American way ("COLOR")	or the British
       way ("COLOUR").	This manual will use the American way.

       Immediately following COLOR should be  three  decimal  numbers  ranging
       from 0 to 255 specifying	red, green and blue intensities, respectively.
       The rest	of the line is the text	to put in the calendar.

       The  COLOR special is "doubly special", because in its normal operating
       mode, remind treats a COLOR special  just  like	a  MSG-type  reminder.
       Also,  if  you  invoke  Remind with -@[n], then it approximates SPECIAL
       COLOR reminders on your terminal.

       See also	the documentation of the $DefaultColor system variable in  the
       section "SYSTEM VARIABLES".

       The  WEEK special lets you place	annotations such as the	week number in
       the calendar.  For example, this	would number each Monday with the  ISO
       8601  week  number.  The	week number is shown like this:	"(Wn)" in this
       example,	but you	can put	whatever text you like after the WEEK keyword.

	    REM	Monday SPECIAL WEEK (W[weekno()])

MISCELLANEOUS
       COMMAND AND KEYWORD ABBREVIATIONS

       The following tokens can	be abbreviated:

       o      CLEAR-OMIT-CONTEXT --> CLEAR

       o      PUSH-OMIT-CONTEXT	--> PUSH

       o      POP-OMIT-CONTEXT --> POP

       o      DUMPVARS --> DUMP

       o      BANNER --> BAN

       o      INCLUDE --> INC

       o      MAYBE-UNCOMPUTABLE --> MAYBE

       o      SCANFROM --> SCAN

       NIFTY EXAMPLES

       This section is a sampling of what you can do with Remind.

	    REM	5 Feb 1991 AT 14:00 +45	*30 \
	    RUN	mail -s	"Meeting at %2"	$LOGNAME </dev/null &

       On 5 February, 1991, this reminder will mail you	reminders of a	2:00pm
       meeting	at  1:15, 1:45 and 2:00.  The subject of the mail message will
       be "Meeting at 2:00pm" and the body of the message will be blank.

	    REM	AT 17:00 RUN echo "5:00pm - GO HOME!" |	xless -g +0+0 &

       This reminder will pop up an xless window at  5:00pm  every  day.   The
       xless window will contain the line "5:00pm - GO HOME!"

	    REM	AT 23:59 RUN (sleep 120; remind	-a [filename()]) &

       This  reminder will run at one minute to	midnight.  It will cause a new
       Remind process to start at one minute past midnight.  This  allows  you
       to have a continuous reminder service so	you can	work through the night
       and still get timed reminders for early in the morning.	Note that this
       trick is	no longer necessary, providing you run Remind in daemon	mode.

	    remind -c12	/dev/null Jan 1993

       This  invocation	 of Remind will	cause it to print a calendar for 1993,
       with all	entries	left blank.

	    REM	CAL [trigdate()-date(year(trigdate()), 1, 1)+1]

       This example puts an entry in each box of a calendar showing the	number
       (1-365 or 366) of the day of the	year.

	    REM	Tue 2 Nov SATISFY (year(trigdate())%4) == 0
	    IF trigvalid()
		 REM [trigdate()] ++5 MSG \
		 U.S. Presidential Election!!
	    ENDIF

       This example warns you 5	days ahead of each American presidential elec-
       tion.  The first	REM command calculates the  first  Tuesday  after  the
       first  Monday in	November.  (This is equivalent to the first Tuesday on
       or after	2 November.)  The SATISFY clause ensures that the trigger date
       is issued only in election years, which are multiples of	4.  The	second
       REM command actually issues the reminder.

       DETAILS ABOUT TRIGGER COMPUTATION

       Here is a conceptual description	of how triggers	are calculated.	  Note
       that  Remind actually uses a much more efficient	procedure, but the re-
       sults are the same as if	the conceptual procedure had been followed.

       Remind starts from the current date (that is, the value of today()) and
       scans forward, examining	each day one at	a time until it	finds  a  date
       that  satisfies	the  trigger,  or  can prove that no such dates	(on or
       later than today()) exist.

       If Remind is executing a	SATISFY-type reminder, it  evaluates  the  ex-
       pression	 with  trigdate() set to the date found	above.	If the expres-
       sion evaluates to zero or the null string, Remind continues  the	 scan-
       ning procedure described	above, starting	with the day after the trigger
       found above.

       The  SCANFROM  clause (having a syntax similar to UNTIL)	can modify the
       search strategy used.  In this case, Remind begins the scanning	proce-
       dure  at	scan_date, which is the	date specified in the SCANFROM clause.
       For example:

	    REM	Mon 1 SCANFROM 17 Jan 1992 MSG Foo

       The example above will always have a trigger date of Monday, 3 February
       1992.  That is because Remind starts scanning from 17 January 1992, and
       stops scanning as soon as it hits a date	that satisfies "Mon 1."

       The main	use of SCANFROM	is in situations where you want	 to  calculate
       the  positions  of  floating holidays.  Consider	the Labour Day example
       shown much earlier.  Labour Day is the first Monday in  September.   It
       can move	over a range of	7 days.	 Consider the following	sequence:

	    REM	Mon 1 Sept SCANFROM [today()-7]	ADDOMIT	MSG Labour Day
	    REM	Mon AFTER MSG Hello

       The  SCANFROM clause makes sure that Remind begins scanning from	7 days
       before the current date.	 This ensures that Labour Day for the  current
       year  will continue to be triggered until 7 days	after it has occurred.
       This allows you to safely use the AFTER keyword as shown.

       As a special case, you can simply use a negative	number after SCANFROM;
       a negative number -N is interpreted as N	days before today.  Thus,  the
       previous	example	could also be written like this:

	    REM	Mon 1 Sept SCANFROM -7 ADDOMIT MSG Labour Day
	    REM	Mon AFTER MSG Hello

       In  general,  use SCANFROM as shown for safe movable OMITs.  The	amount
       you should scan back by (7 days in the example above)  depends  on  the
       number  of possible consecutive OMITted days that may occur, and	on the
       range of	the movable holiday.  Generally, a value of 7 is safe.

       The FROM	clause operates	almost like the	 counterpoint  to  UNTIL.   It
       prevents	 the reminder from triggering before the FROM date.  For exam-
       ple, the	following reminder:

	    REM	Mon Thu	FROM 23	Jul 2007 UNTIL 2 Aug 2007 MSG Test

       will trigger on Mondays and Thursdays between 23	July 2007 and 2	August
       2007 inclusive.

       FROM is really just syntactic sugar; you	could implement	 the  reminder
       above as	follows:

	    REM	Mon Thu	SCANFROM [max(today(), '2007-07-23')] \
		   UNTIL 2 Aug 2007 MSG	Test

       but  that's  a  lot harder to read.  Internally,	Remind treats FROM ex-
       actly as	illustrated using SCANFROM.  For that reason, you  cannot  use
       both FROM and SCANFROM.

       Note  that if you use one REM command to	calculate a trigger date, per-
       form date calculations (addition	or subtraction,	for example) and  then
       use  the	modified date in a subsequent REM command, the results may not
       be what you intended.  This is because you have circumvented the	normal
       scanning	mechanism.  You	should try to write REM	commands that  compute
       trigger	dates  that can	be used	unmodified in subsequent REM commands.
       The file	"defs.rem" that	comes with the	Remind	distribution  contains
       examples.

       DETAILS ABOUT TRIGVALID()

       The  trigvalid()	function returns 1 if Remind could find	a trigger date
       for the previous	REM or IFTRIG command.	More specifically, it  returns
       1  if  Remind finds a date not before the starting date of the scanning
       that satisfies the trigger.  In addition, there is one special case  in
       which trigvalid() returns 1 and trigdate() returns a meaningful result:

       If  the REM or IFTRIG command did not contain an	UNTIL clause, and con-
       tained all of the day, month and	year components, then Remind will cor-
       rectly compute a	trigger	date, even if it  happens  to  be  before  the
       start  of  scanning.  Note that this behaviour is not true for versions
       of Remind prior to 03.00.01.

FILES
       The traditional location	of your	reminders file or directory is:

	       $HOME/.reminders

       where $HOME is your home	directory.

       Remind ships with some preinstalled files  for  holidays	 and  language
       packs.  These are located in the	following directory:

	       /usr/local/share/remind/

       Do  not hard-code the above directory in	your reminder files.  Instead,
       use the value of	the $SysInclude	system variable.

AUTHOR
       Dianne Skoll <dianne@skoll.ca> wrote Remind.  The moon phase  code  was
       copied  largely	unmodified  from "moontool" by John Walker.  The moon-
       rise/moonset code comes from  https://github.com/signetica/MoonRise  by
       Stephen	R. Schmitt and Cyrus Rahman.  The sunrise and sunset functions
       use ideas from programs by Michael Schwartz and Marc T.	Kaufman.   The
       Hebrew  calendar	 support  was  taken from "hdate" by Amos Shapir.  The
       supported languages and their translators are listed below.   Languages
       marked  "complete"  support error messages in that language; all	others
       only support the	substitution filter mechanism and month/day names.

       German -- Wolfgang Thronicke

       Dutch --	Willem Kasdorp and Erik-Jan Vens

       Finnish -- Mikko	Silvonen (complete)

       French -- Laurent Duperval (complete)

       Norwegian -- Trygve Randen

       Danish -- Mogens	Lynnerup

       Polish -- Jerzy Sobczyk (complete)

       Brazilian Portuguese -- Marco Paganini (complete)

       Italian -- Valerio Aimale

       Romanian	-- Liviu Daia

       Spanish -- Rafa Couto

       Icelandic -- Bjorn Davdhsson

BUGS
       If you find a bug in Remind, please report it to: dianne@skoll.ca

       There's no good reason why read-only system variables  are  not	imple-
       mented as functions, or why functions like version(), etc.  are not im-
       plemented as read-only system variables.

       Hebrew dates in Remind change at	midnight instead of sunset.

       Remind has some built-in	limits (for example, number of global OMITs.)

BIBLIOGRAPHY
       Nachum  Dershowitz  and Edward M. Reingold, "Calendrical	Calculations",
       Software-Practice and Experience, Vol. 20(9), Sept. 1990, pp 899-928.

       L. E. Doggett, Almanac for computers for	the year  1978,	 Nautical  Al-
       manac Office, USNO.

       Richard Siegel and Michael and Sharon Strassfeld, The First Jewish Cat-
       alog, Jewish Publication	Society	of America.

       Jean  Meeus,  Astronomical  Algorithms,	Second Edition,	Willmann-Bell,
       Inc.

HOME PAGE
       https://dianne.skoll.ca/projects/remind/

MAILING	LIST
       https://dianne.skoll.ca/mailman/listinfo/remind-fans

SEE ALSO
       rem(1), rem2ps(1), rem2pdf(1), tkremind(1), rem2html(1)

4th Berkeley Distribution	  2025-03-23			     REMIND(1)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=remind&sektion=1&manpath=FreeBSD+Ports+14.3.quarterly>

home | help