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

FreeBSD Manual Pages

  
 
  

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

NAME
       remind -	a sophisticated	reminder service

THE BOOK OF REMIND
       This  man  page	is a good reference for	Remind.	 However, if you are a
       novice wishing to learn Remind, I suggest downloading "The Book of  Re-
       mind" from the Remind home page at https://dianne.skoll.ca/projects/re-
       mind/

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.

	      'z'    has  the effect of	setting	the system variable $Terminal-
		     Hyperlinks	to 1.  See the documentation of	this  variable
		     in	the section "SYSTEM VARIABLES"

	      '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[,spc2]]]]
	      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.	 spc2 may be 0
	      or 1 and it specifies whether  or	 not  blank  lines  should  be
	      printed in between reminders on the same day.  The default is 1,
	      which causes the blank lines to be printed.

	      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

	      p	     Issue  warnings  if  a POP-OMIT-CONTEXT, POP-VARS or POP-
		     FUNCS matches a corresponding PUSH	that is	in a different
		     file.

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

       While back-ends can choose which	INFO strings to	support, all back-ends
       should endeavor to support three	standard ones: Location:, Description:
       and Url:.  TkRemind supports all	three of these,	turning	reminders with
       a Url: INFO string into hyper-links, and	popping	up information windows
       for the Location: and Description: INFO strings.	  Location:  and  Url:
       are self-explanatory; Description: is meant for a longer, more in-depth
       description  of	the  reminder  than  the summary that is normally dis-
       played.

       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.   The keyword COMPLETED-THROUGH may be used as a synonym for COM-
       PLETE-THROUGH.

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, and several more.  These are not safe to  use
	      on  multi-byte strings; instead use mbindex, mbstrlen and	mbsub-
	      str, and the mb variants of the others.  If you  know  for  sure
	      that  a  string  contains	 only single-byte characters, then the
	      byte-oriented versions may be  used  and	are  faster  than  the
	      multi-byte versions.

       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",  "",	 "  is
	      Cool! "

	      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.   The  default  value  is
	      10,000.

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

       $Shaded (read-only)
	      Returns  the  number of times a SHADE special reminder has trig-
	      gered.  This variable is set only	in calendar mode,  not	agenda
	      mode.  You can use this variable to avoid	shading	a calendar day
	      that has already been shaded.

	      For example, suppose you want to shade all calendar boxes	yellow
	      if  any  reminders have triggered	on that	day.  But if a box has
	      been explicitly shaded, you don't	want to	overwrite  that	 shad-
	      ing.  You	could use something like this:

		      SET n $NumTrig
		      #	Do all your reminders here...

		      #	If anything has	triggered and the box is
		      #	not already shaded, then shade it yellow
		      IF $NumTrig > n && !$Shaded
			  REM SPECIAL SHADE 255	255 128
		      ENDIF

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

       $TerminalHyperlinks (INT	type)
	      If  your	terminal  supports escape sequences to allow HTML-like
	      anchors	around	 text	(see	https://gist.github.com/egmon-
	      tkob/eb114294efbcd5adb1944c9f3cb5feda),  then  you  can set this
	      variable to 1.  Remind will then make any	reminder with a	"Url:"
	      info string into a hyperlink  in	your  terminal.	  By  default,
	      $TerminalHyperlinks is set to 1 if Remind's standard output is a
	      terminal,	or to 0	if it is not.

       $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
	      either  standard	output or standard error is a TTY, returns the
	      width of the terminal in columns.	 If  neither  standard	output
	      nor  standard error is a TTY, attempts to	open "/dev/tty"	to ob-
	      tain 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 bytes in string converted
	      to lower-case.  Note: This function  works  correctly  only  for
	      ASCII  strings.  If you are using	Unicode	characters outside the
	      ASCII set, use mblower instead.

       mblower(s_string)
	      Returns a	STRING with all	upper-case characters in  string  con-
	      verted to	lower-case.  This function works correctly on any Uni-
	      code string.

       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.  Note
	      that in Calendar Mode, now() always returns 00:00.

       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 bytes, pads to to len bytes using
	      as many copies (including	partial	copies)	of  padstr  as	neces-
	      sary.   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"

       mbpad(x_arg, s_padstr, i_len [, i_right])
	      This is the multibyte counterpart	to pad.	 The length is	speci-
	      fied in characters rather	than bytes.  Use mbpad rather than pad
	      if either	of the strings contains	non-ASCII characters.

       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, or 00:00 in Calendar Mode.

       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 either	standard output	or standard error is  a	 TTY,  returns
	      the  height of the terminal in rows.  If neither standard	output
	      nor standard error is a TTY, attempts to open "/dev/tty" to  ob-
	      tain 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 (in	Calen-
	      dar Mode)	the date of the	calendar entry	currently  being  com-
	      puted.

       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 bytes in string converted
	      to upper-case.  Note: This function  works  correctly  only  for
	      ASCII  strings.  If you are using	Unicode	characters outside the
	      ASCII set, use mbupper instead.

       mbupper(s_string)
	      Returns a	STRING with all	lower-case characters in  string  con-
	      verted to	upper-case.  This function works correctly on any Uni-
	      code string.

       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.02.05,	returns	"06.02.05".  It	is guaranteed that as new ver-
	      sions of Remind are released, the	value  returned	 by  version()
	      will strictly increase, according	to the rules for string	order-
	      ing.

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

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

       wkdaynum(dq_date) 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.  If you are in a UTF-8 locale, you can also
       use the UTF-8-encoded Hebrew spellings for the month names, namely:

       , , , , , ,  , ,	, , , .

       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,
       or in Hebrew, '	and ' .

       Remind also permits the	following  alternative	spellings  for	Hebrew
       month names:

       Tishrey
	      Can also be spelled Tishri or Tishrei

       Heshvan
	      Can also be spelled Cheshvan or Kheshvan

       Shvat  Can also be spelled Shevat

       Tamuz  Can also be spelled Tammuz

       Adar A Can also be spelled Adar 1, Adar I,   or	1.

       Adar B Can also be spelled Adar 2, Adar II,   or	 2.

       Iyar   Can also be spelled Iyyar.

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

       ivritmon(d_date)
	      Returns the name of the Hebrew month corresponding to  date,  in
	      UTF-8-encoded Hebrew script. For example,	ivritmon('1993/04/12')
	      returns "	".

       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 either the English
	      transliteration shown previously,	or the Hebrew spelling encoded
	      in UTF-8.	 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				  2026-03-02			     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.1.quarterly>

home | help