xenial (7) yodlbuiltins.7.gz

Provided by: yodl_3.06.00-1_amd64 bug

NAME

       yodlbuiltins - Builtins for the Yodl converters

SYNOPSIS

       This manual page lists the standard builtins of the Yodl package.

DESCRIPTION

       The following list shows the builtins defined by the Yodl converters define and which can be used in Yodl
       documents. Refer to the Yodl user guide, distributed with the Yodl package, for a full description.

       The following list shows all builtins of the package in alphabetical order.

       NOTE: Starting with Yodl version 3.00.0 Yodl’s default file inclusion behavior has changed.  The  current
       working  directory  no  longer  remains  fixed at the directory in which Yodl is called, but is volatile,
       changing to the directory in which a yodl-file is located.  This  has  the  advantage  that  Yodl’s  file
       inclusion  behavior  now matches the way C’s #include directive operates; it has the disadvantage that it
       may break some current documents. Conversion, however is simple but can be avoided altogether  if  Yodl’s
       -L  (--legacy-include)  option is used. The builtins INCLUDEFILE, NOEXPANDINCLUDE and NOEXPANDPATHINCLUDE
       are affected by this new behavior.

       Yodl’s builtin commands
              As mentioned previously, YODL’s input consists of text and of commands.  YODL supports a number of
              built-in  commands  which  may either be used in a YODL document, or which can be used to create a
              macro package.

              Don’t despair if you find that the description of this section is too technical. Exactly for  this
              reason,  YODL supports the macro packages to make the life of a documentation writer easier. E.g.,
              see chapter [MACROPACKAGE] that describes a macro package for YODL.

              Most built-in functions and macros expand the information they receive the way  they  receive  the
              information.  I.e., the information itself is only evaluated by the time it is eventually inserted
              into an output medium (usually a file).  However,  some  builtin  functions  will  evaluate  their
              argument(s) once the argument is processed. They are:

       o      The ERROR() built-in function (see section [ERROR]);

       o      The EVAL() built-in function (see section [EVAL]);

       o      The FPUTS() built-in function (see section [FPUTS]);

       o      The INTERNALINDEX() built-in function (see section [INTERNALINDEX]);

       o      The TYPEOUT() built-in function (see section [TYPEOUT]);

       o      The UPPERCASE() built-in function (see section [UPPERCASE]);

       o      The  WARNING()  built-in  function  (see section [WARNING]); All other built-in functions will not
              evaluate their arguments.  See the mentioned functions for details, and in particular EVAL() for a
              description of this evaluation process.

       ADDTOCOUNTER
              The  ADDTOCOUNTER  function  adds  a given value to a counter. It expects two parameter lists: the
              counter name, and the value to add. The counter must be previously created with DEFINECOUNTER.

              The value to add can be negative; in that case, a value is of course subtracted from the counter.

              See further section [COUNTERS].

       ADDTOSYMBOL
              Since Yodl version 2.00 symbols can be manipulated. To add text to an existing symbol the  builtin
              ADDTOSYMBOL  is  available. It expects two parameter lists: the symbol’s name, and the text to add
              to the symbol.  The symbol must  have  been  created  earlier  using  DEFINECOUNTER  (see  section
              [DEFINECOUNTER]).  The  macro’s  second  argument is not evaluated while ADDTOSYMBOL is processed.
              Therefore, it is easy to add the text of another symbol or the expansion of a macro  to  a  symbol
              value. E.g.,

                  ADDTOSYMBOL(one)(SYMBOLVALUE(two)XXnl())

              This  will  add the text of symbol two, followed by a new line, to the contents of symbol one only
              when symbol one is evaluated, not when ADDTOSYMBOL is evaluated.

              Example:

                  ADDTOSYMBOL(LOCATION)(this is appended to LOCATION)

       ATEXIT ATEXIT takes one parameter list as argument. The text of the parameter list  is  appended  to  the
              output file. Note that this text is subject to character table translations etc..

              An  example  using  this  function  is the following. A document in the LaTeX typesetting language
              requires \end{document} to occur at the end of the document. To automatically append  this  string
              to the output file, the following specification can be used:

                  ATEXIT(NOEXPAND(\end{document}))

              Several  ATEXIT lists can be defined. They are appended to the output file in the reverse order of
              specification; i.e., the first ATEXIT list is appended to the output file last. That means that in
              general  the  ATEXIT  text  should  be specified when a `matching’ starting command is sent to the
              output file; as in:

                  COMMENT(Start the LaTeX document.)
                  NOEXPAND(\begin{document})

                  COMMENT(Ensure its proper ending.)
                  ATEXIT(NOEXPAND(\end{document}))

       CHAR   The command CHAR takes one argument, a number or a character, and outputs its corresponding  ASCII
              character  to  the final output file.  This command is built for `emergency situations’, where you
              need to typeset a character despite the fact that it may be redefined  in  the  current  character
              table  (for  a  discussion  of character tables, see [CHARTABLES]). Also, the CHAR function can be
              used to circumvent Yodl’s way of matching parentheses in a parameter list.

              The following arguments may be specified with CHAR (attempted in this order):

       o      A decimal number indicating the number of the character in the ascii-table (for example CHAR(41));

       o      A plain, single character  (for example CHAR(#)).

              So, when you’re sure that you want to send a printable character that is not a closing parenthesis
              to the output file, you can use the form CHAR(c), c being the character (as in, CHAR(;)).  To send
              a non-printable character or a closing parenthesis to the output file, look up the ASCII number of
              the character, and supply that number as argument to the CHAR command.

              Example: The following two statements send an A to the output file.

                  CHAR(65)
                  CHAR(A)

              The following statement sends a closing parenthesis:

                  CHAR(41)

              Another  way to send a string to the output file without expansion by character tables or by macro
              interpretation, is by using the function NOTRANS (see section [NOTRANS]). If you want  to  send  a
              string  to  the  output  without  macro  interpretation, but with character table translation, use
              NOEXPAND (see section [NOEXPAND]).

       CHDIR  The command CHDIR takes one argument, a directory to change to. This  command  is  implemented  to
              simplify  the  working  with  includefile (see includefile in yodlmacros(7)).  As a demonstration,
              consider the following fragment:

                  includefile(subdir/onefile)
                  includefile(subdir/anotherfile)
                  includefile(subdir/yetanotherfile)

              This fragment can be changed to:

                  CHDIR(subdir)
                  includefile(onefile)
                  includefile(anotherfile)
                  includefile(yetanotherfile)
                  CHDIR(..)

              The current directory, as given to CHDIR, only affects how includefile will search for its files.

              Note that this example  assumes  that  the  current  working  directory  is  a  member  of  Yodl’s
              include-path specification (cf., Yodl’s --include option).

       COMMENT
              The  COMMENT  function takes one parameter list. The text in the list is treated as comment. I.e.,
              it is ignored. The text is not copied to the final output file.

       COUNTERVALUE
              COUNTERVALUE expands to the value of a counter. Its single parameter list must contain the name of
              a counter.  The counter must have been created earlier using the builtin DEFINECOUNTER.
              Example:

                  The counter has value COUNTERVALUE(MYCOUNTER).

              See also section [COUNTERS].

       DECWSLEVEL
              DECWSLEVEL  requires  one  (empty)  parameter list.  It reduces the current white-space level. The
              white-space level typically is used in files that only define Yodl macros. When no  output  should
              be generated while processing these files, the white-space level can be used to check for this. If
              the  white-space  level  exceeds  zero,  a  warning  will  be  generated  if  the  file   produces
              non-whitespace  output.  The  builtin  function  DECWSLEVEL is used to reduce the whitespace level
              following a previous call of INCWSLEVEL.

              Once the white space level exceeds zero, no output will be generated. White space, therefore  will
              effectively  be  ignored. The white space level cannot be reduced to negative values. A warning is
              issued if that would have happened if it were allowed.

              Example:

                  INCWSLEVEL()
                  DEFINESYMBOL(....)
                  DEFINEMACRO(...)(...)(...)
                  DECWSLEVEL()

              Without the INCWSLEVEL and DECWSLEVEL, calls, the above definition would generate four empty lines
              to the output stream.

              The  INCWSLEVEL  and  DECWSLEVEL calls may be nested. The best approach is to put an INCWSLEVEL at
              the first line of a macro-defining Yodl-file, and a matching DECWSLEVEL  call  at  the  very  last
              line.

       DEFINECHARTABLE
              DEFINECHARTABLE  is  used  to  define  a  character  translation  table.  The function expects two
              parameterlists, containing the name of the character table and  character  table  translations  on
              separate lines. These character table  translations are of the form

                  character = quoted-string

              Here,  character  is  always  a value within single quotes. It may be a single character, an octal
              character value or a hexadecimal character value. The  single  character  may  be  prefixed  by  a
              \-character (e.g., ’\\’). The octal character value must start with a backslash, followed by three
              octal digits (e.g., ’\045’. The hexadecimal character  value  starts  with  0x,  followed  by  two
              hexadecimal  characters.  E.g.,  ’0xbe’.  The  double  quoted string may contain anything (but the
              string must be on one line), possibly containing escape-sequences as well: in  the  double  quoted
              string  the  standard  C  escape  sequences \a (alert), \b (beep), \f (formfeed), \n (newline), \r
              (carriage return), \t (tab), and \v (vertical tab) are recognized and automatically  converted  to
              their  special  meanings.  Starting  with  Yodl 2.14.0 octal and hexadecimal constants may also be
              used. E.g., character Y may also be specified using the octal value \131 or the hexadecimal  value
              \x59. Any other character following a defines itself: \\ represents a single backslash character.

              Example:

                  DEFINECHARTABLE(demotable)(
                      ’&’     = "&"
                      ’\\’    = "\\backslash"
                      ’\045’  = "oct(45)"
                      ’0xa4’  = "hex(a4)"
                  )

              The  builtin function DEFINECHARTABLE does not activate the table. The table is merely defined. To
              activate the character translation table, use USECHARTABLE. The discussion of character tables  is
              postponed to section [CHARTABLES].

       DEFINECOUNTER
              DEFINECOUNTER  creates  a  new  counter, to be subsequently used by, e.g, the USECOUNTER function.
              DEFINECOUNTER expects two parameter list: the name of  the  counter  to  create  and  an  optional
              initial value. By default the counter will be initialized to zero.

              Examples:

                  DEFINECOUNTER(YEAR)(1950)
                  DEFINECOUNTER(NTIMES)()

              See also section [COUNTERS].

       DEFINEMACRO
              DEFINEMACRO is used to define new macros. This function requires three parameter lists:

       o      An  identifier,  being  the  name  of  the  macro  to  define. This identifier may only consist of
              uppercase or  lowercase  characters.  Note  that  it  can  not  contain  numbers,  nor  underscore
              characters.

       o      A  number,  stating the number of arguments that the macro will require once used. The number must
              be in the range 0 to 61.

       o      The text that the macro will expand to, once used. This text may contain the strings ARGx, x being
              1,  2,  etc..  At  these  places  the  arguments  to the macro will be pasted in. The numbers that
              identify the arguments are 1 to 9, then A to Z and finally a to  z.  This  gives  a  range  of  61
              expandable  arguments, which is enough for all real-life applications.  For example, the following
              fragment defines a macro bookref, which can be used to typeset a reference to a book. It  requires
              three arguments; say, an author, a title and the name of a publisher:

                  DEFINEMACRO(bookref)(3)(
                      Author(s):           ARG1
                      Book title:          ARG2
                      Published by:        ARG3
                  )

              Such a macro could be used as follows:

                  bookref(Sobotta/Becher)
                         (Atlas der Anatomie des Menschen)
                         (Urban und Schwarzenberg, Berlin, 1972)

              When called, it would produce the following output:

                      Author(s):           Sobotta/Becher
                      Book title:          Atlas der Anatomie des Menschen
                      Published by:        Urban und Schwarzenberg, Berlin, 1972

              While  applying  a macro, the three parameter lists are pasted to the places where ARG1, ARG2 etc.
              occur in the definition.

              Note the following when defining new macros:

       o      The parameter list containing the name of the new macro, (bookref)  in  the  above  example,  must
              occur right after DEFINEMACRO. No spaces are allowed in between. Space characters and newlines may
              however occur following this first parameter list.

              This behavior of the yodl program is similar to  the  usage  of  the  defined  macro:  the  author
              information  must,  enclosed  in  parentheses,  follow  right  after  the  bookref  identifier.  I
              implemented this feature to improve the distinguishing between macros and real text. E.g., a macro
              me might be defined, but the text

                  I like me (but so do you)

              still is simple text; the macro me only is activated when a parenthesis immediately follows it.

       o      Be careful when placing newlines or spaces in the definition of a new macro. E.g., the definition,
              as given:

                  DEFINEMACRO(bookref)(3)(
                      Author(s):           ARG1
                      Book title:          ARG2
                      Published by:        ARG3
                  )

              introduces extra newlines at the beginning and ending of the macro, which will be  copied  to  the
              output each time the macro is used. The extra newline occurs, of course, right before the sequence
              Author(s): and following the evaluation of ARG3. A simple backslash character at the  end  of  the
              DEFINEMACRO line would prevent the insertion of extra newline characters:

                  DEFINEMACRO(bookref)(3)(\
                      Author(s):           ARG1
                      Book title:          ARG2
                      Published by:        ARG3
                  )

       o      Note  that when a macro is used which requires no arguments at all, one empty parameter list still
              must be specified. E.g., my macro package (see chapter [MACROPACKAGE]) defines  a  macro  it  that
              starts a bullet item in a list. The macro takes no arguments, but still must be typed as it().

              This  behavior  is  consistent:  it  helps  distinguish which identifiers are macros and which are
              simple text.

       o      Macro arguments may evaluate to text. When a \ is  appended  to  the  macro-argument,  or  in  the
              default  input  handling  within  a non-zero white-space level (see section [INCWSLEVEL]) this may
              invalidate a subsequent macro call. E.g., the macro

                  DEFINEMACRO(oops)(1)(
                      ARG1
                      XXnl()
                  )

              will, when called as oops(hello world), produce the output:

                  hello worldXXnl()

              To prevent this gluing to arguments to subsequent macros, a single + should be  prepended  to  the
              macro call:

                  DEFINEMACRO(oops)(1)(
                      ARG1
                      +XXnl()
                  )

              See also section [PLUSIDENT] obout the `+identifier’-sequence.

       o      Note  the  preferred  layout of macro definitions and macro calls. Adhere to this form, to prevent
              drowning in too many parentheses. In particular:

       o      Put all elements of the macro definition on one line, except for the macro-expansion itself.  Each
              expansion element should be on a line by itself.

       o      When  calling  macros  put  the  macro  parameter  lists  underneath each other. If the macrolists
              themselves contain macro-calls, put  each  call  again  on  a  line  of  its  own,  indenting  one
              tab-position beyond the location of the opening parenthesis of the argument.

       o      No  continnuation  backslashes  are required between parameter lists. So, do not use them there to
              prevent unnecessary clutter.

       o      With complex calls, indent just the arguments, and  put  the  parentheses  in  their  required  of
              logical locations.  Example of a complex call:

                      complex(
                          first(
                              ARG1
                          )(
                              ARG2
                              +XXnl()
                          )
                          ARG3
                          +nop()
                          ARG4
                          +XXnl()
                      )

       o      Macro expansion proceeds as follows:

       o      The parameter lists are read from the input

       o      The  contents  of  the parameters then replace their ARGx references in the macro’s definition (in
              some exceptional cases, clearly indicated as such when applicable, the arguments  will  themselves
              be  evaluated  first,  and  then  these  evaluated  arguments  are  used as replacements for their
              corresponding ARGx references).

       o      The now modified macro is read by Yodl’s lexical scanner. This may result  in  yet  another  macro
              expansion, which will then be evaluated recursively.

       o      Eventually, all expansion is completed (well, should complete, since Yodl doesn’t test for eternal
              recursion) and scanning of the input continues beyond  the  original  macro  call.   For  example,
              assume we have the following two macros:

                  DEFINEMACRO(First)(1)(
                      Hello ARG1
                      +XXnl()
                  )
                  DEFINEMACRO(Second)(1)(
                      First(ARG1)
                      First(ARG1)
                  )

              and the following call is issued:

                  Second(Yodl)

              then the following will happen:

       o      Second(Yodl) is read as encountered.

       o      ARG1  in  Second  is replaced by YODL, and the resulting macro body is sent to the lexical scanner
              for evaluation: It will see:

                  First(Yodl)First(Yodl)

       o      The first call to First() is now evaluated. This will put  (after  replacing  ARG1  by  YODL)  the
              following on the scanner’s input:

                  Hello Yodl+XXnl()First(Yodl)

       o      Hello Yodl contains no macro call, so it is written to the output stream. Remains:

                  +XXnl()First(Yodl)

       o      Assume  XXnl()  merely contains a newline (represented by \n, here), so +XXnl() is now replaced by
              \n. This results in the following input for the lexical scanner:

                  \nFirst(Yodl)

       o      The \n is now written to the output stream, and the scanner sees:

                  First(Yodl)

       o      The second call to First() is now evaluated. This will put the following on the scanner’s input:

                  Hello Yodl+XXnl()

       o      Hello Yodl is written to the output stream. Remains:

                  +XXnl()

       o      +XXnl() is now replaced by \n. The lexical scanner sees:

                  \n

       o      The newline is printed and we’re done.

       DEFINESYMBOL
              NOTE: this function has changed at the release of Yodl 2.00. It now expects two  parameter  lists,
              rather than one

              DEFINESYMBOL  expects two arguments. An identifier, which is the name of the symbol to define, and
              the textual value of the symbol. If the second argument is empty, the symbol is defined,  but  has
              an empty value.

              The  earlier  interpretation of a Yodl symbol as a logical flag can still be used, but allowing it
              to obtain textual values greatly simplifies various Yodl macros.

              Example:

                  DEFINESYMBOL(Yodl)(Your own document language)
                  DEFINESYMBOL(Options)()

       DELETECHARTABLE
              DELETECHARTABLE removes a definition of a character table that  was  defined  by  DEFINECHARTABLE.
              This function expects one argument: the name of the character table remove.

              It’s  an  error  to  attempt to delete a character table that is currently in use or to attempt to
              delete a non-existing character table.

              Example:

                  DELETECHARTABLE(mytable)

       DELETECOUNTER
              DELETECOUNTER removes a definition of a counter that was defined by DEFINECOUNTER.  This  function
              expects one argument: the name of the counter to remove.

              If the counter does not exist, a warning is issued. It is not considered an error to try to delete
              a counter that has not been defined earlier.

              Example:

                  DELETECOUNTER(mycounter)

       DELETEMACRO
              DELETEMACRO removes a definition of a macro that was defined by DEFINEMACRO. This  function  takes
              one argument: the macro name to remove.

              There  is  no  error  condition (except for syntax errors): when no macro with a matching name was
              previously defined, no action is taken.

              For example, the safe way to define a macro is by first undefining it. This ensures that  possible
              previous definitions are removed first:

              Example:
              DELETEMACRO(mymacro)

       DELETENOUSERMACRO
              DELETENOUSERMACRO  removes a `nousermacro’ definition. The function expects one argument: the name
              of the `nousermacro’ identifier to be removed from the nousermacro-set.

              There is no error condition (except for syntax errors): when the identifier  wasn’t  stored  as  a
              `nousermacro’ no action is taken.

              Example:
              DELETENOUSERMACRO(mymacro)

       DELETESYMBOL
              DELETESYMBOL  removes  the definition of a symbol variable. It expects one parameter list, holding
              the name of the variable to deleted.

              This macro has no error condition (except for syntax  errors):  the  symbol  in  question  may  be
              previously defined, but that is not necessary.

              Example:

                  DELETESYMBOL(Options)

       DUMMY  This function is obsolete. It does nothing, and may be removed in future versions of Yodl.

       ENDDEF ENDDEF is obsolete, and should be replaced by DECWSLEVEL.  It may be removed in future versions of
              Yodl.

       ERROR  The ERROR function takes one argument: text to display to the standard error stream.  The  current
              input  file and line number are also displayed. After displaying the text, the yodl program aborts
              with an exit status of 1.

              The text passed to the function is expanded first. See the example.

              The ERROR function is an example of a function that evaluates its parameter list itself.

              This command can be used, e.g., in a macro package when an incorrect  macro  is  expanded.  In  my
              macro  package (see chapter [MACROPACKAGE]) the ERROR function is used when the sectioning command
              chapter() is used in an article document (in the package, chapter’s are only available in books or
              reports).

              An  analogous  builtin  function  is  WARNING,  which also prints a message but does not exit (see
              section [WARNING]).

              Example: In the following call, COUNTERVALUE(NTRIES) is replaced by its actual value:

                  ERROR(Stopping after COUNTERVALUE(NTRIES) attempts)

       EVAL   The EVAL function takes one argument: the text to  be  evaluated.  This  function  allows  you  to
              perform  an  indirect evaluation of Yodl commands. Assume that there is a symbol varnam containing
              the name of a counter variable, then  the  following  will  display  the  value  of  the  counter,
              incrementing it first:

                  EVAL(NOTRANS(USECOUNTER)(SYMBOLVALUE(varnam)))

              The actions of the EVAL function can be described as follows:

       o      First, the NOTRANS(USECOUNTER) is evaluated, producing USECOUNTER.

       o      Next, the open parentheses is processed, producing the open parenthesis itself

       o      Then, SYMBOLVALUE(varnam) is evaluated, producing the name of a counter, e.g. `counter’.

       o      Eventually the closing parentheis is processed, producing the closing parenthesis itself.

       o      All this results in the text

                  USECOUNTER(counter)

       o      This  text  is now presented to Yodl’s lexical scanner, resulting in incrementing the counter, and
              displaying its incremented value.  It should be  realized  that  macro  arguments  themselves  are
              usually not evaluated. So, a construction like

                  USECOUNTER(EVAL(SYMBOLVALUE(varnam)))

              will  fail,  since EVAL(SYMBOLVALUE(varnam)) is not a legal name for a counter: the EVAL() call is
              used here as an argument, which is not expanded. The distinction is subtle, and is caused  by  the
              fact  that builtin functions receive unprocessed arguments, and may impose certain requirements on
              them (like USECOUNTER requiring the name of a counter).

              Summarizing: EVAL acts as follows:

       o      Its argument is presented to Yodl’s lexical scanner

       o      The output produced by the processing of the argument is then inserted into the  input  stream  in
              lieu of the original EVAL call.

              Mosy  built-in  functions  will  not  evaluate  their arguments. In fact, only ERROR, EVAL, FPUTS,
              INTERNALINDEX, TYPEOUT, UPPERCASE and WARNING() will evaluate their arguments.

              Postponing evaluations allows you to write:

                  DEFINESYMBOL(later)(SYMBOLVALUE(earlier))

              Eventually, and not when later is defined, a statement like

                  SYMBOLVALUE(later)

              will produce the value of earlier at the moment SYMBOLVALUE(later) is processed. This is,  in  all
              its  complex  consequences,  what  would  be expected in most cases. It allows us to write general
              macros producing output that is only evaluated when the text of symbols and  values  of  arguments
              become eventually, rather than when the macro is defined, available.

              Decisions  like  these invariably result in questions like `what if I have to keep original values
              in some situation?’ In those situations EVAL() must be  used.  The  following  example  shows  the
              definition  of  three  symbols:  one receives an initial value, two will return one’s actual value
              when two’s value is displayed, three will, using EVAL(), store one’s initial  value.  The  example
              also  shows  yet another way to suppress macro  calls. It uses the macro nop() which is defined in
              the all standard conversion types.

                  DEFINESYMBOL(one)(This is one, before)
                  DEFINESYMBOL(two)(SYMBOLVALUE(one))
                  EVAL(DEFINESYMBOL+nop()(three)(SYMBOLVALUE(one)))
                  SETSYMBOL(one)(this is one, after)
                  SYMBOLVALUE(two)
                  SYMBOLVALUE(three)

       FILENAME
              The function FILENAME() produces an absolute path to the currently processed Yodl  file.  This  is
              not necessarily the canonical path name, as it may contain current- and parent-path directories.

       FPUTS  The  function  FPUTS  expects  two arguments: the first argment is information to be appended to a
              file, whose name is given as the second argument. The first argument is processed by  Yodl  before
              it is appended to the requested filename, so it may contain macro calls.

              For example, the following statement will append a countervalue to the mentioned file:

                  FPUTS(There have been COUNTERVALUE(attempts) attempts)(/tmp/logfile)

              The second argument (name of the file) is not evaluated, but is used as received.

       IFBUILTIN
              The  IFBUILTIN function tests whether its first argument is the name of a builtin function. If so,
              the second parameter list is evaluated, else, the third parameter list  is  evaluated.  All  three
              parameter  lists  (the  variable,  the  true-list  and the false-list) must be present; though the
              true-list and/or the false-list may be empty parameter lists.

              Example:

                  IFBUILTIN(IFBUILTIN)(\
                      `BUILTIN’ is a builtin - function
                  )(\
                      `BUILTIN’ is NOT a builtin - function
                  )

              Please note the preferred layout: The first argument immediately follows the function  name,  then
              the  second argument (the true list) is indented, as is the false list. The layout closely follows
              the preferred layout of if-else statements of many programming languages.

       IFCHARTABLE
              The IFCHARTABLE function tests whether its first argument is the name of a  character  table.  The
              character  table  needs  not  be active.  If the name is the name of a character table, the second
              parameter list is evaluated, else, the third parameter list  is  evaluated.  All  three  parameter
              lists  (the  name,  the true list and the false list) must be present; though the true list and/or
              the false list may be empty parameter lists.

              Example:

                  IFCHARTABLE(standard)(\
                      `standard’ is a character tablebuiltin - function
                  )(\
                      `standard’ is NOT a character tablebuiltin - function
                  )

              Please note the preferred layout: The first argument immediately follows the function  name,  then
              the  second argument (the true list) is indented, as is the false list. The layout closely follows
              the preferred layout of if-else statements of many programming languages.

       IFDEF  The IFDEF function tests for the definition status of the argument in its first parameter list. If
              it  is a defined entity, the second parameter list is evaluated, else, the third parameter list is
              evaluated. All three parameter lists (the entity, the true  list  and  the  false  list)  must  be
              present; though the true list and/or the false list may be empty parameter lists.

              The true list is evaluated if the first argument is the name of:

       o      a built-in function, or

       o      a character table, or

       o      a counter, or

       o      a no-user-macro symbol, or

       o      a symbol, or

       o      a user-defined macro, or Example:

                  IFDEF(someName)(\
                      `someName’ is a defined entity
                  )(\
                      `someName is not defined.
                  )

              Please  note  the preferred layout: The first argument immediately follows the function name, then
              the second argument (the true list) is indented, as is the false list. The layout closely  follows
              the preferred layout of if-else statements of many programming languages.

       IFEMPTY
              IFEMPTY  expects three arguments: a symbol, a true-list and a false-list. IFEMPTY evaluates to the
              true-list if the symbol is an empty string; otherwise, it evaluates to the false-list.

              The function does not further evaluate its argument. Its use is primarily to test whether a  macro
              has  received  an  argument or not. If the intent is to check whether a symbol’s value is empty or
              not, IFSTREQUAL [IFSTREQUAL] should be used, where the first argument is the name of a symbol, and
              the second argument is empty.

              Example:

                  IFEMPTY(something)(\
                      `something’ is empty...
                  )(\
                      `something’ is not an empty string
                  )

              In  the same way, IFEMPTY can be used to test whether an argument expands to a non-empty string. A
              more elaborate example follows  below.  Say  you  want  to  define  a  bookref  macro  to  typeset
              information  about  an author, a book title and about the publisher. The publisher information may
              be absent, the macro then typesets unknown:
              \
                  DEFINEMACRO(bookref)(3)(\
                      Author(s):      ARG1
                      Title:          ARG2
                      Published by:   \
                      IFEMPTY(ARG3)
                      (\
                          Unknown\
                      )(\
                          ARG3\
                      )
                  )

              Using the macro, as in:
              \
                  bookref(Helmut Leonhardt)
                         (Histologie, Zytologie und Microanatomie des Menschen)
                         ()

              would now result in the text Unknown behind the Published by: line.

              Please note the preferred layout: The first argument immediately follows the function  name,  then
              the  second argument (the true list) is indented, as is the false list. The layout closely follows
              the preferred layout of if-else statements of many programming languages.

       IFEQUAL
              IFEQUAL expects four argument lists. It tests whether its first argument is equal  to  its  second
              argument.  If  so,  the  third  parameter  list  is  evaluated, else, the fourth parameter list is
              evaluated. All four argument lists must be present, though all can be empty lists.

              The first two arguments of IFEQUAL should be integral numerical arguments. In order  to  determine
              whether the first two arguments are equal, their values are determined:

       o      If the argument starts with an integral numerical value, that value is the value of the argument.

       o      If the argument is the name of a counter, the counter’s value is the value of the argument

       o      If  the  values  of  the  first  two  arguments van be determined accordingly, their equality will
              determine whether the true list (when the values are equal) or the false list (when the values are
              unequal) will be evaluated.

       o      Otherwise, IFEQUAL will evaluate the false list.

              Example:

                  IFEQUAL(0)()(\
                      0 and an empty string are equal
                  )(\
                      0 and an empty string are not equal
                  )

              Please  note  the preferred layout: The first argument immediately follows the function name, then
              the second argument (the true list) is indented, as is the false list. The layout closely  follows
              the preferred layout of if-else statements of many programming languages.

       IFGREATER
              IFGREATER  expects  four  argument  lists.  It  tests whether its first argument is greater to its
              second argument. If so, the third parameter list is evaluated, else, the fourth parameter list  is
              evaluated. All four argument lists must be present, though all can be empty lists.

              The first two arguments of IFGREATER should be integral numerical arguments. In order to determine
              whether the first two arguments are equal, their values are determined:

       o      If the argument starts with an integral numerical value, that value is the value of the argument.

       o      If the argument is the name of a counter, the counter’s value is the value of the argument

       o      If the values of the first two arguments van be determined accordingly, their order relation  will
              determine  whether  the  true  list (when the first value is greater than the second value) or the
              false list (when the first value is smaller or equal than the second value) will be evaluated.

       o      Otherwise, IFGREATER will evaluate the false list.

              Example:

                  IFGREATER(counter)(5)(\
                      counter exceeds the value 5
                  )(\
                      counter does not exceeds the value 5, or counter is no Yodl-counter.
                  )

              Please note the preferred layout: The first argument immediately follows the function  name,  then
              the  second argument (the true list) is indented, as is the false list. The layout closely follows
              the preferred layout of if-else statements of many programming languages.

       IFMACRO
              The IFMACRO function tests whether its first argument is the name of a macro. If the name  is  the
              name  of  a  macro,  the  second  parameter  list  is evaluated, else, the third parameter list is
              evaluated. All three parameter lists (the name, the true list and the false list) must be present;
              though the true list and/or the false list may be empty parameter lists.

              Example:

                  IFMACRO(nested)(\
                      `nested’ is the name of a macro
                  )(\
                      There is no macro named `nested’
                  )

              Please  note  the preferred layout: The first argument immediately follows the function name, then
              the second argument (the true list) is indented, as is the false list. The layout closely  follows
              the preferred layout of if-else statements of many programming languages.

       IFSMALLER
              IFSMALLER  expects  four  argument  lists.  It  tests whether its first argument is smaller to its
              second argument. If so, the third parameter list is evaluated, else, the fourth parameter list  is
              evaluated. All four argument lists must be present, though all can be empty lists.

              The first two arguments of IFSMALLER should be integral numerical arguments. In order to determine
              whether the first two arguments are equal, their values are determined:

       o      If the argument starts with an integral numerical value, that value is the value of the argument.

       o      If the argument is the name of a counter, the counter’s value is the value of the argument

       o      If the values of the first two arguments van be determined accordingly, their order relation  will
              determine  whether  the  true  list (when the first value is smaller than the second value) or the
              false list (when the first value is greater than or equal to the second value) will be evaluated.

       o      Otherwise, IFSMALLER will evaluate the false list.

              Example:

                  IFSMALLER(counter)(5)(\
                      counter is smaller than the value 5, or counter is no Yodl-counter
                  )(\
                      counter exceeds the value 5
                  )

              Please note the preferred layout: The first argument immediately follows the function  name,  then
              the  second argument (the true list) is indented, as is the false list. The layout closely follows
              the preferred layout of if-else statements of many programming languages.

       IFSTREQUAL
              IFSTREQUAL tests for the equality of two strings. It expects four arguments: two strings to match,
              a  true list and a false list. The true list is only evaluated when the contents of the two string
              arguments exactly match.

              The first two arguments of IFSTREQUAL are partially evaluated:

       o      If the argument is the name of a symbol, the symbol’s value is the value of the argument

       o      Otherwise, the argument itself is used.

              In the degenerate case where the string to be compared is actually the name of  a  SYMBOL,  use  a
              temporary  SYMBOL variable containing the name of that symbol, and compare it to whatever you want
              to compare it with. Alternatively, write a blank space behind the arguments, since  the  arguments
              are  then  interpreted  `as  is’.  In  practice,  the  need  for these constructions seem to arise
              seldomly, however.

              Example:

                  IFSTREQUAL(MYSYMBOL)(Hello world)(
                      The symbol `MYSYMBOL’ holds the value `Hello world’
                  )(
                      The symbol `MYSYMBOL’ doesn’t hold the value `Hello world’
                  )

       IFSTRSUB
              IFSTRSUB tests whether a string is a sub-string of another string. It acts similar to  IFSTREQUAL,
              but it tests whether the second string is part of the first one.

              The first two arguments of IFSTREQULA are partially evaluated:

       o      If the argument is the name of a symbol, the symbol’s value is the value of the argument

       o      Otherwise, the argument itself is used.

              In  the  degenerate  case  where the string to be compared is actually the name of a SYMBOL, use a
              temporary SYMBOL variable containing the name of that symbol, and compare it to whatever you  want
              to  compare  it with. Alternatively, write a blank space behind the arguments, since the arguments
              are then interpreted `as is’. In  practice,  the  need  for  these  constructions  seem  to  arise
              seldomly, however.

              Example:

                      IFSTRSUB(haystack)(needle)(
                          `needle’ was found in `haystack’
                      )(
                          `needle’ was not found in `haystack’
                      )

              Note  that  both  `haystack’ and `needle’ may be the names of symbols. If they are, their contents
              are is compared, rather than the literal names `haystack’ and `needle’

       IFSYMBOL
              The IFSYMBOL function tests whether its first argument is the name of a symbol. If it is the  name
              of  a symbol, the second parameter list is evaluated, else, the third parameter list is evaluated.
              All three parameter lists (the name, the true list and the false list) must be present; though the
              true list and/or the false list may be empty parameter lists.

              Example:

                  IFSYMBOL(nested)(\
                      `nested’ is the name of a symbol
                  )(\
                      There is no symbol named `nested’
                  )

              Please  note  the preferred layout: The first argument immediately follows the function name, then
              the second argument (the true list) is indented, as is the false list. The layout closely  follows
              the preferred layout of if-else statements of many programming languages.

       IFZERO IFZERO  expects  three  parameter  lists.  The  first  argument defines whether the whole function
              expands to the true list or to the false list.

              The first argument of IFZERO should be an integral numerical value. Its  value  is  determined  as
              follows:

       o      If the argument starts with an integral numerical value, that value is the value of the argument.

       o      If the argument is the name of a counter, the counter’s value is the value of the argument

       o      Otherwise, IFZERO will evaluate the false list.

              Note  that,  starting  with Yodl version 2.00 the first argument is not evaluated any further. So,
              COUNTERVALUE(somecounter) will always be evaluated as 0. If the value of a  counter  is  required,
              simply provide its name as the first argument of the IFZERO function.

              Example:

                  DEFINEMACRO(environment)(2)(\
                      IFZERO(ARG2)(\
                          NOEXPAND(\end{ARG1})\
                      )(\
                          NOEXPAND(\begin{ARG1})\
                      )\
                  )

              Such a macro may be used as follows:

                  environment(center)(1)
                      Now comes centered text.
                  environment(center)(0)

              which would of course lead to \begin and \end{center}. The numeric second argument is used here as
              a on/off switch.

       INCLUDEFILE
              INCLUDEFILE takes one argument, a filename. The file is processed by Yodl. If  a  file  should  be
              inserted   without   processing   the   builtin   function  NOEXPANDINCLUDE  [NOEXPANDINCLUDE]  or
              NOEXPANDPATHINCLUDE [NOEXPANDPATHINCLUDE] should be used.

              The yodl program supplies, when necessary, an extension to the filename.  The  supplied  extension
              is .yo, unless defined otherwise during the compilation of the program.

              Furthermore,  Yodl tries to locate the file in the Yodl’s include path (which may be set using the
              --include option). The actual value of the  include  path  is  shown  in  the  usage  information,
              displayed when Yodl is started without arguments.

              NOTE:  Starting  with  Yodl version 3.00.0 Yodl’s default file inclusion behavior has changed. The
              current working directory no longer remains fixed at the directory in which Yodl is called, but is
              volatile,  changing  to the directory in which a yodl-file is located. This has the advantage that
              Yodl’s file inclusion behavior now matches the way C’s #include directive  operates;  it  has  the
              disadvantage  that  it  may break some current documents. Conversion, however is simple and can be
              avoided altogether if Yodl’s -L (--legacy-include) option is used.

              Example:

                  INCLUDEFILE(latex)

              will try to include the file latex or latex.yo from the current include parth. When  the  file  is
              not found, Yodl aborts.

       INCLUDELIT, INCLUDELITERAL
              INCLUDELIT    and    INCLUDELITERAL    are   obsolete.    NOEXPANDINCLUDE   [NOEXPANDINCLUDE]   or
              NOEXPANDPATHINCLUDE [NOEXPANDPATHINCLUDE] should be used instead.

       INCWSLEVEL
              INCWSLEVEL requires one (empty) parameter list.  It increases the current white-space  level.  The
              white-space  level  typically is used in files that only define Yodl macros. When no output should
              be generated while processing these files, the white-space level can be used to check for this. If
              the   white-space  level  exceeds  zero,  a  warning  will  be  generated  if  the  file  produces
              non-whitespace output. The builtin function DECWSLEVEL is used  to  reduce  the  whitespace  level
              following a previous call of INCWSLEVEL.

              Once  the white space level exceeds zero, no output will be generated. White space, therefore will
              effectively be ignored. The white space level cannot be reduced to negative values. A  warning  is
              issued if that would have happened if it were allowed.

              Example:

                  INCWSLEVEL()
                  DEFINESYMBOL(....)
                  DEFINEMACRO(...)(...)(...)
                  DECWSLEVEL()

              Without the INCWSLEVEL and DECWSLEVEL, calls, the above definition would generate four empty lines
              to the output stream.

              The INCWSLEVEL and DECWSLEVEL calls may be nested. The best approach is to put  an  INCWSLEVEL  at
              the  first  line  of  a  macro-defining Yodl-file, and a matching DECWSLEVEL call at the very last
              line.

       INTERNALINDEX
              INTERNALINDEX expects one argument list. The argument list is evaluated and written to  the  index
              file.

              The  index  file  is defined since Yodl version 2.00, and contains the fixup information which was
              previously written to Yodl’s output as the .YODLTAGSTART.  ... .YODLTAGEND. sequence.

              The index file allows for greated processing speed, at the expense  of  an  additional  file.  The
              associated  yodlpost  postprocessing  program will read and process the index file, and will fixup
              the corresponding yodl-output accordingly.

              The index file is not created when output is written to the standard output name,  since  Yodl  is
              unable to request the system for the current file offset.

              The  entries of the index file always fit on one line. INTERNALINDEX will alter newline characters
              in its argument into single blank spaces. Each line starts  with  the  current  offset  of  Yodl’s
              output  file,  thus  indicating  the  exact  location  where a fixup is requested. An example of a
              produced fixup line could be

                  3004 ref MACROPACKAGE

              indicating that at offset 3004 in the produced output file a reference to the  label  MACROPACKAGE
              is requested. Assuming a html conversion, The postprocessor will thereupon write something like

                  <a href="outfile04.html#MACROPACKAGE">4.3.2.</a>

              into the actual output file while processing Yodl’s output up to offset location 3004.

              Consequently, producing Yodl-output normally consists of two steps:

       o      First,  Yodl itself is started, producing, e.g., out.idx (the index file) and out.yodl (Yodl’s raw
              output).

       o      Then, Yodl’s post-processor processes out.idx and out.yodl, producing one  or  more  final  output
              files,  in  which  the  elements  of the index file have been properly handled. This may result in
              multiple output file, like report.html, report01.html, report02.html etc.

       NEWCOUNTER
              NEWCOUNTER is obsolete. DEFINECOUNTER [DEFINECOUNTER] should be used instead.

       NOEXPAND
              NOEXPAND is used to send text to the final output file without being expanded by Yodl  (the  other
              methods  are  the  CHAR  macro, see section [CHAR], and the NOTRANS macro, see section [NOTRANS]).
              NOEXPAND takes one parameter list, the text in question. Whatever occurs in the  argument  is  not
              subject  to parsing or expansion by Yodl, but is simply copied to the output file (except for CHAR
              functions in the argument, which are expanded. If CHAR-expansion is not  required  either  NOTRANS
              [NOTRANS] can be used).

              Furthermore,  the contents of the parameter list are also subject to character table translations,
              using the currently active table. This should come as no surprise. Ignoring character tables would
              make both the processing of CHAR calls and the NOTRANS function superfluous.

              So, the following situations are recognized:

              ──────────────────────────────────────────────
                                    support chartables
                                         and CHAR
                              ──────────────────────────────
              Macro expansion   yes          no
              ──────────────────────────────────────────────
              Yes               (standard)   Push chartable
                                             (standard)
                                             Pop chartable
              No                NOEXPAND     NOTRANS
              ──────────────────────────────────────────────

              E.g., let’s assume that you need to write in your document the following text:

                  INCLUDEFILE(something or the other)
                  IFDEF(onething)(
                      ...
                  )(
                      ....
                  )
                  NOEXPAND(whatever)

              The  way  to accomplish this is by prefixing the text by NOEXPAND followed by an open parenthesis,
              and by postfixing it by a closing parenthesis.  Otherwise, the text  would  be  expanded  by  Yodl
              while processing it (and would lead to syntax errors, since the text isn’t correct in the sence of
              the Yodl language).

              For this function, keep the following caveats in mind:

       o      There is only one thing that a NOEXPAND  cannot  protect  from  expansion:  an  ARGx  in  a  macro
              definition. The argument specifier is always processed. E.g., after

                  DEFINEMACRO(thatsit)(1)(
                      That is --> NOEXPAND(ARG1) <-- it!
                  )
                  thatsit(after all)

              the ARG1 inside the NOEXPAND statement is replaced with after all.

       o      The  NOEXPAND function must, as all functions, be followed by a parameter list. The parentheses of
              the list must therefore be `balanced’.   For  unbalanced  lists,  use  CHAR(40)  to  set  an  open
              parenthesis, or CHAR(41) to typeset a closing parenthesis.

       NOEXPANDINCLUDE
              NOEXPANDINCLUDE takes one argument, a filename. The file is included.

              The filename is uses as specified. The include path is not used when locating this file.

              NOTE:  Starting  with  Yodl version 3.00.0 Yodl’s default file inclusion behavior has changed. The
              current working directory no longer remains fixed at the directory in which Yodl is called, but is
              volatile,  changing  to the directory in which a yodl-file is located. This has the advantage that
              Yodl’s file inclusion behavior now matches the way C’s #include directive  operates;  it  has  the
              disadvantage  that  it  may break some current documents. Conversion, however is simple and can be
              avoided altogether if Yodl’s -L (--legacy-include) option is used.

              The argument to NOEXPANDINCLUDE is partially evaluated:

       o      If the argument is the name of a symbol, the symbol’s value is the value of the argument

       o      Otherwise, the argument itself is used.  The thus obtained file name is not further evaluated:  in
              particular, it will not be subject to character translations.

              The  contents  of  the  file  are  included  literally,  not subject to macro expansion. Character
              translations are performed, though. If character translations are not  appropriate,  PUSHCHARTABLE
              can be used to suppress character table translations temporarily.

              The purpose of NOEXPANDINCLUDE is to include source code literally in the document, as in:

                  NOEXPANDINCLUDE(literal.c)

              The  function  NOEXPANDPATHINCLUDE  can  be  used  to insert a file which is located in one of the
              directories specified in Yodl’s include path.

       NOEXPANDPATHINCLUDE
              NOEXPANDPATHINCLUDE takes one argument, a filename. The file is included. The file is searched for
              in the directories specified in Yodl’s includepath.

              NOTE:  Starting  with  Yodl version 3.00.0 Yodl’s default file inclusion behavior has changed. The
              current working directory no longer remains fixed at the directory in which Yodl is called, but is
              volatile,  changing  to the directory in which a yodl-file is located. This has the advantage that
              Yodl’s file inclusion behavior now matches the way C’s #include directive  operates;  it  has  the
              disadvantage  that  it  may break some current documents. Conversion, however is simple and can be
              avoided altogether if Yodl’s -L (--legacy-include) option is used.

              The argument to NOEXPANDPATHINCLUDE is partially evaluated:

       o      If the argument is the name of a symbol, the symbol’s value is the value of the argument

       o      Otherwise, the argument itself is used.  The thus obtained file name is not further evaluated:  in
              particular, it will not be subject to character translations.

              Like the NOEXPANDINCLUDE function, the contents of the file are included literally, not subject to
              macro expansion. Character translations are performed, though. If character translations  are  not
              appropriate,  PUSHCHARTABLE  [PUSHCHARTABLE]  can be used to suppress character table translations
              temporarily.

              The purpose of NOEXPANDPATHINCLUDE is to include  source  code  as  defined  in  a  macro  package
              literally into the document, as in:

                  NOEXPANDPATHINCLUDE(rug-menubegin.xml)

       NOTRANS
              NOTRANS  copies  its one argument literally to the output file, without expanding macros in it and
              without translating the characters with the current translation table.  The  NOTRANS  function  is
              typically used to send commands for the output format to the output file.

              For example, consider the following code fragment:

                  COMMENT(--- Define character translations for \, { and } in LaTeX. ---)
                  DEFINECHARTABLE(standard)(
                      ’\\’    =    "$\\backslash$"
                      ’{’     =    "\\verb+{+"
                      ’}’     =    "\\verb+}+"
                  )

                  COMMENT(--- Activate the translation table. ---)
                  USECHARTABLE(standard)

                  COMMENT(--- Now two tests: ---)

                  NOEXPAND(\input{epsf.tex})
                  NOTRANS(\input{epsf.tex})

              NOEXPAND will send

                  $\backslash$input\verb+{+epsf.tex\verb+}+

              since  the  characters  in  its  argument  are  translated with the standard translation table. In
              contrast, NOTRANS will send \input{epsf.tex}.

              The parameter list of NOTRANS must be balanced with respect to  its  parentheses.  When  using  an
              unbalanced set of parentheses, use CHAR(40) to send a literal (, or CHAR(41) to send a ).

              The  NOEXPAND  description  summarizes  all  combinations  of  character translations and/or macro
              expansion, and how they are handled and realized by Yodl.

       NOUSERMACRO
              NOUSERMACRO controls yodl’s warnings in the following way: When Yodl is started with the  -w  flag
              on  the  command  line,  then  warnings  are generated when Yodl encounters a possible macro name,
              followed by a parameter list, without finding a macro by that name.  Yodl  then  prints  something
              like cannot expand possible user macro.

              Examples  of  such  sequences  are,  The  necessary file(s) are in /usr/local/lib/yodl, or see the
              manual page for sed(1). The candidate macros are file and sed; these names could just as  well  be
              `valid’ user macros followed by their parameter list.

              When a corresponding NOUSERMACRO statement appears before yodl encounters the candidate macros, no
              warning is generated. A fragment might therefore be:

                  NOUSERMACRO(file sed)
                  The necessary file(s) are in ...
                  See the manual page for sed(1).

              The NOUSERMACRO accepts one or more names in its  argument,  separated  by  white  space,  commas,
              colons, or semi-colons.

       OUTBASE
              OUTBASE  inserts the current basename of the output file into the output file. The basename is the
              name of the file of which the directory components and extension were stripped.

              If the output file is the standard output file, - is inserted.

       OUTDIR OUTDIR inserts the current path name of the output file into the output file. The path name is  a,
              not  necessarily absolute, designator of the directory in which the output file is located. If the
              output file is indicated as, e.g., -o out, then OUTDIR simply inserts a dot.

              If the output file is the standard output file, a dot is inserted too.

       OUTFILENAME
              OUTFILENAME inserts the current filename of the output file into the output file. The filename  is
              the name of the file of which the directory components  were stripped.

              If the output file is the standard output file, - is inserted.

       PARAGRAPH
              PARAGRAPH  isn’t  really  a  builtin  function,  but  as  it  is handled especially by Yodl, it is
              described here nonetheless.  Starting with Yodl 2.00  PARAGRAPH operates as follows:

              If the macro is not defined, new paragraphs, defined as series of consecutive empty lines  written
              to  the  output  stream, are not handled different from any other series of characters sent to the
              output stream. I.e., they are inserted into that stream.

              However, if the macro has been defined, Yodl will call it whenever a new paragraph (defined  as  a
              series of at least two blank lines) was recognized.

              The  empty lines that were actually recognized may be obtained inside the PARAGRAPH macro from the
              XXparagraph symbol, if this symbol has been be defined by that time. If defined, it  will  contain
              the white space that caused Yodl to call the PARAGRAPH macro.

              Note  that,  in order to inspect XXparagraph it must have been defined first. Yodl itself will not
              define this symbol itself.

              The PARAGRAPH macro should be  defined as a macro not expecting  arguments.   The  macro  is  thus
              given  a  chance  to  process  the paragraph in a way that’s fitting for the particular conversion
              type. If the PARAGRAPH macro produces series of empty lines itself, then those  empty  lines  will
              not  cause  Yodl  to  activate  PARAGRAPH.  So,  Yodl  itself will not recursively call PARAGRAPH,
              although the macro could call  itself  recursively.  Of  course,  such  recursive  activcation  of
              PARAGRAPH is then the sole responsibility of the macro’s author, and not Yodl’s.

              Some  document  languages  do  not  need paragraph starts; e.g., LaTeX handles its own paragraphs.
              Other document languages do need it: typically, PARAGRAPH is then  defined  in  a  macro  file  to
              trigger some special action. E.g., a HTML converter might define a paragraph as:

                  DEFINEMACRO(PARAGRAPH)(0)(
                      XXnl()
                      NOTRANS(<p>)
                  )

              A  system  like  xml has more strict requirements. Paragraphs here must be opened and closed using
              pairs of <p> and </p> tags. In those cases an auxiliary counter can be used  to  indicate  whether
              there  is  an open paragraph or not. The PARAGRAPH macro could check for this as follows, assuming
              the availability of a counter XXp:

                  DEFINEMACRO(PARAGRAPH)(0)(
                      XXnl()
                      IFZERO(XXp)(
                      )(
                          NOTRANS(</p>)
                      )
                      NOTRANS(<p>)
                      SETCOUNTER(XXp)(1)
                  )

              Note that the above fragment exemplifies an approach, not necessarily the  implementation  of  the
              PARAGRAPH macro for an xml-converter.

       PIPETHROUGH
              The  builtin  function  PIPETHROUGH  is,  besides  SYSTEM,  the  second function with which a Yodl
              document can affect its environment. Therefore, the danger of `live data’  exists  which  is  also
              described  in  the  section  about SYSTEM (see section [SYSTEM]). Nevertheless, PIPETHROUGH can be
              very useful. It is intended to use external programs to accomplish special features. The  idea  is
              that  an  external  command  is  started,  to which a block of text from within a Yodl document is
              `piped’. The output of that child program is piped back into the Yodl document; hence, a block  of
              text  is  `piped  through’  an  external  program.  Whatever is received again in the Yodl run, is
              further processed.

              The PIPETHROUGH function takes two arguments:

       o      the command to run, and

       o      the text to send to that command.

              Functionally, the occurrence of the PIPETHROUGH function and of its two arguments is  replaced  by
              whatever the child program produces on its standard output.

              An example might be the inclusion of the current date, as in:

              The current date is:
              PIPETHROUGH(date)()

              In this example the command is date and the text to send to that program is empty.

              The  main  purpose  of this function is to provide a way by which external programs can be used to
              create, e.g., tables or figures for a given output format.  Further releases of Yodl  may  contain
              such dedicated programs for the output formats.

       POPCHARTABLE
              Character tables which are pushed onto the table stack using PUSHCHARTABLE() are restored (popped)
              using POPCHARTABLE(). For a description of this mechanism please refer to section [PUSHINGTABLES].

       POPCOUNTER
              POPCOUNTER is used to remove the topmost counter from the counter stack.  The values  of  counters
              may  be  pushed  on  a  stack  using PUSHCOUNTER [PUSHCOUNTER]. To remove the topmost element of a
              counter’s stack POPCOUNTER is available. POPCOUNTER expects one argument: the name of the  counter
              to  pop.  The previously pushed value then becomes the new value of the counter. A counter’s value
              may be popped after defining it, whereafter the stack will be empty, but the counter will still be
              defined. In that case, using the counter’s value is considered an error.

              Examples:

                  DEFINECOUNTER(YEAR)(1950)
                  POPCOUNTER(YEAR)
                  COMMENT(YEAR now has an undefined value)

              See also section [COUNTERS].

       POPMACRO
              POPMACRO  is used to remove the actual macro definition, restoring a previously pushed definition.
              The values of macros may be pushed on a stack using PUSHMACRO. To remove the topmost element of  a
              macro’s  stack POPMACRO is available. POPMACRO expects one argument: the name of the macro to pop.
              The previously pushed value then becomes the new value of the macro.

              A macro’s value may be popped after defining it, whereafter the stack will be empty, but the macro
              will still be defined. In that case, using the macro is considered an error.

              Example:

                  DEFINEMACRO(Hello)(1)(Hello, ARG1, this is a macro definition)
                  Hello(Karel)
                  PUSHMACRO(Hello)(1)(Hello, ARG1, this is the new definition)
                  Hello(Karel)
                  POPMACRO(Hello)
                  Hello(Karel)
                  COMMENT(The third activation of Hello() produces the same output
                          as the first activation)

       POPSYMBOL
              POPSYMBOL  is  used to remove the topmost symbol from the symbol stack.  The values of symbols may
              be pushed on a stack using PUSHSYMBOL [PUSHSYMBOL]. To remove the topmost element  of  a  symbol’s
              stack POPSYMBOL is available.

              POPSYMBOL  expects  one  argument: the name of the symbol to pop. The previously pushed value then
              becomes the new value of the symbol. A symbol’s value may be popped after defining it,  whereafter
              the  stack  will  be empty, but the symbol will still be defined. In that case, using the symbol’s
              value is considered an error.

              Example:

                  DEFINESYMBOL(YEAR)(This happened in 1950)
                  POPSYMBOL(YEAR)
                  COMMENT(YEAR now has an undefined value)

       POPWSLEVEL
              POPWSLEVEL is used to remove the topmost wslevel from the wslevel stack.  The values  of  wslevels
              may be pushed on a stack using PUSHWSLEVEL [PUSHWSLEVEL]. See also section DECWSLEVEL [DECWSLEVEL]

              To remove the topmost element of a wslevel’s stack POPWSLEVEL is available. POPWSLEVEL expects one
              argument: the name of the wslevel to pop. The previously pushed value then becomes the  new  value
              of  the  wslevel.  A wslevel’s value may be popped after defining it, whereafter the stack will be
              empty, but the wslevel will still  be  defined.  In  that  case,  using  the  wslevel’s  value  is
              considered an error.

              Example:

                  COMMENT(Assume WS level is zero)

                  PUSHWSLEVEL(1)
                  COMMENT(WS level now equals 1)

                  POPWSLEVEL()
                  COMMENT(WS level now equals 0 again)

       PUSHCHARTABLE
              Once  a  character  table has been defined, it can be pushed onto a stack using PUSHCHARTABLE. The
              pushed chartable may be popped later.  PUSHCHARTABLE  is  described  in  more  detail  in  section
              [PUSHINGTABLES].

       PUSHCOUNTER
              PUSHCOUNTER is used to start another lifetime for a counter, pushing its current value on a stack.
              A stack is available for each individual counter.

              PUSHCOUNTER expects two arguments: the name of the  counter  to  push  and  its  new  value  after
              pushing.  When the second argument is an empty parameter list, the new value will be zero. The new
              value may be specified as a numerical value, or as the name of an existing  counter.  Specify  the
              name of the counter twice to merely push its value, without modifying its current value.

              Examples:

                  DEFINECOUNTER(YEAR)(1950)
                  PUSHCOUNTER(YEAR)(1962)
                  COMMENT(YEAR now has the value 1962, and a pushed value of 1950)

              See also section [COUNTERS].

       PUSHMACRO
              PUSHMACRO  is  used  to  start  another  lifetime for a macro, pushing its current definition on a
              stack. A stack is available for each individual macro.

              PUSHMACRO expects three arguments: the name of the macro to push,  the  number  of  its  arguments
              after  pushing  (which  may  be  different  from the number of arguments interpreted by the pushed
              macro)  and its new definition.

              So, PUSHMACRO is used exactly like DEFINEMACRO, but redefines a current macro  (or  define  a  new
              macro if no macro was defined by the name specified as its first argument.

              Example:

                  DEFINEMACRO(Hello)(1)(Hello, ARG1, this is a macro definition)
                  Hello(Karel)
                  PUSHMACRO(Hello)(1)(Hello, ARG1, this is the new definition)
                  Hello(Karel)
                  POPMACRO(Hello)
                  Hello(Karel)
                  COMMENT(The third activation of Hello() produces the same output
                          as the first activation)

       PUSHSYMBOL
              PUSHSYMBOL is used to start another lifetime for a symbol, pushing its current value on a stack. A
              stack is available for each individual symbol.

              PUSHSYMBOL expects two arguments: the name of the symbol to push and its new value after  pushing.
              When the second argument is an empty parameter list, the new value will be zero. The new value may
              be specified as a numerical value, or as the name of an existing symbol. Specify the name  of  the
              symbol twice to merely push its value, without modifying its current value.

              Examples:

                  DEFINESYMBOL(YEAR)(This happened in 1950)
                  PUSHSYMBOL(YEAR)(This happended in 1962)
                  COMMENT(YEAR now has the value `This happended in 1962’ and a
                          pushed value of `This happened in 1950’)

       PUSHWSLEVEL
              PUSHWSLEVEL is used to start another lifetime of the white-space level pushing the level’s current
              value on a stack. See also section INCWSLEVEL [INCWSLEVEL]

              PUSHWSLEVEL expects one argument, the new value of  the  white-space  level.  This  value  may  be
              specified  as  a  numerical value or as the name of a counter. The argument may be empty, in which
              the new value will be zero.

              Example:

                  COMMENT(Assume WS level is zero)

                  PUSHWSLEVEL(1)
                  COMMENT(WS level now equals 1)

                  POPWSLEVEL()
                  COMMENT(WS level now equals 0 again)

       RENAMEMACRO
              RENAMEMACRO takes two arguments: the name of a built-in macro (such as INCLUDEFILE)  and  its  new
              name.

              E.g., after

                  RENAMEMACRO(INCLUDEFILE)(include)

              a  file  must be included by include(file).  INCLUDEFILE can no longer be used for this: following
              the RENAMEMACRO action, the old name can no longer be used; it becomes an undefined symbol.

              If you want to make an alias for a built-in command, do it with DEFINEMACRO. E.g., after:

                  DEFINEMACRO(include)(1)(INCLUDEFILE(ARG1))

              both INCLUDEFILE and include can be used to include a file.

       SETCOUNTER
              SETCOUNTER expects two parameter lists: the name of a counter, and a numeric value or the name  of
              another counter.

              The  corresponding  counter  (which  must  be  previously  created  with  NEWCOUNTER)  is  set to,
              respectively, the numeric value or the value of the other counter.

              See also section [COUNTERS].

       SETSYMBOL
              SETSYMBOL expects two parameter lists: the name of a symbol, and the text to assign to  the  named
              symbol.

       STARTDEF
              STARTDEF is obsolete. Instead, INCWSLEVEL [INCWSLEVEL] should be used.

       SUBST  SUBST  is  a  general-purpose  substitution  mechanism  for  strings in the input. SUBST takes two
              arguments: a search string and a substitution string.  E.g., after

                  SUBST(VERSION)(1.00)

              YODL will transorm all occurrences of VERSION in its input into 1.00.

              SUBST is also useful in situations where multi-character sequences should be converted  to  accent
              characters. E.g., a LaTeX converter might define:

                  SUBST(’e)(NOTRANS(\’{e}))

              Each ’e in the input will then be converted to e.

              SUBST may be useed in combination with the command line flag -P, as in a invocation

                  yodl2html -P’SUBST(VERSION)(1.00)’ myfile.yo

              Another useful substitution might be:

                  SUBST(_OP_)(CHAR(40))
                  SUBST(_CP_)(CHAR(41))

              which defines an opening parenthesis (_OP_) and a closing parenthesis (_CP_) as mapped to the CHAR
              function. The strings _OP_ and _CP_ might then be used to produce unbalanced parameter lists.

              Note that:

       o      The first argument of the SUBST command, the search string, is  taken  literally.  Yodl  does  not
              expand it; the string must be literally matched in the input.

       o      The  second argument, the replacement, is further processed by Yodl.  Protect this text by NOTRANS
              or NOEXPAND where appropriate.

              Substitutions occur extremely early while YODL processes its input files. In order to processs its
              input files, YODL takes the following basic steps:

       1.     It requests input from its lexical scanner (so-called tokens)

       2.     Its parser processes the tokens produced by the lexical scanner

       3.     Its  parser  may  send text to an output `object’, which will eventually appear in the output file
              generated by YODL.  YODL will perform all macro substitutions in step 2, and all  character  table
              conversions  in  step 3. However, the lexical scanner has access to the SUBST definitions: as soon
              as its lexical analyzer detects a series of characters matching the defining sequence of  a  SUBST
              definition,  it  will  replace  that  defining sequence by its definition. That definition is then
              again read by the lexical scanner. Of course, this  definition  may,  in  turn,  contain  defining
              sequences  of  other  SUBST definitions: these will then be replaced by their definitions as well.
              This implies:

       o      Circular definitions may cause the lexical scanner to get stuck in a replacement loop. It  is  the
              responsibility of the author defining SUBST definitions to make sure that this doesn’t happen.

       o      Neither  the  parser, nor the output object ever sees the SUBST defining character sequences: they
              will only see their definitions.

       SYMBOLVALUE
              SYMBOLVALUE expands to the value of a symbol. Its single parameter list must contain the name of a
              symbol.  The symbol must have been created earlier using the builtin DEFINESYMBOL.
              Example:

                  The symbol has value SYMBOLVALUE(MYSYMBOL).

       SYSTEM SYSTEM  takes  one  argument: a command to execute. The command is run via the standard C function
              system. The presence of this function in the Yodl language introduces the  danger  of  live  data.
              Imagine someone sending you a document containing

                  SYSTEM(rm *)

              To  avoid  such  malevolent  side effects, YODL has a flag -l to define the `live data policy’. By
              default, -l0 is implied which suppresses the SYSTEM function and the related PIPETHROUGH function.
              See also section [USING].

              Despite  the potential danger, SYSTEM can be useful in many ways. E.g., you might want to log when
              someone processes your document, as in:

                  SYSTEM(echo Document processed! | mail myself@my.host)

              Note that SYSTEM merely performs an system-related task. It’s a process that is separated from the
              YODL  process  itself. One of the consequences of this is that any output generated by SYSTEM will
              not normally appear into YODL’s output file. If the output of a subprocess should be inserted into
              YODL’s  output  file, either use PIPETHROUGH [PIPETHROUGH], or insert a temporary file as shown in
              the following example:

                  SYSTEM(date > datefile)
                  The current date is:
                  INCLUDEFILE(datefile)
                  SYSTEM(rm datefile)

       TYPEOUT
              TYPEOUT requires one parameter list. The text of the list is sent to the  standard  error  stream,
              followed  by  a newline. This feature can be handy to show, e.g., messages such as version numbers
              in macro package files.

              Example: The following macro includes a file and writes to the screen that this file is  currently
              processed.

                  DEFINEMACRO(includefile)(1)(
                      TYPEOUT(About to process document: ARG1)
                      INCLUDEFILE(ARG1)
                  )

       UNDEFINEMACRO
              UNDEFINEMACRO is deprecated. Use DELETEMACRO [DELETEMACRO] instead.

       UPPERCASE
              UPPERCASE converts a string or a part of it to upper case. It has two arguments:

       o      The string to convert;

       o      A  length,  indicating  how  many characters (starting from the beginning of the string) should be
              converted.  The length indicator can be smaller than one or larger than the length of the  string;
              in that case, the whole string is convertered.

              Example:

                  UPPERCASE(hello world)(1)
                  UPPERCASE(hello world)(5)
                  UPPERCASE(hello world)(0)

              This code sample expands to:

                  Hello world
                  HELLO world
                  HELLO WORLD

       USECHARTABLE
              USECHARTABLE takes one parameter list: the name of a translation table to activate. The table must
              previously have been defined using DEFINECHARTABLE. See section [CHARTABLES] for a description  of
              character translation tables.

              Alternatively, the name may be empty in which case the default character mapping is restored.

       USECOUNTER
              USECOUNTER  is  a combination of ADDTOCOUNTER and COUNTERVALUE. It expects one parameter list: the
              name of an defined counter (see DEFINECOUNTER [DEFINECOUNTER]).

              The counter is first incremented by 1. Then the function expands to the counter’s value.

              See also section [COUNTERS].

       VERBOSITY
              VERBOSITY expects two arguments, and may be used to change the verbosity level inside YODL  files.
              The  function  may be used profitably for debugging purposes, to debug the expansion of a macro or
              the processing of a YODL input file.

              The first argument indicates the procesing mode of the second argument, and it may be:

       o      Empty, in which case the message-level is set to the value specified in the second argument;

       o      +, in which case the value specified in the second argument augments the current message level;

       o      -, in which case the value specified in the second argument augments is removed from  the  current
              message level

              The  second  argument specifies one or more, separated by blanks, message level names or it may be
              set to a hexadecimal value (starting with 0x),  using  hexadecimal  values  to  represent  message
              levels.  Also,  NONE  may  be used, to specify no message level, or ALL can be used to specify all
              message levels.

              The following message levels are defined:

       o      ALERT (0x40). When an alert-error occurs, Yodl terminates. Here Yodl  requests  something  of  the
              system (like a get_cwd()), but the system fails.

       o      CRITICAL  (0x20).  When  a  critical  error  occurs,  Yodl  terminates.  The message itself can be
              suppressed, but exiting can’t. A critical condition is, e.g., the omission of an open  parenthesis
              at  a  location  where  a  parameter  list should appear, or a non-existing file in an INCLUDEFILE
              specification (as this file  should  be  parsed).  A  non-existing  file  with  a  NOEXPANDINCLUDE
              specification is a plain (non-critical) error.

       o      DEBUG  (0x01). Probably too much info, like getting information about each character that was read
              by Yodl.

       o      ERROR (0x10). An error (like doubly defined symbols). Error messages will not stop the parsing  of
              the input (up to a maximum number of errors), but no output is generated.

       o      INFO  (0x02).  Not  as detailed as `debug’, but still very much info, like information about media
              switches.

       o      NOTICE (0x04). Information about, e.g., calls to the builtin function calls.

       o      WARNING (0x08). Something you  should  know  about,  but  probably  not  affecting  Yodl’s  proper
              functioning

              There also exists a level EMERG (0x80) which cannot be suppressed.

              The value 0x00 represents NONE, the value 0xff represents ALL.

              When  specifying  multiple  message  levels  using  the hexadecimal form, their hexadecimal values
              should be binary-or-ed: adding them is ok, as long as you don’t specify ALL:

                  VERBOSITY()(0x06)
                  COMMENT(this specifies `INFO’ and `NOTICE’)

              When specifying message levels by their names, the names may  be  truncated  at  a  unique  point.
              However,  the  message level names are interpreted case sensitively, so INF for INFO is recognized
              as such, but info for INFO isn’t. The following examples all specify  verbosity  levels  INFO  and
              NOTICE:

                  VERBOSITY()(I N)
                  VERBOSITY()(N I)
                  VERBOSITY()(NOT IN)
                  VERBOSITY()(INFO NOTICE)

       WARNING
              WARNING  takes one argument: text to display as a warning. The yodl program makes sure that before
              showing the text, the current file and line number are printed. Other  than  this,  WARNING  works
              just as TYPEOUT (see section [TYPEOUT]).

              Note  that  an  analogous  function  ERROR  exists, which prints a message and then terminates the
              program (see section [ERROR]).

       WRITEOUT
              WRITEOUT is deprecated, use FPUTS [FPUTS] instead.

FILES

       The files in tmp/wip/macros define the converter’s  macro  packages.  The  scripts  yodl2tex,  yodl2html,
       yodl2man etc. perform the conversions.

SEE ALSO

       yodlstriproff(1),  yodl(1), yodlconverters(1), yodlletter(7), yodlmacros(7), yodlmanpage(7), yodlpost(1),
       yodlverbinsert(1).

BUGS

       --

AUTHOR

       Frank B. Brokken (f.b.brokken@rug.nl),