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

FreeBSD Manual Pages

  
 
  

home | help
REMIND(1)			VERSION 06.02.07		       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 Remind" from
     the Remind home page at the following URL:

	     https://dianne.skoll.ca/projects/remind/

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 reminder 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 to-
	    day's reminders on standard output and exits.  It may fork	a  back-
	    ground 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 Re-
	    mind in daemon mode.

     Purge Mode
	    In this mode, Remind produces no output, but creates new versions 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 re-
	    minder  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 op-
	    tion.

     -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 de-
	    fault, a calendar for only the current month is produced.  This  op-
	    tion 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  speci-
		   fied by the reminder's delta.  This also causes Remind to in-
		   clude  text outside %"...%" sequences that would otherwise be
		   removed (though the actual  %"  markers  themselves	are  re-
		   moved.)

	    '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 charac-
		   ter 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 dis-
		   play.

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

	    'c'    causes  Remind  to  use VT100 escape sequences to approximate
		   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 creat-
	    ing a calendar with the -c option.	Some terminals don't handle this
	    correctly and garble the rendering of the calendar; see the documen-
	    tation 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	necessity)  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 considered "bright".

	    If you supply the optional numeric parameters, the have the  follow-
	    ing meanings:  n=0 tells Remind to use the standard 16 VT100 colors.
	    n=1  tells it to use an extended 256-color palette supported 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 Remind 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 reminders may be hard or
	    impossible to see if the color is too close to  the  terminal  back-
	    ground color.  If you supply the letter t rather than a number, then
	    Remind  attempts to guess the background color of the terminal, even
	    if stdout is not a terminal.

	    On startup, if the standard output is a terminal, Remind attempts 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 emitting 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 clamping 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 termi-
	    nal, or to 80 if standard output is not a terminal.  If col is spec-
	    ified as the letter t, then Remind attempts 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 win-
	    dow:

		    remind -c -wt .reminders | less

	    Note that the value of col is also used to set the	system	variable
	    $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 certain 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 out-
	    put calendar is not formatted.  It is listed in  a	"simple  format"
	    that  can  be  used as input for more sophisticated calendar-drawing
	    programs.  If n starts with "+", then it is interpreted as a  number
	    of weeks.  This option also implicitly enables the -o option.

	    If	you immediately follow the s with the letter a, then Remind dis-
	    plays reminders on the calendar on the day they  actually  occur  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 out-
	    put  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 implicitly enables the pure JSON inter-
	    change 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 dis-
	    plays reminders on the calendar on the day they  actually  occur  as
	    well as on any preceding days specified by the reminder's delta.  If
	    you  follow the p with another p, then Remind uses a more comprehen-
	    sive 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  for-
	    mat,  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 Re-
	    mind outputs additional information for back-end  programs	such  as
	    rem2ps.  This additional information lets the back-end programs cor-
	    relate 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  er-
	    ror,  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 options is
	    used, if a repetition factor *n is used, or if a date other than to-
	    day's date is specified on the command-line.

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

     -tn    If you supply a number n after the -t option, then	Remind	pretends
	    that  every REM command has a delta of ++n, regardless of any exist-
	    ing 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 supplied  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  minutes
	    for all timed reminders.  If -tt is given with no n, a default delta
	    of 5 minutes is used.

     -h     The -h option ("hush...") suppresses certain warning and information
	    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  in-
	    clude  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 pro-
	    cessing queued reminders,  rather  than  forking  off  a  background
	    process to handle them.

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

     -dchars
	    The -d option enables certain debugging modes.   The  chars  specify
	    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 expression
		   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 warnings.
		   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 ex-
		   pression to be "non-constant"

	    q	   Output a TRANSLATE command each time the _()  built-in  func-
		   tion is called or the %(...) substitution sequence is encoun-
		   tered.

     -g[a|d[a|d[a|d[a|d]]]]
	    Normally,  reminders  are  issued in the order in which they are en-
	    countered 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 outputs.  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 inser-
	    tion of times in the calendar output.

     -x[n]  Sets the iteration limit for the SATISFY clause of	a  REM	command.
	    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  reminder  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	xmessage
	    that  pops	up  a window and displays its invocation arguments.  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.  Because
	    all shell and whitespace characters are escaped, the program you ex-
	    ecute with the -k option must be prepared to handle the entire  mes-
	    sage as a single argument.

	    If	you  follow  the -k option with a colon, then the command is ap-
	    plied only to queued timed reminders.  Normal reminders are  handled
	    as	usual.	 In  the  above example, if you want normal reminders to
	    simply be displayed as usual, but queued reminders to be sent to no-
	    tify-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 defaults 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  di-
	    rectory,  Remind additionally checks if all files within that direc-
	    tory 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 tkre-
	    mind(1).   The older server mode option -z0 still works, but is dep-
	    recated; it uses an ad-hoc method to  communicate  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 environ-
	    ment variables HOME, SHELL and USER to the	home  directory,  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 Re-
	    mind 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 disabled.  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.  Normally,
	    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 -+ options 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 "INITIAL-
	    IZING 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 de-
     faults to 1.  If you leave out the year, then it defaults	to  the  current
     year.  You cannot leave out the month.

     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 disables 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  com-
     mand line as one argument: YYYY-MM-DD@HH:MM.

     You can also specify the date as a trigger by prefixing it with the at sym-
     bol,  "@".   You  might  need  to quote the argument.  In this case, Remind
     evaluates everything after the "@" as a trigger and the  resulting  trigger
     date  is  used as the effective date.  For example, if you want to see what
     reminders will trigger on the next Friday the 13th, you could use this:

	 remind .reminders '@13 SATISFY [$Tw == 5]'

     You can also specify the date directly and use an "@" trigger argument;  in
     this  case,  Remind  uses	the specified date as the starting point for the
     trigger calculation.  As an example:

	 remind .reminders 2026-07-01 '@13 SATISFY [$Tw == 5]'

     will set Remind's notion of "today" to 2026-11-13 because that is the first
     Friday the 13th on or after 2026-07-01.

     In addition, you can supply a repeat parameter, which has	the  form  *rep.
     This  causes Remind to be run rep times, with the date incrementing on each
     iteration.  You may have to enclose the parameter in quotes to avoid  shell
     expansion.   See the subsection "Repeated Execution" in the section "CALEN-
     DAR 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 supply
	    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 output.
	    --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 Calendar Mode.  Note that
	    in JSON mode, the output from any RUN-type reminder that would  nor-
	    mally  appear on standard output is redirected to standard error in-
	    stead; 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 error
	    messages to standard output and then exit.	The messages are printed
	    in a format suitable for the first argument of a TRANSLATE	command.
	    If you TRANSLATE the error messages, then Remind will use the trans-
	    lated versions when outputting error and warning messages.	See also
	    TRANSLATE GENERATE in the section "THE TRANSLATION TABLE".

	    Note  that	if an untranslated message contains printf-style format-
	    ting 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	existing
	    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  potentially-un-
	    trustworthy  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 Re-
	    mind.  If Remind finishes processing the script and then starts han-
	    dling 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, oper-
	    ator,  constant,  variable reference, etc corresponds to one expres-
	    sion 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 ap-
	    ply.   The default limit of ten million should never be triggered by
	    any sensible Remind script, however, 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 standard
	    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 editor
     capable of creating plain-text files to create a Remind script.   The  com-
     mands 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.  Several
     lines can be continued using the backslash character, as in the above exam-
     ple.  In this case, all of the concatenated lines are treated as  a  single
     line by Remind.  Note that if an error occurs, Remind reports the line num-
     ber of the last line of a continued line.

     Remind ignores blank lines, and lines beginning with the '#' or ';' charac-
     ters.  You can use the semicolon as a comment character if you wish to pass
     a Remind script through the C pre-processor, which interprets the '#' char-
     acter 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  upper-
     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 com-
     mand is responsible for issuing reminders.  Its syntax is:

	    REM  [ONCE]  [date_spec] [back] [delta] [repeat] [TODO] [MAX-OVERDUE
	    n] [COMPLETE-THROUGH complete_date] [PRIORITY prio] [SKIP | BEFORE |
	    AFTER] [OMIT omit_list] [ADDOMIT] [NOQUEUE] [OMITFUNC omit_function]
	    [AT time [tdelta] [trepeat]] [SCHED sched_function] [WARN warn_func-
	    tion] [UNTIL expiry_date | THROUGH last_date] [SCANFROM scan_date  |
	    FROM  start_date]  [DURATION duration] [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 compli-
     cated 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  SUBSTITUTION	FILTER."
     However,  if  you	have  used the -k command-line option, then MSG-type re-
     minders 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 warn-
     ing.  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 re-
     minder is formatted to fit into  a  paragraph-like  format.   Three  system
     variables control the formatting of MSF-type reminders - they are $FirstIn-
     dent,  $SubsIndent and $FormWidth.  They are discussed in the section "SYS-
     TEM VARIABLES." The MSF keyword causes the spacing of your reminder  to  be
     altered - extra spaces are discarded, and two spaces are placed after peri-
     ods and other characters, as specified by the system variables $EndSent and
     $EndSentIg.  Note that if the body of the reminder includes newline charac-
     ters  (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 single reminder body.

     A RUN-type reminder also passes the body through the  substitution  filter,
     but  then	executes the result as a system command.  A CAL-type reminder is
     used only to place entries in the calendar produced when Remind is run with
     the -c, -s or -p options.	When Remind runs a command,  it  sets  the  com-
     mand'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 program-
     mer.  The PS and PSFILE reminders are ignored unless Remind is run with the
     -p option.  See the section "More about PostScript" for more details.

     A SPECIAL-type reminder is used to pass "out-of-band" information from  Re-
     mind to a calendar-producing back-end.  It should be followed by a word in-
     dicating  the type of special data being passed.  The type of a special re-
     minder depends on the back-end.  For the  Rem2PS  back-end,  SPECIAL  Post-
     Script  is  equivalent to a PS-type reminder, and SPECIAL PSFile is equiva-
     lent to a PSFILE-type reminder.  The body of a SPECIAL  reminder  is  obvi-
     ously  dependent  upon the back-end.  A back-end must ignore 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 ex-
     ample:

	     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  speci-
     fied 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 weekday con-
     straint.  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 issued
     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  statements
     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 statements
     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 following
     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 us-
     ing 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  al-
     gorithm;  it  would  be much too slow in practice.  Internally, 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 com-
     puted as the first Monday in the next month, minus 7 days.  The back speci-
     fication 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 sev-
     eral 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 periodic
     reminders.  For example, an event occurring every Wednesday could be speci-
     fied as:

	  REM Wed MSG Event!

     However, events that do not repeat daily, weekly, monthly or yearly require
     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 op-
     tionally weekday); this is the start date of the  repetition  period.   The
     repeat component is an asterisk followed by a number specifying the repeti-
     tion 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 repeats 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  COMPUTATION"
     near  the end of this manual.  Note that SCANFROM is available only in ver-
     sions 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 information.)

     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 until  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  trig-
     gered  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 overrides 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 several
     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 VARIABLES 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  ig-
     nored 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  fol-
     lowed 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 Fri-
     day.  This is because the delta of +1 does not  count  Saturday  or  Sunday
     when  it  counts  backwards from the trigger date to determine how much ad-
     vance 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 exam-
     ple:

	     OMIT Sat Sun
	     REM 15 OMIT Fri Sat MSG Whatever

     In the REM command, the effective list of omitted weekdays will be  Friday,
     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)  re-
	    turns  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 is-
     sued  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 function
     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 omit-
     ted.  For that reason, when Remind searches through omitted days, it termi-
     nates  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  repre-
     senting one minute to midnight.  Alternatively, it may be specified in com-
     mon  "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  repre-
     sents one minute to midnight.  The "am" and "pm" portions are case-insensi-
     tive and the "m" is optional.

     You  can use either a colon or a period to separate the hours from the min-
     utes.  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 re-
     minder happening at the specified time.

     If you use a very large tdelta, then Remind  will	queue  future-dated  re-
     minders whose tdelta and optional trep would cause them to be issued today.

     However,  if  you use the SCHED keyword, then any tdelta is ignored and you
     cannot force the reminder to be queued  earlier  than  the  actual  trigger
     date.

     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  al-
     ways  issued at the specified time, even if the tdelta is not a multiple 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	reminder
     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  op-
     tion.   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 activated,
     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 explained.	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 TkRemind.  These
     back-ends have specific rules about tags; see their documentation	for  de-
     tails.

     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 in-
     clude 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 before 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 de-
     scription 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-ex-
     planatory; Description: is meant for a longer, more in-depth description of
     the reminder than the summary that is normally displayed.

     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  start-
     ing 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 sim-
     plify 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 minutes
     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 reminders.
     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 following
     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  cannot  be
     combined  with  a	day.   Additionally, First/Second/Third/Fourth/Last must
     have at least one weekday name.  The following 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  sub-
     stitution	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 Thursday, 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 num-
	    ber 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 Thursday."

	    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 appends
	    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  reminders
	    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 lead-
	    ing 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  similar
	    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  trigger
	    date.   The  diff  is  defined  as the actual number of days between
	    these two dates; OMITs are not counted.  (Strict date subtraction 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  table.
	    It	is  the  equivalent of [_("any_text")] but is more convenient 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 equiva-
	    lent of [triginfo("any_text")] but is more convenient 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 calendar
		   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.
	    If the reminder is more than a day in the future,  then  the  phrase
	    will  be prefixed by "d days,".  Note that unless you specify the -a
	    option, timed reminders 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
	    "current"  and the trigger date and 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  number
	    produced by %4.

     %6     is	replaced with "ago" or "from now", depending on the relationship
	    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 and always between 0 and
	    23.  (That is, for events more than a day away,  the  days	are  not
	    counted in %7.)

     %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 %!   se-
	    quence 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 %?  se-
	    quence 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 se-
	    quence 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 in-
	    clude 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  $Ad-
	    dBlankLines to 0.

     o	    Substitutions  a,  b, c, e, f, g, h, i, j, k, l, u and v all are re-
	    placed 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  sim-
	    pler %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 un-
	    defined results if used in a reminder that does not have an AT  key-
	    word.   Also, if a reminder has a delta and may be triggered on sev-
	    eral days, the time substitutions ignore the  date.   Thus,  the  %1
	    substitution  may  report that a meeting is in 15 minutes, for exam-
	    ple, 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  de-
	    signed 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  capitalized
	    (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 Remind normally
	    scans  for the first non-space character after a MSG, CAL or RUN to-
	    ken.

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 matter
     what action you take.  Events  include  things  like  birthdays,  holidays,
     meetings,	etc... pretty much everything that occurs on a particular sched-
     ule.  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 specific
     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 buy 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  recurring,
     the  simplest way is simply to remove the TODO designator from the REM com-
     mand (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 re-
     currences 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	COMPLETE-THROUGH
     date,  then  after  30 April 2026, Remind will keep reminding 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 COMPLETE-
     THROUGH.

LIMITING REMINDERS ABOUT OVERDUE TODOS
     Although Remind is happy to keep reminding you about overdue TODOs for hun-
     dreds 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 reminding 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.   How-
     ever,  the  last  time it will remind you will be on 2025-08-18, because of
     the MAX-OVERDUE clause.  Starting on 2025-08-19, Remind will no longer  re-
     mind 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 algorithm.  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 out-
     put:

	 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 examples:

	 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 re-
     minders 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 exam-
     ple, 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 before
     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 output.

     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  count-
     ing  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  holi-
     day:

	  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 November
     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 meeting 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 keyword 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 followed
     by the case-sensitive time zone name in which the command is to  be  inter-
     preted.   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 com-
     mand.  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 adjustment.

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

     If  you  are on a system that stores time zone data in /usr/share/zoneinfo,
     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  speci-
     fied  time  zone.	 Here's an example: Suppose the local time zone is Amer-
     ica/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	trigger.
     Even  though  2025-09-05  has  been OMITted, the SKIP keyword evaluates 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 reminder
     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, similar
     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 file-
     name  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 order; the
     sort order matches that used by the shell when it expands "*.rem".

     Note that the file specified by an INCLUDE command is interpreted	relative
     to the current working directory of the Remind process.  If you want to in-
     clude  a file relative to the directory containing the currently-processing
     file, use DO instead.  For example, if the current file is  /home/user/.re-
     minders/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-compatibility, 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 symbolic
     link itself, DO will fail.  Remind does not resolve the real path	of  sym-
     bolic links, so you should avoid using symbolic links to files.

     The  SYSINCLUDE  command  is similar to DO, but it looks for relative path-
     names under the system directory containing standard reminder scripts.  For
     this installation of Remind, the system directory is  "/usr/local/share/re-
     mind".

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 en-
     tirely trust the contents of the other files.  For example, they  may  con-
     tain  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 reminder or expres-
     sion 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 reminder 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  commands  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()  func-
     tion.  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  returns
     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 INCLUDECMD
     is if you have your reminders stored in a file in some  non-Remind  format;
     you  can write a command that transforms them to Remind format and then Re-
     mind can "include" the file with an appropriate INCLUDECMD command.

     Note that if RUN is disabled, then INCLUDECMD will fail with the error mes-
     sage "RUN disabled"

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

     INCLUDECMD  passes  the rest of the line to popen(3), meaning that the com-
     mand is executed by the shell.  As such, shell meta-characters may need es-
     caping 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 INCLUDECMD uses expres-
     sion-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  current  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 expressions
     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 ma-
	    chine word.  The INT data type corresponds to the C "int" type.

     STRING
	    The STRING data type consists of strings of characters.  It is some-
	    what comparable to a C character array, but more  closely  resembles
	    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 environment, the string "dh"
	    contains one character but four bytes.  And the  string  "A(C)A(C)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 mbsubstr, and
	    the mb variants of the others.  If you know for sure that  a  string
	    contains  only  single-byte  characters, then the byte-oriented ver-
	    sions may be used and are faster than the multi-byte versions.

     TIME   The TIME data type is used for two different purposes:  To represent
	    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 de-
	    termines 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  upper
	    limit  on the hour component (beyond that imposed by the restriction
	    that a duration expressed in minutes must fit into the signed  inte-
	    ger  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.  Inter-
	    nally, DATETIME objects are stored as the number  of  minutes  since
	    midnight, 1 January 1990.  You can think of a DATETIME object as be-
	    ing 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", "", "I is Cool!
	    dh"

	    Note that the empty string is represented by  "".	Remind	supports
	    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 digits; this operates
	    just as in C.  The "\x" must be followed by one or two  hex  digits;
	    the escape sequence "\x00" is not permitted.

	    To	include a quote in a string, use "\"".	Any other character pre-
	    ceded 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 com-
	    mon "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 sepa-
	    rate the minutes from the hours.  However, Remind will  consistently
	    output  times  in 24-hour format using only one separator character.
	    (The output separator character is chosen at compile-time.)

	    If the TIME is used where Remind expects a time-of-day (for example,
	    in an AT clause), then it can be written in 24-hour format	(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 expects 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 con-
	    stants 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  ei-
	    ther '-' 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 versions of  Re-
	    mind  prior  to  03.00.01  did not support date constants.	In those
	    versions, you must create dates using the  date()  function.   Also,
	    versions prior to 03.00.02 did not support 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.  Alternatively, if
	    one argument is a STRING and the other an INT, returns a STRING con-
	    sisting  of  the  INT  number of repeats of the original STRING.  In
	    this case, the INT argument cannot be negative.

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

     %	    Modulus.  Returns the remainder upon dividing one INT by another.

     +	    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, convert-
	    ing  it to an integer number of minutes past midnight, and then per-
	    forms 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 mid-
	    night, 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 ar-
	    gument  to	a  STRING, and then performs concatenation.  See the co-
	    erce() 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  between
	    two TIMEs.

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

	    DATE - INT - returns a DATE that is INT days earlier than the origi-
	    nal 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 sub-
	    traction 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 comparison
	    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 dis-
	    tinct 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 != re-
	    turns 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 interpreted as appro-
	    priate 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 interpreted as  ap-
	    propriate 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" error.  Unlike
     C,  integer  operations  will  not  simply give the wrong answer in case of
     overflow.

     Operators of equal precedence are always evaluated from left to right,  ex-
     cept  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 underscore,
     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 vari-
     ables"  that  are	used  to query or control the operating state of Remind.
     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  vari-
     ables  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 dol-
     lar sign.	System variable names are not case-sensitive.

     The  following system variables are defined.  Those marked "read-only" can-
     not be changed with the SET command.  All system variables hold  values  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 suppressed by end-
	    ing the reminder or banner with a single  percent  sign.)	If  $Ad-
	    dBlankLines  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 new-
	    line.

     $CalcUTC
	    If 1 (the default), then Remind uses C library functions  to  calcu-
	    late  the number of minutes between local and Universal Time Coordi-
	    nated.  This affects astronomical calculations (sunrise() for  exam-
	    ple.)   If 0, then you must supply the number of minutes between lo-
	    cal and Universal Time Coordinated in the $MinsFromUTC system  vari-
	    able.

     $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 vari-
	    able 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 be-
	    tween 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 character
	    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  duplicate
	    reminders.	 A  given  reminder is considered to be a duplicate 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 issued.
	    In December of 2024, "Phooey" will be issued every Wednesday as well
	    as on Friday, 20 December 2024

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

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

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

	    Duplicates	are  detected after all variable expansion and substitu-
	    tions 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  dupli-
	    cate 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 $De-
	    faultColor is "-1 -1 -1", which suppresses default coloring of  MSG-
	    type  reminders.   If you set $DefaultColor to any other value, then
	    all MSG-, MSF- and CAL-type reminders are effectively converted into
	    SPECIAL COLOR reminders whose color value is specified by  $Default-
	    Color.

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

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

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

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

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

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

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

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

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

     $EndSentIg (STRING type)
	    Contains a list of characters that should be ignored  when	MSF  de-
	    cides  whether  or	not  to place two spaces after a sentence.  Ini-
	    tially, 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 pur-
	    poses 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, $ExpressionTimeLimit 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 saving time are thus presumed to
	    be identical for both years, and the Unix library functions can han-
	    dle 2027.  By default, this variable is 0.	Set it to 1 if	the  sun
	    or	UTC  functions	misbehave for years greater than 2037.	See also
	    the section "MACHINES WITH A 32-BIT TIME_T TYPE"

     $FormWidth
	    The maximum width of each line of text for formatting  MSF-type  re-
	    minders.  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 re-
	    minder contains a word too long to fit in this width, it will not be
	    truncated - the width limit will be ignored.

     $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 direc-
	    tives 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  in-
	    tegers   using   twos-complement   representation,	 this	will  be
	    2147483647.

     $IntMin (read-only)
	    The smallest representable INT.  On a machine with 32-bit signed in-
	    tegers  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 float-
	    ing-point type, we need to express it as a	string.   $Latitude  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, $Latitude 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 float-
	    ing-point type, we need to express it as a string.	 $Longitude  can
	    range  from  "-180.0" to "180.0", with positive numbers representing
	    points east of the Greenwich Meridian and  negative  numbers  repre-
	    senting  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  latitudes  are
	    positive;  southern  ones are negative.  For southern latitudes, all
	    three components should be negative.  These three variables are dep-
	    recated; you should use $Latitude instead.

     $Location (STRING type)
	    This is a string specifying the name of your location.  It	is  usu-
	    ally  the  name of your town or city.  It can be set to whatever 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; eastern 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 reasons, the sign for longi-
	    tude is different from the usual convention!  If you find the longi-
	    tude 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 deprecated; you should use $Longitude instead.
	    Note also that $Longitude uses the standard convention  of	negative
	    for western longitudes and positive for eastern ones.

	    The latitude and longitude information is required for the functions
	    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 $Latitude, $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  sus-
	    pended  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 trigger 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 trigger 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  (described
	    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 create.
	    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  recommend	 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  local
	    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 yourself.  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 constant.)

     $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 us-
	    ing  the file access date to determine whether or not to run a ONCE-
	    type reminder, Remind will maintain a timestamp in the  file  $Once-
	    File.   This  is more reliable than using the access date of the re-
	    minder 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 cur-
	    rent user.	If you try to set $OnceFile after a  ONCE  reminder  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 triggered.  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.

     $Repeat (read-only)
	    If this variable holds a non-zero value n, then a command-line argu-
	    ment of *n was supplied to specify repeated runs of Remind..

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

     $Shaded (read-only)
	    Returns the number of times a SHADE special reminder has  triggered.
	    This  variable  is	set only in calendar mode, not agenda mode.  You
	    can use this variable to avoid shading a calendar day that	has  al-
	    ready 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 ex-
	    plicitly shaded, you don't want  to  overwrite  that  shading.   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 op-
	    tions was supplied.

     $SortByDate (read-only)
	    Set to 0 if no -g option is used, 1 if sorting by date in  ascending
	    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 as-
	    cending order, or 2 if sorting by priority in descending order.

     $SortByTime (read-only)
	    Set to 0 if no -g option is used, 1 if sorting by time in  ascending
	    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  unknown
	    token  and is treated as a REM command, or if a REM command is miss-
	    ing a type and is treated as a MSG-type reminder.  Setting $Suppres-
	    sImplicitWarnings 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 locale,
	    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.   Currently,
	    Remind  ships  with  some standard holiday files and language packs.
	    The value of $SysInclude is "/usr/local/share/remind"  on  this  in-
	    stallation.

     $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 character
	    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 library  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 determined,
	    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 specified 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  an-
	    chors around text (see https://gist.github.com/egmontkob/eb114294ef-
	    bcd5adb1944c9f3cb5feda),  then  you can set this variable to 1.  Re-
	    mind 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 $Warn-
	    ingLevel 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  $Warn-
	    ingLevel, 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 $Dae-
     mon,   $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 modifi-
     able  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-separated
     list of arguments in parentheses.	Function names are  not  case-sensitive.
     If  a function takes no arguments, it must be followed by "()" in the func-
     tion 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"  denote  INT,
     STRING,  DATE,  TIME  and DATETIME arguments, respectively.  If an argument
     can be one of several types, the characters are concatenated.  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 in-
	    formation.

	    In the body of a reminder, the substitution sequence %(text) is (al-
	    most) the equivalent of [_("text")].  Therefore, the  following  re-
	    minders 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  fil-
	    ter  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 specified mode, and -1 other-
	    wise.

     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 sup-
	    plied, 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 ei-
	    ther  a  TIME or a DATETIME object) to "AM/PM" format.  The optional
	    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 in-
	    tegers from 0 to 255 specifying the value of  the  respective  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 Re-
	    mind is running in, as specified by the -@ option.	If color mode is
	    not enabled, then ansicolor always returns the empty string.  Other-
	    wise, it returns the escape  sequence  that  best  approximates  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  default),
	    then colors are not adjusted based on the terminal background 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  at-
	    tributes to normal.

	    Note  that inserting ANSI color sequences in calendar mode will pro-
	    duce garbled results.  Therefore, we  recommend  defining  functions
	    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 reminders will
	    continue to be colored.

     args(s_fname)
	    Returns  the  number of arguments expected by the user-defined func-
	    tion 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 partic-
	    ular user-defined function has been defined previously.  The  args()
	    function  is  available only in versions of Remind 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, evaluates and  re-
	    turns  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  re-
	    cently-evaluated  catch()  function  whose first argument yielded an
	    error.  Note that the error message is always in English even if Re-
	    mind 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 arguments.  Any
	    codepoint may be supplied and a correct multi-byte character  string
	    will  be returned.	Note that none of the arguments 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  returned.
	    If index is less than 1, then arg1 is returned.  If index 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  evalu-
	    ated.  Any non-chosen arguments will not be evaluated.

     coerce(s_type, x_arg)
	    This function converts arg to the specified type, if such conversion
	    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 unchanged.

	    If type is "STRING", then arg is converted to a string consisting 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 component.  A  DATE  arg
	    cannot be converted to a time.

	    If	type is "DATETIME", then an INT arg is converted by interpreting
	    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 con-
	    verted 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 obtain the  terminal  size.
	    If this fails, returns -1.

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

	    The result of columns(str) may be less than, equal	to,  or  greater
	    than  the  result  of  mbstrlen(str).   This is because some Unicode
	    characters are so-called combining characters that add  one  to  the
	    character  length,	but  don't occupy any columns on their own.  And
	    other Unicode characters are double-width characters that add one to
	    the character length, but two to the number 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 result 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 arguments.

	    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 sec-
	    ond and third must be INTs.  The second and third arguments are  in-
	    terpreted 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.	(Actually, 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 supplied,
	    only the date component is used.

     day(dq_date)
	    This function takes a DATE or DATETIME as an argument,  and  returns
	    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 ar-
	    gument, returns the number of days in the month containing the argu-
	    ment.

     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 vari-
	    able 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 sub-
	    stitution 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 produce undefined
	    results.

	    Dosubst()  is  only  available starting from version 03.00.04 of Re-
	    mind.

     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 component of a
	    datetime  is  ignored.)   If arg is omitted, then it defaults to to-
	    day().

	    Note that easterdate computes the Western Easter.  For the	Orthodox
	    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 "\" fol-
	    lowed  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  double-
	    quotes.

     eval(s_arg)
	    Parses  the  string arg as an expression and evaluates it, returning
	    the result.  Note that any variable names in the  parsed  expression
	    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 specifica-
	    tion 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 Oc-
	    tober 2008 that satisfies "Mon 1".

	    If	you want to see how many days it is from the first Monday in Oc-
	    tober, 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 ex-
	    ist,  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 guar-
	    anteed to be correct for use in an INCLUDE command as follows:

	       INCLUDE [filedir()]/stuff

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

	    Note  that	if the currently-processing reminders file was specified
	    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 symbolic links to files un-
	    less both the symbolic link and its target 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 representing
	    the  value of the specified environment variable.  Returns "" if the
	    environment variable is not defined.  Note that the names  of  envi-
	    ronment 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  strip-
	    ping 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, re-
	    turns arg2, and so on.  If all of the test arguments are false,  re-
	    turns  default.   Note that only those arguments needed to determine
	    the final result are evaluated.  This function accepts an odd number
	    of arguments - note that prior to version 03.00.05 of Remind, it ac-
	    cepted 3 arguments only.  The 3-argument version of iif() is compat-
	    ible 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 positions, 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  charac-
	    ter index rather than a byte index.

     isany(arg1 [,arg2, ..., argN]);
	    Returns  1	if the first argument arg1 is equal to any of the subse-
	    quent arguments arg2 through argN; returns 0  otherwise.   Also  re-
	    turns 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  context,  isconst  will
	    still  return  1.	For details about constant vs.	non-constant ex-
	    pressions, see the section "NON-CONSTANT EXPRESSIONS"

     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 de-
	    faults to midnight.

	    Note that this function is only as reliable as the	C  run-time  li-
	    brary  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 supplied,
	    then the year component is used in the test.

     isomitted(dq_date)
	    Returns 1 if date is omitted, given the current global OMIT context.
	    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 Re-
	    mind.  Remind used to support compiled-in  support	for  other  lan-
	    guages, but now all localization is done at run-time.  As such, this
	    function   always	returns   "English".   However,  the  expression
	    _("LANGID") returns the two-character ISO 639 language code  of  any
	    language pack in effect, assuming the language pack author has writ-
	    ten the localization correctly!

     localtoutc(q_datetime)
	    Given a DATETIME object interpreted in the local time zone, return 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 converted
	    to lower-case.  This function works correctly on any Unicode string.

     max(x_arg1 [,x_arg2...)
	    Can take any number of arguments, and returns the maximum.	The  ar-
	    guments  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  ar-
	    guments  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  (for-
	    merly  GMT)  to local time on the specified date and time.	Date de-
	    faults to today() and time defaults to midnight.  If local	time  is
	    before  UTC, the result is negative.  Otherwise, the result is posi-
	    tive.

	    Note that this function is only as reliable as the	C  run-time  li-
	    brary  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, returns 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 abbreviation of
	    a  month  name) then the corresponding month number is returned.  If
	    str is not a valid month name, then an error occurs.

     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 defaults  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 defaults to today().  If
	    time is omitted, it defaults to midnight.  Moontime() is intended to
	    be used in conjunction with moondate().  The  moondate()  and  moon-
	    time()  functions  are accurate to within a couple of minutes of the
	    times in "Old Farmer's Almanac" 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_date-
     time)
	    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 returned 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 argu-
	    ment.  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  midnight  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 DATETIME of
	    the next moonset on or after midnight on date.

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

     multitrig(s_trig1 [,s_trig2, [... s_trigN]])
	    multitrig evaluates each string as a trigger, similar  to  evaltrig,
	    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  to-
	    day, regardless of whether it would have triggered today.

	    If	no trigger can be computed that is later than today(), then mul-
	    titrig 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  re-
	    minder 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 multi-
	    trig 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  effectively
	    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  addi-
	    tional arguments that are names of weekdays to be omitted.	However,
	    in	a  REM	command, any local OMITFUNC clause is not taken into ac-
	    count 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 count-
	    ing 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 inconsistent
	    results.

	    Here is a more complex use for nonomitted.	 My  garbage  collection
	    follows two interleaved 14-day cycles: One Friday, garbage and paper
	    recycling ("Black Box") are collected.  The next Friday, garbage and
	    plastic recycling ("Blue Box") are collected.  If any of Monday-Fri-
	    day  is a holiday, collection is delayed until 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  returns
	    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 including the Friday.

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

     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 callback to ordx,
	    RUN will be disabled.

     orthodoxeaster([dqi_arg])
	    If arg is an INT, then returns the date of	Orthodox  Easter  Sunday
	    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 necessary.  By de-
	    fault, 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 specified
	    in characters rather than bytes.  Use mbpad rather than pad  if  ei-
	    ther 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 supplied,
	    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 quar-
	    ter), 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 display.
	    The font is the same font used for calendar entries.  If notesize is
	    given,  it	specifies  the	font  size to use for the annotation, in
	    PostScript units (1/72 inch.)  If notesize is not given, it defaults
	    to the size used for calendar entries.  (If you  annotate  the  dis-
	    play,  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 commands
	    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 provided by
	    the  operating  system.  This is in contrast to current(), which may
	    return a time supplied on the command line.

     realnow()
	    Returns the true time of day as provided by  the  operating  system.
	    This  is  in  contrast to now(), which may return a time supplied 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 supplied  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 obtain the
	    terminal size.  If this fails, returns -1.

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

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

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

	    If maxlen is specified, then shell() returns the first maxlen  char-
	    acters  of	output (rather than the first 511).  If maxlen is speci-
	    fied as a negative number, then it defaults to the value of the sys-
	    tem variable $MaxStringLen.

     shellescape(s_str)
	    Returns str with all shell metacharacters such as " ", "*", etc  es-
	    caped 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 for-
	    ward by 5 days, not including Thursday, May 14 or Saturday and  Sun-
	    day, 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 pa-
	    rameter ranges from 0 to 3, and specifies which event we are  inter-
	    ested  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  DATETIME  ob-
	    ject;  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 supplied, 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  go-
	    ing.  The return values are one of the following: "TTY" if standard-
	    output  is	a terminal, "BLOCKDEV" if it is a block device (very un-
	    likely), "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 out-
	    put 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" error.
	    Note that strlen returns the number of bytes in the string, not  the
	    number of characters.  These numbers are the same for ASCII strings,
	    but may be different for UTF-8 strings.

     mbstrlen(str)
	    Similar  to  strlen, but returns the length of the string in charac-
	    ters 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 in-
	    dexes 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  in-
	    dexes, 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 sunrise 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 sunset  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 cur-
	    rent().  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 system
	    date, or a date supplied on the command line, or (in Calendar  Mode)
	    the date of the calendar entry currently being computed.

     trig(s_1 [,s_2, ...])
	    For each string argument s_n, trig evaluates s_n as if it were a REM
	    or	IFTRIG	trigger specification.	If the trigger would trigger to-
	    day, 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	function
	    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,  some-
	    thing like:

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

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

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

		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 be-
	    comes:

		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 com-
	    mand.  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 com-
	    putable 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,  returns
	    the integer 0.  See "MULTI-DAY EVENTS" for more information.

     trigeventstart()
	    Returns  a	DATETIME representing the start of the most recent trig-
	    gerable REM command that had an AT clause.	For events without a DU-
	    RATION or that do not span multiple days, returns the same as  trig-
	    datetime().   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 trigger-
	    able REM command that had an AT and a DURATION clause.  If the event
	    does  not  span  multiple  days, returns the same thing as trigdura-
	    tion().  If the REM command lacked an AT or DURATION clause, returns
	    -1.  See "MULTI-DAY EVENTS" for more information.

     trigback()
	    Returns the "back" amount of the last REM or  IFTRIG  command.   Re-
	    turns  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 components.  If the
	    trigger  specification  lacks one of those components, then 0 is re-
	    turned.

	    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.  Re-
	    turns 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.  Re-
	    turns 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,  returns
	    the time zone name.  Otherwise returns the empty string.

     trigduration()
	    Returns (as a TIME type) the DURATION parameter of a timed reminder.
	    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 inte-
	    ger -1.  If there is a THROUGH parameter, that will be  returned  by
	    triguntil() since "THROUGH yyyy-mm-dd" is simply syntactic 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 in-
	    teger -1.  Note that FROM and SCANFROM interact; a reminder that has
	    a "FROM yyyy-mm-dd" parameter will act as if it has a SCANFROM para-
	    meter 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 integer
	    -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 compar-
	    isons 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 advance.
	    Note that in earlier versions of Remind,  trigger  was  required  to
	    convert  a	date into something the REM command could consume.  How-
	    ever, in this version of Remind, you can  omit  it.   Normally,  the
	    date  and  time  are the local date and time; however, if utcflag is
	    non-zero, the date and time are interpreted as UTC	times,	and  are
	    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 problem.

     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 sepa-
	    rated 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 speci-
	    fied 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 de-
	    fault 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,  Remind
	    will  warn	you  if you use an invalid time zone name for srczone 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 converted
	    to upper-case.  This function works correctly on any Unicode 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 defined.
	    If XY is not defined, an error results.

	    However, if you supply a second argument, it is returned if the var-
	    name is not defined.  The expression value("XY", 0) will return 0 if
	    XY is not defined, and the value of XY if it is defined.  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.07, returns "06.02.07".  It is guaranteed that as new versions
	    of	Remind	are  released,	the  value  returned  by  version() will
	    strictly increase, according to the rules for string ordering.

     weekno([dq_date, [i_wkstart, [i_daystart]]])
	    Returns the week number of the year.  If no arguments are  supplied,
	    returns  the ISO 8601 week number for today().  If one argument 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 wkstart 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, returns  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  Saturday.)
	    If	a  STRING  is  supplied, then if str is a valid weekday name (or
	    minimum 3-character abbreviation  thereof)	then  the  corresponding
	    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 in-
     terim  (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; Remind
     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 system, 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 remain-
     ing 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 implementation 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 "ex-
     pression 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 command-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" ex-
     pression, 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  re-
     cursively.  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	example,
	    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 de-
	    termine the first token of a line for the flow-control commands  (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 com-
	    mands 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  re-
     sult 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.  Normally,
     reminder scripts are processed sequentially.  However, IF and related  com-
     mands  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 por-
     tion 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-commands are
     executed.	If expr evaluates to zero or null, then the f-commands	(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  corresponding
     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  trig-
     ger 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  naming
     variables.  Args is a comma-separated list of arguments, and expr is an ex-
     pression.	 expr  is not evaluated at the time the function is defined; in-
     stead, it is evaluated each time the  function  is  called.   Args  can  be
     empty,  in which case you define a function taking no parameters.	Here are
     some examples:

	  FSET double(x) 2*x
	  FSET yeardiff(date1, date2) year(date1) - year(date2)
	  FSET since(x) ord($Ty - x)

     The last function is useful in birthday reminders.  For example:

	  REM 1 Nov +12 MSG Dean's [since(1984)] birthday is %b.

     Dean was born in 1984.  The above example, on 1 November 1992, would print:

	  Dean's 8th birthday is today.

     Similarly, the function is useful in anniversary reminders.  For example:

	     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  argu-
	    ments, 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 variable,
	    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 func-
	    tion that breaks the recursion) or an error will result after a cer-
	    tain maximum number of recursive calls (by default, 1000.)

     o	    If a user-defined function has the same name as a built-in function,
	    it is ignored and the built-in function is used.   To  prevent  con-
	    flicts  with future versions of Remind (which may define more built-
	    in functions), you may wish to name all user-defined  functions  be-
	    ginning with an underscore.

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

     To delete a user-defined function, use FUNSET.  This  takes  a  space-sepa-
     rated  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, otherfunc or
     thirdfunc will exist.  Remind does not issue an error if you try to  FUNSET
     a nonexistent user-defined function; it simply does nothing 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.  How-
     ever,  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 func-
     tion, the command fails with an error message and does nothing.

     If you define a user-defined function and then later on redefine it, Remind
     will issue a warning.  If you do not want this warning, then use FUNSET  to
     remove  the existing definition before you redefine the function.	Alterna-
     tively, you can use a "-" token before the function name to suppress "rede-
     fined 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 in-
     ternal 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  func-
     tion defined above.  After the POP-FUNCS msgprefix would be restored 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 functions
     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 successively 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 be-
	    fore 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  Re-
	    mind  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 re-
	    minder on its trigger date.

     3	    Warn_function should (as a matter of good style) return 0 as the fi-
	    nal value in its sequence of return  values.   However,  a	reminder
	    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 sched-
     uling of timed reminders.	It should be followed by the name of a	user-de-
     fined  function,  sched_function.	 Note  that  if  you use SCHED, then any
     tdelta and trep are ignored.

     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, Re-
     mind calls the scheduling function to determine when  to  trigger	the  re-
     minder.   The first time the reminder is queued, the scheduling function is
     called with an argument of 1.  Each time the reminder is triggered,  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 trigger 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.  Finally, 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 Remind
	    reverts to using the AT time and the delta and  repeat  values,  and
	    never calls sched_func again.

     2	    If processing sched_func yields a time earlier than the current sys-
	    tem  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 reminder
	    even after the AT-time.  Also, it is quite possible to not trigger a
	    reminder on the AT time when you use a  scheduling	function.   How-
	    ever,  if  your scheduling function is terminated (for reasons 1 and
	    2) before the AT time of the reminder, it will be triggered  at  the
	    AT time, because normal processing takes over.

     4	    Your  scheduling functions should (as a matter of good style) return
	    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 calculated 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 com-
     mand-line option is reached.

     If expr is not satisfied, then trigvalid() is set to 0 and the  error  mes-
     sage  "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 re-
     lated functions or system variables; otherwise, expr will not change as Re-
     mind iterates.  In fact, if expr is not a constant and does not call  trig-
     date()  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 af-
     ter the 13th of each month.  The way to do it is with  a  more  complicated
     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 calculated 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  sepa-
     rate 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 fu-
     ture.  This could cause strange results, as the OMIT context can change de-
     pending on the current date.  For example, if you use the following 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 Tuesday,  8  Septem-
     ber,  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  unless
     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 trig-
     ger, 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 occur-
     ring 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 condi-
     tion,  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 provided
     for those rare occasions when it makes  sense.   If  you  use  MAYBE-UNCOM-
     PUTABLE  inside the evaltrig() function, then untriggerable triggers 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  often
     overkill.	 For  example, if you turn on the -dx option for a reminder file
     with many complex expressions, you'll get a huge amount of output.  The DE-
     BUG command allows you to control the debugging flags  under  program  con-
     trol.  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  op-
     tions  section.   If preceded with a "+", the corresponding group of debug-
     ging options is switched on.  Otherwise, they are switched off.  For  exam-
     ple, you could use this sequence to debug a complicated expression:

	  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 for-
     mat is:

     DUMPVARS [-c] [var...]

     If you supply a space-separated list of variable names,  the  corresponding
     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 dollar 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  trig-
     ger date of today()) and printed to the error output stream.  Example:

	  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 reminders  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 returned
     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  Re-
     mind.  This is not terribly useful to most people, but may be useful 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 array of
     zero or more objects.  There are three possible types of objects in the ar-
     ray:

     banner
	    The banner object, if present, will be the first object in	the  ar-
	    ray.  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 ob-
	    jects  that  contain  all of the keys described in the rem2ps(1) man
	    page  section  "CALENDAR  ENTRIES".   However,  the   calendar_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 re-
     minders  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 repeatedly,
     performing one iteration through the whole file for each day in the  calen-
     dar.   Reminders  that  trigger are saved in internal buffers, and then in-
     serted into the calendar in the appropriate places.

     If you also supply the -a option, then Remind will not  include  timed  re-
     minders 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 %"...%" se-
     quence, only that portion is inserted.  For example, consider  the  follow-
     ing:

	  REM 6 Jan MSG %"Dianne's birthday%" is %b

     In  agenda mode, Remind would print "Dianne's birthday is today" on 6 Janu-
     ary.  However, in the calendar mode, only the text "Dianne's  birthday"  is
     inserted into the box for 6 January.

     If you explicitly use the %"...%" sequence in a RUN-type reminder, then the
     text  between the delimiters is inserted into the calendar.  If you use the
     sequence %"%" in a MSG or CAL-type reminder, then no calendar entry is pro-
     duced for that reminder.

     PRESERVING VARIABLES

     Because Remind iterates through the script for each day  in  the  calendar,
     slow operations may severely reduce the speed of producing a calendar.

     For example, suppose you set the variables "me" and "hostname" as follows:

	  SET me shell("whoami")
	  SET hostname shell("hostname")

     Normally,	Remind	clears all variables between iterations in calendar mode
     and between iterations if a '*N' parameter was  supplied  on  the	command-
     line.   However,  if  certain  variables  are slow to compute, and will not
     change between iterations, you can "preserve" their values  with  the  PRE-
     SERVE  command.  Also, since function definitions are preserved between it-
     erations, 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 iterations.  On the  next  itera-
     tion,  the  commands  are	skipped, since initialized 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 automatically
     preserved between calendar iterations.

     Note that for efficiency, Remind caches the reminder script  (and	any  IN-
     CLUDEd 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  command-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 calendar
     mode.  It repeatedly executes the	reminder  script,  incrementing  today()
     with  each  iteration.  The same rules about preserving variables and func-
     tion definitions apply.  Note that using repeat on the  command  line  also
     enables  the  -q  option and disables any -z option.  As an example, 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  interpret-
     ing  special  characters  in  expr.  You can have as many -i options as you
     want on the command line, and they are processed  in  order.   Thus,  if  a
     variable  is  defined in one -i option, it can be referred 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  PRE-
     SERVE 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  directly  to  the
     PostScript  output  (after processing by the substitution filter) while the
     PSFILE-type's body should simply consist of a filename.  The Rem2PS program
     will open the file named in the PSFILE-type reminder, and include its  con-
     tents 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 calendars.
     For example, PostScript code to shade a calendar box will	obliterate  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 PSFILE-type reminders
     with priorities; instead, you should ensure that they  appear  in	the  re-
     minder  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 order for priorities,  the  PostScript
     output will not work.

     All  of the PostScript code for a particular date is enclosed in a save-re-
     store pair.  However, if several PostScript-type  reminders  are  triggered
     for  a single day, each section of PostScript is not enclosed in a save-re-
     store 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 back-
     grounds for particular days.

     Before executing your PostScript code, the origin of the PostScript coordi-
     nate  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  sup-
     ply.   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 He-
	    brew 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  invalid
     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  modification
     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  reminder  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  ensure
     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 ed-
     its 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.  How-
     ever, if you supply a numeric argument after -j, then  Remind  will  create
     .purged  files for the specified level of INCLUDE.  For example, if you in-
     voke 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.	However,  .purged  files
     will not be created for third-or-higher level INCLUDE 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 ex-
     pired,  you  may see the following comments inserted before the problematic
     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.  In-
     stead, the only change it makes to the .purged file is to mark expired  re-
     minders with "#!P: Expired".

NON-CONSTANT EXPRESSIONS
     In Purge Mode, Remind will not mark a REM statement as expired if its trig-
     ger  specification  contains a non-constant expression.  A non-constant ex-
     pression is defined as one whose value might differ from run to  run,  usu-
     ally  because  it	depends  on  the current date, but also if it depends on
     something from the environment (such as the output  of  the  shell()  func-
     tion.)

     The  use of any of the following in an expression causes Remind to consider
     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	example,
		   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.  Addi-
     tionally, 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-constant.

     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 be-
     cause the code flow depends on today's date, which could change  in  subse-
     quent  Remind  runs.  If you want to force a variable to be treated as con-
     stant, no matter what, then use the following just before you use the vari-
     able:

	     SET var const(var)

     Variables initialized on the command-line with the -i flag are always  con-
     sidered 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 de-
     cides 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 ex-
     pression to be non-constant, it's best to use DEBUG +n before 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 issued im-
     mediately,  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 (ascend-
     ing 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 af-
     ter timed reminders.

     In ascending order, reminders are issued with the most imminent first.  De-
     scending order is the reverse.  Reminders	are  always  sorted  by  trigger
     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 trigger
     date from the previous one (or if it is the first one to be  issued),  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 displayed.

     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 following
     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  SORT-
     BANNER  has  been	defined.  (This could be used, for example, to provide 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  msgsuf-
     fix().  They should each accept one argument, a number from 0 to 9999.

     In agenda mode, for MSG- and MSF-type reminders, the following sequence oc-
     curs 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 reminders 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 possi-
     bly 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 backspace.  This
     places the suffix before rather than after the carriage return.  (The back-
     space 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 sortbanner(),
     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 support
     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 cor-
	    responding day's name in your language.  Strings must be valid UTF-8
	    strings.

     $January, $February, $March, $April, $May, $June, $July, $August, $Septem-
     ber, $October, $November, $December
	    Set each of these system variables to a string representing the cor-
	    responding	month's  name  in  your language.  Strings must be valid
	    UTF-8 strings.

     $Ago, $Am, $And, $At, $Hour, $Is, $Minute, $Now, $On, $Pm, $Today, $Tomor-
     row, $Was
	    Set each of these system variables to the translation of the  corre-
	    sponding  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 unpredictable.

     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  typically
     sufficient to properly translate Remind's output to another language.  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 English, 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 num-
	    ber.  This function completely overrides the  substitution	sequence
	    "%N".   The  three	arguments are an integer alt which, if non-zero,
	    indicates that the alternate-mode substitution  sequence  "%*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 "to-
	    day" 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  after
     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  sub-
     stitution---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 integer
     zero, then the normal substitution mechanism is used.  Therefore, the  pre-
     vious 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 fol-
     lows:

	    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 function with alt set to  0  and
     date  and time to the trigger date and time, respectively.  The %{name} se-
     quence is replaced  with  whatever  the  function	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 defined or
     returns an error, then %{name} is replaced with the empty string.

     Note  that when Remind invokes any callback function for a substitution se-
     quence, 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 contain 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 function,
     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 entries.

     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  translations,
     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  TRANSLATE
     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  corresponding
     translation  table entry automatically.  This is done for all of the trans-
     lation-related system variables except for $Hplu and $Mplu.

     The converse applies too; creating a translation table for "December" auto-
     matically sets $December.	And if you  invoke  TRANSLATE  CLEAR,  then  all
     translation-related  system  variables  are  set to their default values as
     well.

     The translation table always contains a special entry LANGID whose  default
     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 let-
		   ter 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  (Norwegian),  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 Re-
     mind into additional languages.

THE HEBREW CALENDAR
     Remind has support for the Hebrew calendar, which is a luni-solar calendar.
     This allows you to create reminders for  Jewish  holidays,  jahrzeits  (an-
     niversaries 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:

     xax(C)x"x,  xx(C)xxx,  xx!xx,  xxxa,  x(C)xx,  xxx",  x xx!x, xxxx", x!xxx,
     xaxxx, xx, xxxx.

     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  He-
     brew, 'xxx" x and 'xxx" x.

     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, xxx" x or xxx" 1.

     Adar B
	    Can also be spelled Adar 2, Adar II, xxx" x or xxx" 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 Hesh-
     van.  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 midnight, 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 para-
	    meter.  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 ex-
	    ample, 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') re-
	    turns "x xx!x".

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

	    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 exam-
	    ple:

		      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 be-
	    haviour  is  appropriate for Purim Katan, which only appears 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	section,
	    "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 burial is de-
     layed - 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  after
	    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 observed 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 behav-
     iour 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 Com-
     prehensive Hebrew Calendar" by Arthur Spier, and "Calendrical Calculations"
     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 supplied.)

     The various SPECIALs recognized are particular for each  backend;	however,
     there  are four SPECIALs that all backends should attempt to support.  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 in-
     terpreted as RGB components from minimum (0) to maximum (255).  The example
     above shades weekends a fairly dark grey and makes  Mondays  a  fully-satu-
     rated  red.   (These shadings appear in calendars produced by Rem2PS, tkre-
     mind 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 omit-
     ted 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  invoke
     Remind  with  -@[n],  then  it approximates SPECIAL COLOR reminders on your
     terminal.

     See also the documentation of the $DefaultColor system variable in the sec-
     tion "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  Re-
     mind 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 election.
     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 Novem-
     ber.)  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  results  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 expression
     with trigdate() set to the date found above.  If the  expression  evaluates
     to  zero  or  the	null string, Remind continues the scanning procedure de-
     scribed 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 procedure
     at scan_date, which is the date specified in the SCANFROM clause.	For  ex-
     ample:

	  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 be-
     fore 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 al-
     lows 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 previ-
     ous 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  pre-
     vents  the reminder from triggering before the FROM date.	For example, 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 exactly 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,  perform
     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 mecha-
     nism.  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 Re-
     mind  finds a date not before the starting date of the scanning that satis-
     fies the trigger.	In addition, there is one special case	in  which  trig-
     valid() 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 lan-
     guages and their translators are listed below.  Languages marked "complete"
     support  error  messages in that language; all others only support the sub-
     stitution 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 DavAdhsson

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  implemented
     as functions, or why functions like version(), etc.  are not implemented 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", Soft-
     ware-Practice and Experience, Vol. 20(9), Sept. 1990, pp 899-928.

     L.  E.  Doggett,  Almanac for computers for the year 1978, Nautical Almanac
     Office, USNO.

     Richard Siegel and Michael and Sharon Strassfeld, The First Jewish Catalog,
     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-06-05			       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