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

FreeBSD Manual Pages

  
 
  

home | help
REMIND(1)		       VERSION 06.01.08			     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.  In	this case, if Remind has been compiled
       against the GNU Readline	library, it will use Readline to give  you  an
       interactive line-editing	interface.

       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.

MODES OF OPERATION
       Remind has four major modes of operation:

       Agenda Mode
	      Agenda  mode  is	the default mode.  In this mode, Remind	prints
	      today's reminders	on standard output and exits.  It may  fork  a
	      background  process  to pop up queued reminders for later	in the
	      day.

       Calendar	Mode
	      In this mode, Remind generates a calendar	either by  drawing  it
	      in  the  terminal	or by sending data in computer-readable	format
	      to a back-end program that actually draws	the calendar.

       Daemon Mode
	      This is a	special	mode of	operation in which Remind  is  invoked
	      by a front-end and runs as a daemon, accepting requests from the
	      front-end	 and sending messages back to the front-end.  TkRemind
	      uses Remind in daemon mode.

       Purge Mode
	      In this mode, Remind produces no output, but  creates  new  ver-
	      sions  of	 its  input files with all expired reminders commented
	      out.

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.

	      In a UTF-8 locale, Remind	will use  "left-to-right  marks"  when
	      creating	a  calendar  with the -c option.  Some terminals don't
	      handle this correctly and	garble the rendering of	the  calendar;
	      see  the	documentation  of  $SuppressLRM	in the section "SYSTEM
	      VARIABLES" for a workaround.

       -@[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
	      usual  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 expres-
		     sion node tree.  This is unlikely to be useful unless you
		     are working on Remind's expression	evaluation engine.

	      h	     Dump hash-table statistics	on exit.

	      u	     When  Remind  exits,  print a list	of variables that were
		     SET, but not subsequently used.

		     Note that the u debugging flag may	produce	spurious warn-
		     ings.  For	example, this sequence of commands:

			     DEBUG +u
			     SET a 1
			     IFTRIG Wed
				     MSG a = [a]
			     ENDIF

		     will issue	a warning about	a being	unused	unless	it  is
		     run on a Wednesday.

	      n	     Print debugging information about why Remind considers an
		     expression	to be "non-constant"

	      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
       (e.g., 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	number
	      to standard output and then exit.

       --hide-completed-todos
	      In  Calendar Mode, Remind	normally shows all TODOs.  If you sup-
	      ply this option, the it will  not	 show  TODOs  that  have  been
	      marked as	completed.

       --only-todos
	      Only issue TODO-type reminders.

       --only-events
	      Do not issue TODO-type reminders.

       --json In Agenda	Mode, output JSON instead of the normal	text-mode out-
	      put.   --json also disables sorting (the -g option) and disables
	      queueing (the -q option).	 See the  section  "AGENDA  MODE  JSON
	      OUTPUT"  for more	details.  The --json option is ignored in Cal-
	      endar Mode.  Note	that in	JSON mode, the output  from  any  RUN-
	      type  reminder  that would normally appear on standard output is
	      redirected to standard error instead; this is so	that  RUN-type
	      reminders	 don't mess up the output and cause invalid JSON to be
	      produced on standard output.

       --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.

       --max-expr-complexity=n
	      Limit the	total complexity of expression valuation for  a	 given
	      line  in	a  script to n nodes.  Roughly speaking, each function
	      call, operator, constant,	variable reference, etc	corresponds to
	      one expression node.  By default,	the limit is set  to  10000000
	      (ten  million).	You can	explicitly set it to zero if you don't
	      want any limit to	apply.	 The  default  limit  of  ten  million
	      should  never  be	 triggered by any sensible Remind script, how-
	      ever, and	we don't recommend changing the	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.

       --flush
	      The --flush long option makes Remind's standard output and stan-
	      dard  error  streams  unbuffered.	 It is mostly used for testing
	      and should probably not be used 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] [TODO] [MAX-OVER-
	      DUE  n] [COMPLETE-THROUGH	complete_date] [PRIORITY prio] [SKIP |
	      BEFORE | AFTER] [OMIT omit_list] [ADDOMIT]  [NOQUEUE]  [OMITFUNC
	      omit_function]  [AT  time	[tdelta] [trepeat]] [SCHED sched_func-
	      tion]  [WARN  warn_function]  [UNTIL   expiry_date   |   THROUGH
	      last_date]  [SCANFROM scan_date |	FROM start_date] [DURATION du-
	      ration] [TAG tag]	[TZ timezone] [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.  When	Remind runs a command,
       it sets the command's standard input to come from /dev/null.

       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 (e.g.,  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 (i.e., 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 date	and time is before the
	      trigger  date  and the AT	time, or "was" if it is	after.	The %!
	      sequence may be used in a	non-timed reminder, in which case only
	      dates are	compared.

       %?     is replaced with "are" if	the current date and  time  is	before
	      the trigger date and the AT time,	or "were" if it	is after.  The
	      %?   sequence may	be used	in a non-timed reminder, in which case
	      only dates are compared.

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

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

       %:     is replaced with " (done)" for a	TODO  reminder	whose  trigger
	      date  is	on or after its	COMPLETE-THROUGH date.	It is replaced
	      with the empty string in any other situation.  Note that because
	      Remind does not display completed	TODO reminders in Agenda Mode,
	      this escape sequence is really only useful in Calendar Mode.

       %"     (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      The ! and	? substitutions	may be preceded	by an asterisk (%*! or
	      %*?),  in	 which case the	comparison is made between the trigger
	      date and realtoday() instead of today().

       o      Any of the substitutions dealing with time (0 through 9) 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 recommended that  you
	      use the time substitutions only in timed reminders 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.

EVENTS AND TODOS
       The REM command is normally used	to create an EVENT.  This is something
       that happens at a certain time, possibly	recurring, and happens no mat-
       ter  what action	you take.  Events include things like birthdays, holi-
       days, meetings, etc... pretty much everything that occurs on a particu-
       lar schedule.  Once the date of an event	has  passed,  Remind  will  no
       longer remind you about the event.

       A  TODO	is different; it is a task that	you have to complete by	a spe-
       cific date or date and time.  If	you don't explicitly mark  a  TODO  as
       done, Remind will keep reminding	you about it even past the due date..

       To mark a REM as	a TODO,	simply include the TODO	keyword.  For example:

	   REM TODO 15 August 2025 ++5 MSG Buy cat food	%b.

       In  Agenda  Mode, Remind	will start warning you on 10 Aug 2025 that you
       have to but cat food in 5 days' time, 4 days' time, etc...

       However,	on 16 Aug 2025,	Remind will say	"Buy cat food yesterday."  and
       it will keep reminding you of your need to buy cat food until  the  end
       of time,	or until you mark the TODO as done.

MARKING	TODOS AS DONE
       There  are  two ways to mark a TODO as done.  If	the TODO is not	recur-
       ring, the simplest way is simply	to remove the TODO designator from the
       REM command (or indeed, to completely delete it.)  The former keeps the
       reminder	on the calendar	while the latter completely removes it.

       If a TODO is recurring, use the COMPLETE-THROUGH	clause to  mark	 which
       recurrences have	been completed.	 For example:

	   REM TODO 30 April ++15 COMPLETE-THROUGH 2025-04-30 MSG File taxes

       Canadian	 income	taxes must be filed every 30 April.  The above command
       will remind you to pay taxes in 2026.  If you  don't  update  the  COM-
       PLETE-THROUGH  date, then after 30 April	2026, Remind will keep remind-
       ing you until the end of	time that your taxes  were  due	 on  30	 April
       2026.   To  indicate that you've	paid them, simply update the COMPLETE-
       THROUGH date to 2026-04-30 and then Remind will start reminding you  of
       your 2027 taxes (starting 15 days before	the due	date.)

       It  is  an  error  to  specify COMPLETE-THROUGH without also specifying
       TODO.

LIMITING REMINDERS ABOUT OVERDUE TODOS
       Although	Remind is happy	to keep	reminding you about overdue TODOs  for
       hundreds	 of years, for some things this	may be pointless.  If you want
       Remind to stop nagging you about	an overdue TODO	after a	certain	number
       of days,	use the	MAX-OVERDUE n clause.  In this case, Remind stops  re-
       minding	you of a TODO that is overdue by more than n days.  Here is an
       example.

	   REM TODO 2025-08-13 ++5 MAX-OVERDUE 5 MSG Task: %b.

       Remind starts reminding you of the task on 2025-08-08, because  of  the
       ++5 back	value.	It keeps reminding you of the task after the due date.
       However,	 the  last  time it will remind	you will be on 2025-08-18, be-
       cause of	the MAX-OVERDUE	clause.	 Starting on 2025-08-19,  Remind  will
       no longer remind	you of the task	since it's probably pointless---it has
       passed the MAX-OVERDUE period.

MORE DETAILS ABOUT TODOS
       TODOs  are  treated  specially  only in Agenda Mode.  In	Calendar Mode,
       they appear in the calendar exactly as a	normal event would.

       TODOs are implemented internally	by  using  the	COMPLETE-THROUGH  date
       plus  one  day  as  the starting	point for Remind's date-scanning algo-
       rithm.  If you have a recurring TODO without a COMPLETE-THROUGH clause,
       then Remind starts scanning from	the beginning of time,	which  we  all
       know is 1 January 1990.	Consider this command:

	   REM TODO Wed	+7 MSG Take out	the trash %a (%b)

       Running	that command in	Agenda Mode on 2025-08-13 yields the following
       output:

	   Take	out the	trash on Wednesday, 3 January, 1990 (13006 days	ago)

       Remind is very persistent about reminding you of	tasks!	 If  you  take
       out the trash and mark it done:

	   REM TODO Wed	+7 COMPLETE-THROUGH 2025-08-13 MSG Take	out the	trash %a (%b)

       then you	get this:

	   Take	out the	trash on Wednesday, 20 August, 2025 (in	7 days'	time)

       You  can	 use  FROM and UNTIL to	limit the recurrence interval of tasks
       just as you can with events.  For example, if you are house-sitting for
       the month of August and need to water plants every Wednesday:

	   REM TODO Wed	+7 FROM	2025-08-06 UNTIL 2025-08-27 MSG	Plants %b.

       Running that command on 13 Aug yields: "Plants 7	days ago." because you
       have not	told Remind that you completed the  first  watering.   If  you
       finish  your duties and add a COMPLETE-THROUGH date of 2025-08-27, then
       Remind never reminds you	of that	task in	the future.

       In Purge	Mode, Remind will not purge TODOs unless they have been	marked
       as complete.  In	the case of a recurring	TODO, Remind will not purge it
       until the last occurrence is marked as complete.

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	(i.e.,	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.

TIMEZONE SUPPORT
       The REM command supports	an optional TZ keyword,	which should  be  fol-
       lowed  by  the case-sensitive time zone name in which the command is to
       be interpreted.	Note that if you use the TZ  keyword,  then  you  must
       also use	an AT clause.  Here are	some examples:

	   REM Wednesday AT 14:00 TZ America/Toronto MSG 2PM Eastern (%2).
	   REM Wednesday AT 23:59 TZ America/Los_Angeles SATISFY [$Td == 13] MSG Foo %b	%2.

       Within a	SATISFY	clause and an OMITFUNC function, all trigger functions
       and  the	trigger	date are interpreted in	the time zone specified	in the
       REM command.  Outside the REM command, however, trigger	functions  are
       adjusted	 to the	local time zone.  If the local time zone is UTC	and we
       feed Remind the following file on 2025-09-04 UTC:

	   SET $AddBlankLines 0
	   BANNER %
	   REM Wednesday AT 14:00 TZ America/Toronto MSG 2PM Eastern (%2).
	   set a $T
	   set b $Tt
	   REM MSG a = [a], b =	[b]
	   REM Wednesday AT 23:59 TZ America/Los_Angeles SATISFY [$Td == 13] MSG Foo %b	%2.
	   set c $T
	   set d $Tt
	   REM MSG c = [c], d =	[d]

       Then the	output is as follows:

	   a = 2025-09-10, b = 18:00
	   c = 2026-05-14, d = 06:59

       That is because the trigger date	of the first (Wednesday, 2025-09-10 at
       14:00 Eastern time) is 2025-09-10 at 18:00 UTC.	In  the	 second	 case,
       Wednesday, 13 May 2026 is the SATISFied trigger date, which is adjusted
       to  Thursday, 14	May 2026 at 06:59 UTC because of the time zone adjust-
       ment.

       If you use an invalid time zone name after the TZ keyword, results  are
       undefined.   As	mentioned  previously, time zone names are case-sensi-
       tive; America/Toronto is	valid, but america/toronto is not.

       If you are on a system that stores time zone data  in  /usr/share/zone-
       info,  then Remind will attempt to validate the time zone name and will
       warn you	if it appears to be invalid.  If you want to  specify  a  time
       zone  that  lacks  a file under /usr/share/zoneinfo anyway, and want to
       suppress	the warning, prefix the	time zone name with "!".  For example:

	   REM Thursday	AT 14:45 TZ !EST+5EDT,M3.2.0/2,M11.1.0/2 MSG Old TZ format

       In a reminder with the TZ keyword, OMIT	dates  are  evaluated  in  the
       specified time zone.  Here's an example:	Suppose	the local time zone is
       America/Toronto and you have this script:

	   # A Friday
	   OMIT	2025-09-05

	   # A Saturday
	   OMIT	2025-09-13

	   REM Saturday	AT 01:00 TZ Europe/Amsterdam SKIP MSG Early Sat	AM

       On 2025-09-05 in	the America/Toronto time zone, the reminder will trig-
       ger.   Even though 2025-09-05 has been OMITted, the SKIP	keyword	evalu-
       ates the	date in	the Europe/Amsterdam time zone,	 and  2025-09-06  (the
       trigger date) is	not omitted.

       Conversely,  on	2025-09-12  in	the America/Toronto time zone, the re-
       minder will not	trigger.   Even	 though	 2025-09-12  is	 not  OMITted,
       2025-09-13  is,	and  that  is the trigger date in the Europe/Amsterdam
       time zone.

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 installation of  Remind,  the	 system	 directory  is
       "/usr/local/share/remind".

THE RETURN COMMAND
       The  RETURN  command  causes Remind to ignore the remaining contents of
       the file	currently being	processed.  It can be used as a	quick  way  to
       "exit" from an included file (though it also works at the top-level.)

       Here is an example of how RETURN	might be used:

	       IF already_done
		   RETURN
	       ENDIF
	       set already_done	1
	       preserve	already_done
	       # Do expensive processing here

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"

       Remind arranges so that when the	command	specified by INCLUDECMD	is ex-
       ecuted, its standard input is opened to /dev/null.

       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.

	      Remind normally expects to be running in	a  UTF-8  environment.
	      In  this	environment,  there  is	a difference between bytes and
	      characters since in UTF-8, a character may be represented	 by  a
	      sequence	of  more than one byte.	 For example, in a UTF-8 envi-
	      ronment, the string "" contains one character  but  four	bytes.
	      And the string "n" contains three	characters but five bytes.

	      Remind  has a set	of functions that work on bytes, namely	index,
	      strlen and substr.  These	are not	 safe  to  use	on  multi-byte
	      strings;	instead	 use  mbindex,	mbstrlen and mbsubstr.	If you
	      know for sure that a string contains  only  single-byte  charac-
	      ters, then the byte-oriented versions may	be used	and are	faster
	      than the multi-byte versions.

	      Some  ancient  or	 embedded systems may lack the C library func-
	      tions needed to deal with	multi-byte strings.  In	that case, the
	      mbxxx functions all return an error.

       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, 0x1F, 0xfe00 (the last two demonstrate the
	      use of hexadecimal constants)

       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.  Be-
	      cause $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 substi-
	      tutions 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	effec-
	      tively  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 in-
	      dividual 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  ex-
	      plicitly	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 com-
	      mand-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 com-
	      mand 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 key-
	      word  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 2027, because both years begin on a
	      Friday, 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 2027.  By default, this
	      variable is 0.  Set it to	1 if the sun or	UTC  functions	misbe-
	      have  for	 years	greater	 than 2037.  See also the section "MA-
	      CHINES WITH A 32-BIT TIME_T TYPE"

       $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.

       $HideCompletedTodos (read-only)
	      If non-zero, then	the --hide-completed-todos option was supplied
	      on the command line.

       $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.

       $JSONMode (read-only)
	      If non-zero, then	the --json command-line	option was supplied.

       $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  (the  default)  means  to
	      skip parsing them	and 1 means to parse them.

	      For example, if we have the following REM	statement:

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

	      Then  if	$ParseUntriggered is set to 1, 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,
	      the default, then	Remind will not	 issue	the  error  except  on
	      2020-01-01, when the reminder is triggered.

	      Keeping $ParseUntriggered	at 0 may slightly improve performance,
	      at  the  risk  of	 not catching errors until a reminder is trig-
	      gered.  We recommend leaving it set to 0.

       $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 or INT type)
	      Equivalent to trigdate().	 (See BUILT-IN FUNCTIONS.)

       $Tb (read-only, DATE or INT type)
	      Equivalent to trigbase().

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

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

       $Tu (read-only, DATE or INT type)
	      Equivalent to triguntil().

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

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

       $Tt (read-only, TIME or INT 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.

       $TimetIs64bit (read-only)
	      This variable returns 1 if the internal  C  time_t  type	is  at
	      least  64	 bits  long.  If it returns 0, then the	internal C li-
	      brary is unable to represent dates after about 2038, and	Remind
	      will  use	 a workaround to avoid problems.  See also the section
	      "MACHINES	WITH A 32-BIT TIME_T TYPE"

       $TodoFilter (read-only)
	      If 0, then both events and TODOs are being output.  If  1,  then
	      the  --only-todos	 command-line option was supplied.  If 2, then
	      the --only-events	command-line option was	supplied.

       $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.

       $WarningLevel (STRING type)
	      As new versions of Remind	are  released,	new  warnings  may  be
	      added.   If  your	 formerly-fine	scripts	suddenly start issuing
	      warnings when you	upgrade	Remind,	then as	a stopgap measure, you
	      may set $WarningLevel to a string	of the form AB.CD.EF where AB,
	      CD and EF	are pairs of decimal digits.  This will	 suppress  any
	      warnings that were introduced after Remind version AB.CD.EF.  If
	      you  do  not  set	$WarningLevel, then it defaults	to the current
	      version of Remind, meaning all warnings will be issued.

	      For example, if you want the warnings  you  receive  limited  to
	      what Remind 05.00.00 would have produced,	use:

		  SET $WarningLevel "05.00.00"

	      We do not	recommend setting $WarningLevel	as a matter of course;
	      you  should  use	it to suppress warnings	only for as long as it
	      takes for	you to fix your	remind scripts so they no longer cause
	      warnings to be emitted.

       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.

SAVING AND RESTORING VARIABLES
       Just as with the	OMIT context, you can save and restore the  values  of
       global variables	and all	(modifiable) system variables.	For example:

	       SET a 1
	       UNSET b

	       # Save variables
	       PUSH-VARS $DefaultColor $AddBlankLines a	b

	       SET $DefaultColor "255 0	0"
	       SET $AddBlankLines 0
	       SET a 3
	       SET b 4
	       REM MSG Hello

	       # Restore all the variables we pushed earlier
	       POP-VARS

	       # Now the changes to $DefaultColor and $AddBlankLines
	       # have been undone.  Additionally, a is restored	to 1
	       # and b is unset

       As  you see from	the example, PUSH-VARS takes a list of global variable
       names and/or system variable names.  You	can save  the  values  of  any
       modifiable system variables and any global variable.  You can even push
       global variables	that are not set.

       The  POP-VARS  command  restores	the values of all system variables and
       global variables	that were pushed by the	most recent PUSH-VARS command.
       If you push an undefined	global variable, then that variable  is	 unset
       by the POP-VARS command.

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 agenda mode
		      REM SPECIAL COLOR	0 255 0	Green in agenda	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 byte 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.

       codepoint(s_string)
	      Returns an INT that is the code point of the first character  in
	      string,  treating	multi-byte characters correctly.  As a special
	      case, codepoint("") returns 0.

       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().

       catch(x_arg1, x_arg2)
	      Evaluates	arg1 and if no error  occurs,  returns	the  resulting
	      value.  If an error occurs during	the evaluation of arg1,	evalu-
	      ates  and	 returns  arg2.	 Note that catch() can only catch run-
	      time evaluation errors.  It cannot catch syntax errors.

	      Here are some examples:

	      catch(4/2, 33)  => 2, because 4/2	evaluates without error
	      catch(4/0, 33)  => 33, because 4/0 gives a divide-by-zero	error
	      catch(2, 1/0)   => 2, and	the second argument is not evaluated
	      catch(4/0, 1/0) results in a divide-by-zero error

	      Note in the last example that catch does not  protect  you  from
	      errors in	the evaluation of arg2.

       catcherr()
	      Returns  a  string  representing the error message from the most
	      recently-evaluated catch() function whose	first argument yielded
	      an error.	 Note that the error message is	always in English even
	      if Remind	has been localized; this lets you  reliably  test  the
	      return value.  Here are some examples:

		  # No "catch" invocations yet:	 sets a	to "Ok"
		  set a	catcherr()

		  # Sets b to "oops" and a to "Division	by zero"
		  set b	catch(1/0, "oops")
		  set a	catcherr()

		  # Sets b to 1	and a to "Division by zero".  The catch	error
		  # is never cleared by	a non-error catch()
		  set b	catch(4-3, "not-evaluated")
		  set a	catcherr()

       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
	      "".

       mbchar(i_i1 [,i_i2...])
	      This  function can take any number of INT	arguments.  It returns
	      a	STRING consisting of the characters  specified	by  the	 argu-
	      ments.   Any  codepoint may be supplied and a correct multi-byte
	      character	string will be returned.  Note that none of the	 argu-
	      ments can	be 0, unless there is only one argument.  As a special
	      case,  mbchar(0) returns "".  Additionally, no argument may be a
	      negative number.

       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.

	      The result of columns(str)  may  be  less	 than,	equal  to,  or
	      greater  than the	result of mbstrlen(str).  This is because some
	      Unicode characters are so-called combining characters  that  add
	      one  to  the  character  length, but don't occupy	any columns on
	      their own.  And other Unicode characters are double-width	 char-
	      acters that add one to the character length, but two to the num-
	      ber of display columns.

       const(x_arg)
	      Evaluates	 arg  and returns it, but also ensures that the	result
	      is marked	"constant".  Use with caution; incorrect use could re-
	      sult in unwanted reminders being purged in Purge Mode.  See also
	      the section "NON-CONSTANT	EXPRESSIONS"

       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, si_m, i_d)
	      The date() function returns a DATE object	with the  year,	 month
	      and  day	components  specified by y, m and d.  The month	can be
	      specified	as an integer from 1 to	12, or a string	 that  is  the
	      name of a	month.

       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,	 they are interpreted as year,
	      month, day and time.  Year and day must be INTs.	Month  may  be
	      an  INT from 0 to	12 or a	string naming a	month.	Time 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.	(Actu-
	      ally, month can also be a	string that is the name	of a month.)

       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(si_m, i_y) or	daysinmon(dq_date)
	      Returns the number of days in month m (1-12) of the year y.  The
	      first  argument  can  either  be	an  integer from 1 to 12, or a
	      string that is the name of a month.  If given a single  DATE  or
	      DATETIME	argument, returns the number of	days in	the month con-
	      taining the argument.

       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.

       eval(s_arg)
	      Parses the string	arg as an expression and evaluates it, return-
	      ing the result.  Note that any variable names in the parsed  ex-
	      pression	refer  to  global  variables, not any local variables.
	      For example, consider this:

		      SET x 2
		      FSET f(x)	x + eval("1 + x")
		      REM MSG F	is [f(9)]

	      The result will be "F is 12" because the reference to  x	inside
	      the  eval() argument refers to the global	variable x and not the
	      function argument.

	      Note that	for safety, RUN	is disabled during the	evaluation  of
	      eval(),  which  means  you  can't	 use the shell() function from
	      within an	eval().

       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"

       hex(i_n)
	      Returns a	STRING that is the hexadecimal	representation	of  n.
	      There  is	 no  "0x" prefix and any letters in the	returned value
	      are uppper-case.

       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.  Note that index uses byte positions, not	character  po-
	      sitions,	so  should  not	 be  used  on  non-ASCII strings.  Use
	      mbindex for non-ASCII strings.

       The first byte of a string is numbered 1.  If target 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.

       mbindex(s_search, s_target [,i_start])
	      Similar  to  index()  but	 returns the character position	rather
	      than the byte position.  Also, start is interpreted as a 1-based
	      character	index rather than a byte index.

       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)

       isconst(x_any)
	      Evaluates	its argument and then throws away the value, returning
	      1	 if  the  expression  is  constant or 0	if it is non-constant.
	      Note that	isconst	does not take into account the context;	if arg
	      is a constant expression but evaluated in	 a  non-constant  con-
	      text,  isconst  will still return	1.  For	details	about constant
	      vs.  non-constant	expressions, see the section "NON-CONSTANT EX-
	      PRESSIONS"

       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(dqis_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.  If arg is	a STRING,  re-
	      turns  the name of the month.  This last case might sound	silly,
	      but for example:

			   mon("Mar")

	      will return "March", the full name of the	month.

       monnum(dq_date) or monnum(s_str)
	      Returns an INT from 1 to 12, representing	the month component of
	      date.  If	a STRING is supplied rather than a DATE	 or  DATETIME,
	      then if str is a valid month name	(or minimum 3-character	abbre-
	      viation  of a month name)	then the corresponding month number is
	      returned.	 If str	is not a valid month name, then	an  error  oc-
	      curs.

       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.

       nonconst(x_arg)
	      Returns the argument arg unchanged, but forces the expression to
	      be  considered non-constant.  For	details, see the section "NON-
	      CONSTANT EXPRESSIONS"

       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".

	      In order to help with localization, if  you  define  a  function
	      called  ordx  that takes a single	parameter, then	calling	ord(n)
	      invokes ordx(n) and returns whatever it does.  During the	 call-
	      back to ordx, RUN	will be	disabled.

       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.

	      When shell runs cmd, it arranges for cmd's standard  input  file
	      descriptor to be connected to /dev/null.

	      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
	      (e.g., /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 unlikely), "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	in bytes.  If the length of str	is too
	      large to represent as an integer,	emits a	"Number	too high"  er-
	      ror.   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.

       mbstrlen(str)
	      Similar to strlen, but returns the length	of the string in char-
	      acters  rather than bytes	and is thus safe for use on multi-byte
	      strings.

       substr(s_str, i_start [,i_end])
	      Returns a	STRING consisting of all bytes in str from start up to
	      and including end.  Bytes	are numbered from 1.  If  end  is  not
	      supplied,	then it	defaults to the	length of str.	Because	substr
	      uses  byte  indexes rather than character	indexes, it should not
	      be used on multi-byte strings.

       mbsubstr(s_str, i_start [,i_end])
	      Similar to substr	but uses character indexes  rather  than  byte
	      indexes, and is thus safe	for use	on multi-byte strings.

       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.

       trigeventstarttz()
	      Similar to trigeventstart() but returns the DATETIME in the time
	      zone specified by	a TZ clause, if	one was	 present.   If	no  TZ
	      clause was present, returns the same value as trigeventstart().

       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.

       trigbase()
	      Returns  the  "base" date	of the last REM	or IFTRIG command.  If
	      the trigger specification	includes all three of day,  month  and
	      year,  then  the	base date is the date formed from those	compo-
	      nents.  If the trigger specification lacks one of	 those	compo-
	      nents, then 0 is returned.

	      Here is an example of how	trigbase() might be used:

		      REM 2025-05-05 *7	UNTIL 2025-05-26 \
			 MSG Meeting: week #[(trigdate() - trigbase())/trigrep()+1]

	      On   2025-05-05,	 it  would  print:  "Meeting:  week  #1".   On
	      2025-05-12, it would print: "Meeting: week #2" and so on.

       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.

       trigtz()
	      If  a  TZ	clause was used	in the last REM	or IFTRIG command, re-
	      turns the	time zone name.	 Otherwise returns the empty string.

       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")

       trigistodo()
	      Returns 1	if the last REM	command	was a TODO type	or 0 if	not.

       trigcompletethrough()
	      Returns  a  DATE object that is the COMPLETE-THROUGH date	of the
	      most recent REM command.	If there was no	COMPLETE-THROUGH date,
	      returns the INT 0.

       trigmaxoverdue()
	      Returns an INT that is the MAX-OVERDUE value of the most	recent
	      REM command.  If there was no MAX-OVERDUE	clause,	returns	-1.

       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.
	      Normally,	the date and time are the local	date  and  time;  how-
	      ever,  if	utcflag	is non-zero, the date and time are interpreted
	      as UTC times, and	are converted 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.

	      trigger()	will never return a date earlier than "1 January 1990"
	      even  if the UTC flag dictates that it should.  So do not	use it
	      for reminders before about 2 January 1990	 in  your  local  time
	      zone.   I	 do not	anticipate this	restriction being a real prob-
	      lem.

       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 in
	      the system default time zone.  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().

       trigtimetz()
	      Similar  to  trigtime()  but  returns  the time in the time zone
	      specified	by a TZ	clause,	if one was present.  If	no  TZ	clause
	      was present, returns the same value as trigtime().

       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 srczone is the empty string,
	      then the default system time zone	is used	as  the	 source	 zone.
	      If dstzone is omitted or is the empty string, the	default	system
	      time  zone is used as the	destination zone.  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

	      If  your	system includes	the directory /usr/share/zoneinfo, Re-
	      mind will	warn you if you	use an invalid time zone name for src-
	      zone or dstzone.	To suppress these warnings, add	a "!"  to  the
	      beginning	of the time zone name.

       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.  Note that	value evaluates	the second argument lazily; it
	      is not evaluated if varname is defined.

       version()
	      Returns a	string specifying the version of Remind.  For  version
	      06.01.08,	returns	"06.01.08".  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) or wkdaynum(s_str)
	      Returns a	number from 0 to 6 representing	the day-of-week	of the
	      specified	 date.	 (0 represents Sunday, and 6 represents	Satur-
	      day.)  If	a STRING is supplied, then if str is a	valid  weekday
	      name (or minimum 3-character abbreviation	thereof) then the cor-
	      responding  weekday  number  is returned.	 If str	is not a valid
	      weekday name, then an error occurs.

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

MACHINES WITH A	32-BIT TIME_T TYPE
       Internally, the standard	C library represents times as a	 time_t	 type.
       This  is	 a  signed  integer type that counts seconds since midnight, 1
       January 1970 UTC.  If the time_t	type is	only 32	bits in	size, then the
       C library cannot	represent times	after 19 January 2038 at 03:14:07 UTC.

       To work around this limitation, Remind will "fold" years	 greater  than
       2037  to	 a  smaller  year that begins on the same day and has the same
       number of days.	This results in	a year that's very likely to have  the
       same  daylight saving rules as the original year, unless	the rules have
       changed in the interim (in which	case the rule change could not even be
       represented on a	32-bit machine,	so it's	moot.)

       Remind then does	UTC-to-local  or  local-to-UTC	conversions  with  the
       folded  year,  and  then	post-conversion	corrects it back.  This	should
       give correct results for	astronomical functions and conversions between
       local and UTC time, providing the daylight saving time rules  have  not
       changed between the folded year and the original	year.

       Note  that  the $FoldYear system	variable is no longer that useful; Re-
       mind always folds years if it's necessary on a 32-bit system.  You  can
       set  $FoldYear to 1 to force Remind to fold years even on a 64-bit sys-
       tem, but	that's useful only for testing and not for production.

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.

       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 depth	of 64,
       across all levels of INCLUDE.

       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.  expr is not evaluated	at the time  the  function  is
       defined;	 instead,  it  is  evaluated each time the function is called.
       Args can	be empty, in which case	you define a function taking no	 para-
       meters.	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.

       o      If  a user-defined function is defined in	a context where	RUN is
	      disabled,	then whenever that function is	called,	 RUN  will  be
	      disabled during its evaluation, even if it is called from	a con-
	      text where RUN is	enabled.

       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.

       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 func-
       tion.  Alternatively, you can use a "-" token before the	function  name
       to suppress "redefined function"	warnings, as in	the following example:

	       FSET - f(x) 2*x
	       # You must have space before and	after the "-"
	       # This will NOT work:
	       # FSET -f(x) 2*x

SAVING AND RESTORING FUNCTIONS
       Occasionally,  it is useful to redefine a function for a	specific block
       of reminders, but to restore its	original definition at the end of that
       block.  Just as with variables, functions can be	pushed onto and	popped
       off an internal stack.  Here is an example:

	       PUSH-FUNCS msgprefix
	       FSET msgprefix(x) "My new prefix: "
	       INCLUDE block_of_reminders.rem
	       POP-FUNCS

       The file	block_of_reminders.rem would be	executed  with	the  msgprefix
       function	 defined  above.   After  the POP-FUNCS	msgprefix would	be re-
       stored to its previous definition if it had one,	or simply unset	if  it
       was not previously defined.

       The  command PUSH-FUNCS takes a space-separated list of function	names.
       All of the named	user-defined functions will be saved  to  an  internal
       stack.  You can even push names that are	not defined as any function.

       After  a	function name has been pushed, Remind will not issue a warning
       if you redefine it, because presumably the purpose of pushing it	in the
       first place is to redefine it.

       The command POP-FUNCS restores the definitions of all the  user-defined
       functions  in the corresponding PUSH-FUNCS command.  If undefined func-
       tions were pushed onto the stack, then POP-FUNCS	makes those  functions
       undefined again.	 Here's	one more example:

	       FUNSET a
	       FSET b(x) 2*x
	       REM MSG [b(3)]	# Outputs 6
	       PUSH-FUNCS a b
	       FSET a(x) 22*x
	       FSET b(x) 3*x
	       REM MSG [a(3)] [b(3)] # Outputs 66 9
	       POP-FUNCS
	       REM MSG [a(3)]	# Undefined function "a"
	       REM MSG [b(3)]	# Outputs 6

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 "shextvlfqnu"
       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	[-c] [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.

       If  you supply the -c flag, then	any variable determined	to be constant
       will have its value followed by "<const>"

       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.

AGENDA MODE JSON OUTPUT
       If you supply the --json	argument, then Remind outputs JSON instead  of
       the  normal text	output.	 The JSON output consists of a single JSON ar-
       ray of zero or more objects.  There are three possible types of objects
       in the array:

       banner The banner object, if present, will be the first object  in  the
	      array.   There will be at	most one banner	object.	 It contains a
	      single key, banner, whose	value is the banner that Remind	 would
	      normally print in	Agenda Mode.

       noreminders
	      The  noreminders object, if present, will	be the final object in
	      the array.  There	will be	at most	one  noreminders  object.   It
	      contains	a  single keym,	noreminders, whose value is the	phrase
	      "No reminders.", possibly	localized into a different language.

       event  All other	objects	in the array are event objects.	 They are JSON
	      objects that contain all of the keys described in	the  rem2ps(1)
	      man  page	 section  "CALENDAR  ENTRIES".	 However,  the	calen-
	      dar_body,	plain_body and raw_body	keys will not be present.

       JSON output can be used by a front-end to display an attractive list of
       reminders in Agenda Mode.  The  "show  today's  reminders"  feature  of
       tkremind	uses the JSON output.

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 agenda mode, Remind would print "Dianne's birthday is	 today"	 on  6
       January.	 However, in the calendar mode,	only the text "Dianne's	birth-
       day" 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: or a relative SCANFROM clause

	  #!P! Could not parse next line: Some-Error-Message-Here

	  #!P! Problem calculating trigger date

       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.

       If you use the "Hush" flag -h in	conjunction with the "Purge" flag  -j,
       then  Remind  does  not	create	any  of	the diagnostic comments	listed
       above.  Instead,	the only change	it makes to the	 .purged  file	is  to
       mark expired reminders with "#!P: Expired".

NON-CONSTANT EXPRESSIONS
       In  Purge  Mode,	Remind will not	mark a REM statement as	expired	if its
       trigger specification contains a	non-constant expression.   A  non-con-
       stant expression	is defined as one whose	value might differ from	run to
       run, usually because it depends on the current date, but	also if	it de-
       pends  on  something  from  the	environment (such as the output	of the
       shell() function.)

       The use of any of the following in an expression	causes Remind to  con-
       sider it	non-constant:

	      o	     A	global variable	that has been assigned the result of a
		     non-constant expression, or  that	has  been  assigned  a
		     value in a	non-constant context (to be described later.)

	      o	     A system variable

	      o	     Certain  built-in	functions  that	 depend	on the current
		     date (for example,	today()) or the	environment (for exam-
		     ple, shell()).

       In addition, for	the purposes of	safely	expiring  reminders  in	 Purge
       Mode, Remind considers the following to be non-constant:

	      o	     The use of	an OMITFUNC

	      o	     The use of	a relative SCANFROM

       Whenever	 a  variable is	assigned a value, Remind tracks	whether	or not
       the expression whose value it was assigned is constant or non-constant.
       Additionally, variables that are	assigned in a non-constant context are
       always assumed to be non-constant.  A non-constant context is the  code
       in  the	scope  of  an IF statement where the IF	expression is non-con-
       stant.

       Here are	some examples that should make things clear:

	       SET d '2025-06-01'	 # d is	constant
	       REM [d] MSG Hello!	 # eligible for	purging

	       SET d today() - 3	 # d is	non-constant
	       REM [d] MSG Hello!	 # not eligible	for purging

	       IF wkdaynum(today()) == 3
		   set d '2025-06-01'	 # d is	non-constant
	       ELSE
		   set d '2026-01-01'	 # d is	non-constant
	       ENDIF

	       SET d '2025-06-01'	 # d is	constant
	       IF today() > today() + 3	 # This	branch is never	taken, but...
		   SET d '2029-01-01'	 # d is	still marked non-constant
	       ENDIF

	       # Although here d is still '2025-06-01',	it is marked
	       # non-constant because as far as	Remind is concerned,
	       # the IF	body *might* have been executed	depending on today()

       Note that within	the IF...ENDIF scope, any assignments are non-constant
       because the code	flow depends on	today's	date, which  could  change  in
       subsequent  Remind runs.	 If you	want to	force a	variable to be treated
       as constant, no matter what, then use the following just	before you use
       the variable:

	       SET var const(var)

       Variables initialized on	the command-line with the -i flag  are	always
       considered to be	non-constant.

       If  you	have  an  expired reminder that	for some reason	you never want
       purged, simply use the built-in	function  nonconst  somewhere  in  the
       trigger.	 For example:

	       REM 1992-01-01 MSG This will be purged after Jan	1 1992
	       REM [nonconst('1992-01-01')] MSG	This will never	be purged

	       REM Wed UNTIL 1993-12-31	MSG This will be purged	after 1993
	       REM Wed UNTIL [nonconst('1993-12-31')] MSG Never	purged

       The n debugging flag prints a message to	standard error whenever	Remind
       decides	that  an expression is non-constant.  This can produce a large
       amount of output, so if you want	to find	out  why  Remind  considers  a
       specific	 expression  to	be non-constant, it's best to use DEBUG	+n be-
       fore it and DEBUG -n after it to	limit the amount of output.

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 agenda 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 override	substitution sequences that are	 not  alphanumeric  as
       follows:

	      Override %: with subst_colon

	      Override %! with subst_bang

	      Override %? with subst_question

	      Override %@ with subst_at

	      Override %# with subst_hash

       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.

       Note  that when Remind invokes any callback function for	a substitution
       sequence, RUN will be disabled.

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  works  similarly	 to MSG	when the -p option is not sup-
       plied.)

       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 agenda	 mode,	remind
       treats a	COLOR special just like	a MSG-type reminder.  Also, if you in-
       voke 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

       A SCANFROM that specifies a full	date is	called	an  absolute  SCANFROM
       and  a  SCANFROM	 that specifies	a negative number is called a relative
       SCANFROM.

       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  or  SATISFY
       clause,	and  contained all of the day, month and year components, then
       Remind will correctly 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)

Remind				  2025-10-27			     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+15.0>

home | help