Provided by: yodl_4.02.02-2_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.

       `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 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 `PUSHSUBST’ built-in function (see section `[PUSHSUBST]’);

       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]’);

       o      The  `XXSUBST’ internal use only built-in function; 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 arguments: the counter
              name, and an additive expression defining the value to add. The counter must be previously created
              with `DEFINECOUNTER’.

              The  additive  expression may not contain blank spaces and may use + and - operators, its operands
              may either be integral numeric values or names of (defined) counters.  The resulting value can  be
              negative; in that case, a value is subtracted from the destination counter.

              For example, if `one’ and `two’ are counters, then

                  ADDTOCOUNTER(one)(-two)\//    subtracts two’s value from one
                  ADDTOCOUNTER(one)(two+two)\// adds 2 x two’s value to one

              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 adds 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’ expects one argument. The argument 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 requirement that open- and close-parentheses must match.

              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’ searches 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 defines one parameter list. The text that is passed as argument is treated
              as comment. I.e., it is ignored; it is not copied to the final output file.

              As an alternative to (short) `COMMENT’ the triplet `\’`//’ can be used. It starts  `end  of  line’
              comment, ignoring all characters on a line starting at `\’`//’ up to the first non-blank character
              encountered on the next line. If the next line’s first non-blank characters are `\’`//’, then that
              begins another end of line comment, which will therefore also be skipped.

              To  actually  write  `\’`//’  or, using the current font: \// in a yodl-converted document, write,
              e.g., `tt(\)tt(//)’ or, using the  current  font:  nop(/)//  in  a  yodl-source  file,  and  write
              `\CHAR’`(/)/’ in `verb’ sections.

              Example:

                  Hello world\// producess Hello world, skipping the rest
                      \// this line is completely ignored
                     s\// at this point Hello worlds has been produced.

       `COUNTERVALUE’
              `COUNTERVALUE’s’  argument expands to the value of a counter. Its single argument 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)  argument.   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 is 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
              effectively is 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  backslash  character  (`\’)  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. This builtin function expects two arguments: the name of
              the counter and an additive expression whose value is used to initialize the counter.

              The additive expression may not contain blank spaces and may use + and - operators,  its  operands
              may  either be integral numeric values or names of (defined) counters.  The resulting value can be
              negative; in that case, a value is subtracted from the destination counter.

              Examples:

                  DEFINECOUNTER(year)(1950)
                  DEFINECOUNTER(nTimes)(year+12)\// initializes nTimes to 1962

              See also section `[COUNTERS]’ and the `USECOUNTER’ and `ADDTOCOUNTER’ builtin functions.

       `DEFINEMACRO’
              `DEFINEMACRO’ is used to define new macros. This function expects three arguments:

       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 it’s used.  The  number
              must be in the range 0 to 61.

       o      The  text  that the macro expands to, once used. This text may contain the strings `ARG’x, x being
              1, 2, etc.. At these places the arguments to the macro are 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 values of the three arguments are pasted to the places  where  `ARG1’,
              `ARG2’ etc. occur in the definition.

              Note the following when defining new macros:

       o      The  argument  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 argument.

              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 are 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 argument  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()
                  )

              when called as `oops(hello world)’, produces 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’s arguments 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 arguments.

       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 arguments are read from the input

       o      The  contents  of the arguments then replace their `ARGx’ references in the macro’s definition (in
              some exceptional cases, clearly indicated as such when applicable, the  arguments  themselves  are
              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 happens:

       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 puts  (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 puts 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’
              `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 argument,  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)

       `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 argument 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 `book’s or `report’s).

              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 displays  the  counter’s  value,  after  having
              incremented it:

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

              Here, `EVAL’ performs the following steps:

       o      First, `NOTRANS(USECOUNTER)’ is evaluated, producing `USECOUNTER’.

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

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

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

       o      All this results in the text

                  USECOUNTER(counter)

       o      This  text  is  presented  to  Yodl’s  lexical scanner, resulting in incrementing the counter, and
              displaying its incremented value.

              b(Caveat): macro arguments themselves are usually not evaluated. So, a construction like

                  USECOUNTER(EVAL(SYMBOLVALUE(varnam)))

              fails, as ``EVAL(SYMBOLVALUE(varnam))’’ is not a legal name for a counter. Here the `EVAL()’  call
              is used as an argument, and is therefore not expanded.

              The  distinction  is  subtle,  and  is  a  consequence  of the fact that builtin functions receive
              unprocessed arguments. Builtin functions may impose certain requirements on their arguments  (like
              `USECOUNTER’  requiring the name of a counter) and these requirements are checked on the arguments
              as received.

              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.

              Most  built-in  functions  do  not  evaluate  their  arguments. In fact, only `ERROR, EVAL, FPUTS,
              INTERNALINDEX,  PUSHSUBST,  TYPEOUT,  UPPERCASE,  WARNING’  and  the  iinternally  used  `XXSUBST’
              functions 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)

              produces  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 define variables using
              values  of other variables?’ In those cases `EVAL()’ must be used. The following example shows the
              definition of three symbols: `one’ receives an initial value, `two’ returns `one’’s  actual  value
              when `two’’s value is displayed, `three’, using `EVAL()’, stores `one’’s initial value.

              The  example  also shows yet another way to suppress macro calls, using the macro `nop()’ which is
              defined in the all standard conversion types:

                  DEFINESYMBOL(one)(One’s first value)
                  DEFINESYMBOL(two)(SYMBOLVALUE(one))
                  EVAL(DEFINESYMBOL+nop()(three)(SYMBOLVALUE(one)))
                  SETSYMBOL(one)(One’s second value)
                  "SYMBOLVALUE(two)"      COMMENT(displays "One’s second value")
                  "SYMBOLVALUE(three)"    COMMENT(displays "One’s first value")

       `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 argument 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 appends 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 argument is evaluated, else, the third argument is evaluated. All  three  arguments
              (the  variable, the true-list and the false-list) must be present; though the true-list and/or the
              false-list may be empty.

              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
              argument is evaluated, else, the third argument is evaluated. All three arguments (the  name,  the
              true  list  and the false list) must be present; though the true list and/or the false list may be
              empty.

              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 argument. If  it
              is  a defined entity, the second argument is evaluated, else, the third argument is evaluated. All
              three arguments (the entity, the true list and the false list) must be present;  though  the  true
              list and/or the false list may be empty.

              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 argument is evaluated, else, the fourth argument is evaluated. All four
              argument lists must be present, though all can be empty.

              The first two arguments of `IFEQUAL’ should be integral numeric 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 determines
              whether the true list (when the values are equal) or the false list (when the values are  unequal)
              will be evaluated.

       o      Otherwise, `IFEQUAL’ evaluates 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 than its
              second argument. If so, the third parameter list is evaluated, otherwise its  fourth  argument  is
              evaluated. All four argument lists must be present, though all can be empty.

              The first two arguments of `IFGREATER’ should be integral numeric 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
              determines  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) is evaluated.

       o      Otherwise, `IFGREATER’ evaluates 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 argument is evaluated, else, the third argument is evaluated. All
              three arguments (the name, the true list and the false list) must be present; though the true list
              and/or the false list may be empty.

              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 than its
              second argument. If so, the third parameter list is evaluated, otherwise its  fourth  argument  is
              evaluated. All four argument lists must be present, though all can be empty.

              The first two arguments of `IFSMALLER’ should be integral numeric 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
              determines  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) is evaluated.

       o      Otherwise, `IFSMALLER’ evaluates 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 argument is evaluated, otherwise the third argument is evaluated. All
              three arguments (the name, the true list and the false list) must be present; though the true list
              and/or the false list may be empty.

              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.

              C(  FBB consider additive expressions   )

       `IFZERO’
              `IFZERO’  expects  three  arguments. If the first argument is zero (0) the function expands to the
              true list (the second argument). Otherwise it expands to the false list (the third argument).

              The first argument of `IFZERO’ should be an integral numeric 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, the first arguments evaluates as 0, and the false list is used.

              Note   that,   starting   with  Yodl  version  2.00  the  first  argument  is  not  evaluated.  So
              `COUNTERVALUE(somecounter)’ always evaluates 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.

              Example:

                  INCLUDEFILE(latex)

              Here,  Yodl attempts to include the file `latex’ or `latex.yo’ from the current include path. When
              the file is not found, Yodl aborts.

       `INCWSLEVEL’
              `INCWSLEVEL’ requires one (empty) argument.

              It increments 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
              is generated if the file produces non-whitespace output. The builtin function `DECWSLEVEL’ is used
              to decrement the whitespace level following a previous `INCWSLEVEL’ call.

              Once the white space level exceeds zero,  no  output  is  generated.  White  space,  therefore  is
              effectively  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  greater processing speed, at the expense of an additional file. The
              associated `yodlpost’ postprocessing program reads and processes the index file, and modifies  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’ changes  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 thereupon writes 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.

       `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  argument,  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’ and (iinternally used) `XXSUBST’ functions in the argument, which are expanded.
              If `CHAR’-expansion is not required either NOTRANS `[NOTRANS]’ can be used).

              Furthermore, the contents of the argument 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 sense 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 `ARG’x 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 argument. 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.

              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 is not affected by available 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.

              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 is not affected by available 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’ sends

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

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

              The  argument  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 `)’.

              While converting Yodl-documents to target document types Yodl frequently  uses  the  (not  further
              documented) builtin function `XXSUBST’. In the unlikely event that the text `XXSUBST(...)’ must be
              written in a document, the sequence

                  XXSUBST+CHAR(40)...CHAR(41)

              can be used.

              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, warnings are generated when Yodl encounters a possible macro name, i.e.,
              a name that is followed by a parenthesized argument, while no macro by that name has been defined.
              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 argument.

              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 Yodl handles paragraphs in a special way it is
              probably  useful  to  describe  paragraph  handling  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 calls it whenever  a  new  paragraph  (defined  as  a
              series of at least two blank lines) has been 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 contains
              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 does 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  do
              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. `PIPETHROUGH’ can be very useful. It uses an external program
              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 is 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, after which its stack is empty. In that case,
              using the macro (although the macro’s name is still defined) 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)

       `POPSUBST’
              `POPSUBST’ is used to revert to a previous level of interpretation of `SUBST’  definitions.  Refer
              to the descriptions of the `PUSHSUBST’ and `SUBST’ builtin commands below for details.

              There is no limit to the number of times `POPSUBST’ can be called. Once the ``PUSHSUBST’ stack’ is
              empty `SUBST’ definitions are automatically interpreted  (so  no  stack-underflow  error  is  ever
              encountered).

       `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, after which its stack is empty.  In  that  case,
              using the symbol (although the symbol’s name is still defined) 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, emptying the stack, 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 an additive expression
              whose value becomes the counter’s new value (after pushing the current value)

              The additive expression may not contain blank spaces and may use + and - operators,  its  operands
              may  either be integral numeric values or names of (defined) counters.  The resulting value can be
              negative; in that case, a value is subtracted from the destination counter.

              When the second argument is empty, then the new value will be  zero.   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)

       `PUSHSUBST’
              `PUSHSUBST’  can  be used to (temporarily) suppress the interpretation of `SUBST’ definitions (the
              `SUBST’ built-in command is covered below, refer to its description for an example).

              `PUSHSUBST’ expects one argument: an integral number which is either 0 or non-zero (commonly:  1).
              After calling `PUSHSUBST’`(0)’ `SUBST’ definitions are not interpreted anymore; use `POPSUBST’`()’
              to revert to the previous type of interpretation. Alternatively, `PUSHSUBST’`(0)’ can be  used  to
              stack another level of `SUBST’ interpreations on top of the last-used one.

              On  a  64-bit  computer the `PUSHSUBST’ stack can hold slightly more than 60 `SUBST’ interpreation
              levels. When more levels are pushed, the oldest levels are silently forgotten. Calling  `POPSUBST’
              once  the  `PUSHSUBST’  stack is empty results in activating the `SUBST’ interpretations (and so a
              stack-underflow error will not be encountered).

       `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 text after pushing.
              When the second argument is an empty argument, the new text will be empty. The  new  text  may  be
              specified  as a literal text, 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
              case 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 arguments: the name of a counter, and an additive expression defining the
              value to assign. The counter must be previously created with `DEFINECOUNTER’.

              The  additive  expression may not contain blank spaces and may use + and - operators, its operands
              may either be integral numeric values or names of (defined) counters.  The resulting value can  be
              negative; in that case, a negative value is assigned to the destination counter.

              For example, if `one’ and `two’ are counters, then

                  SETTOCOUNTER(one)(-two)\//    assigns -two’s value to one
                  SETTOCOUNTER(one)(two+two)\// assigns 2 x two’s value to one

              See also section `[COUNTERS]’.

       `SETSYMBOL’
              `SETSYMBOL’  expects  two  arguments:  the  name  of a symbol, and the text to assign to the named
              symbol. The symbol must previously have been defined by `DEFINESYMBOL’.

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

                  SUBST(VERSION)(1.00)

              YODL transforms all occurrences of `VERSION’ in its input into `1.00’.

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

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

              Each `’e’ in the input will subsequently 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 arguments.

              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 process its
              input files, YODL takes the following 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  eventually  appears  in  the  output  file
              generated  by  YODL.   YODL  performs  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 replaces 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 are then 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
              only see their definitions.

              In some cases substitutions must be suppressed. Consider  double  quoted  text  strings  that  are
              frequently used in programming languages. E.g., `"hello world"’. The text inside the string should
              not be converted by Yodl, but unless substitutions can be suppressed the string
              "\"evil code"

              appears as
              "evil code"

              To suppress the interpretation of `SUBST’ definitions  `PUSHSUBST’,  introduced  earlier,  can  be
              used. The predefined macro `verb’ suppresses the interpretation of `SUBST’ definitions by starting
              with `PUSHSUBST’`(0)’ and ending with `POPSUBST’`()’.

       `SYMBOLVALUE’
              `SYMBOLVALUE’ expands to the value of a symbol. Its single argument must be the name of a  symbol.
              The symbol must have been created earlier using `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’.

              `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’
              not  normally  appears  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  argument.  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)
                  )

       `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 argument: 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  argument:  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  parenthesized  argument  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]’).

FILES

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

SEE ALSO

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

BUGS

       --

AUTHOR

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