CML Reference Guide

Chapter 5:  CML Directives


CML pages are like mini-programs.  They contain directives which control which lines of HTML code will actually get sent to the browser, or control how many times a set of HTML lines will be evaluated. 

The directives are:
  1. For
  2. Count
  3. While
  4. If
  5. Elif
  1. Else
  2. Set
  3. Copy
  4. Include
  5. Return
  1. Quit
  2. Break
  3. Continue
  4. Eval
Plus an "end" directive, that closes the "for", "count", "while", "if", "elif", and "else" directives.


5.1 For

The CML "for" loop evaluates a set of lines multiple times.  It looks like:

     for variable1 [variable2 ... ] in list
          (HTML code or other CML directive code)

where variable1, variable2 etc. are names, and list is a list of words or values.  Typically list may be the result of a CML function.  The for loop evaluates the lines between "for" and "end", substituting the words in list as the values of variable1, variable2, etc.  (The brackets simply mean that variable2, etc. are optional.  The brackets would not actually appear in the syntax of the for loop.)

For example, the loop:

     for x in abc qrs xy

will evaluate the lines between "for" and "end" three times, using each word in list.  (If there are no words, the lines will be skipped.)  The first time through the loop, x will have as its value "abc".  The second time it will have the value "qrs", and so on.

A different example shows the use of multiple variables:

     for one two in alpha beta delta gamma

The first time through the loop, one will have the value "alpha" and two will have the value "beta".  The second time, one will have the value "delta", and so on.

The indenting of each line as shown above is not necessary, but it is a good idea.  It helps make the CML code much more readable.


5.2 Count

The CML "count" loop is similar to the "for" loop.  It looks like:

     count variable x y
          (HTML code or other CML directive code)

where variable is a name, and x and y are numeric values or expressions.  The count loop will evaluate the lines between "count" and "end" one time for each integer value between x and y, inclusive.  The first time, variable will have the value x.  Then x+1, and so on, up to and including y.  If y is less than x, the lines will be skipped entirely.


5.3 While

The CML "while" loop is perhaps the simplest loop control directive.  It has the form:

     while expression
          (HTML code or other CML directive code)

The "while" loop evaluates expression, and examines the first word of the result.  If it is a number, not equal to 0, all of the lines between "while" and "end" are evaluated.  The loop then repeats, re-evaluating expression, and so on.  The "while" loop will continue to execute as long as expression is non-zero, so be careful!


5.4 If

The CML "if" statement evaluates a set of lines if a certain condition is true.  It looks like:

     if condition
          (HTML code or other CML directive code)
where condition is some expression.  If there is at least one word in condition, and the first word is a non-zero number, then the enclosed set of lines will be evaluated once.  Otherwise they will be skipped.  (Also see the related functions $if() and $ifthen().)


5.5 Elif

The "if" statement may be extended to handle multiple exclusive cases with the "elif" directive.  It looks like:

     if condition1
          (HTML code or other CML directive code)

     elif condition2

The lines between "elif" and "end" are evaluated when the previous "if" condition1 failed (was 0 or did not exist) and the first word of condition2 is a non-zero number.

Multiple "elif"s may be strung together, one after another.  Only one of the blocks of CML code between the if/end and elif/end pairs will be executed.


5.6 Else

There is an (optional) matching "else" to the CML "if" and "elif" statements.  It looks like:

     if condition
          (HTML code or other CML directive code)


The lines between "else" and "end" are evaluated if condition is 0, or does not exist at all.  Note: the "if" must have its own "end"!  "Else" may be used with just an "if", or a series of "if"s and "elifs".  If the latter, it must be the last of the series.


5.7 Set

The "for" and "count" directives define the value of a variable during iterations of the lines between the "for" or "count", and the matching "end" directive.  Outside of those loops, the variable is undefined.

A variable may also be defined across the evaluation of all CML pages, using the "set" directive.  It looks like:

     set variable x
where variable is a name (or an expression that evaluates to a name), and x is some expression.  For the rest of this session, variable has the value x (unless changed by another "set" directive).  Variables defined by "set" are considered "global" in scope, i.e. the variables are available in all subsequently evaluated CML pages.

(Also see the related function $set().)


5.8 Copy

The Copy directive is identical to the Set directive, except that it preserves leading spaces (after the one space required to separate the directive from the expression).  Spaces, in this context, include blanks, tabs, newlines, and Kanji double-wide spaces.

For example, if the "struck-out" letter b represents a space, then

   set  abcbbbhello
   copy xyzbbbgoodbye

sets abc to "Hello", and xyz to "bbgoodbye".


5.9 Include

The "include" directive includes the text of a CML file at the current point.  It has the syntax:

     include filename  [ arg1 [ arg2 ... ] ]

where filename is the name of a file, or a set of CML functions that evaluate to the name of a file.  Filename is relative to the CML_Path directory specified in the swebd.conf file.  (See the Caucus installation guide for details.)  The brackets indicate that arguments arg1, arg2, and so on are optional (they are not actually part of the syntax).  If the arguments are present, they are available inside the included file via the $inc(n) function.

Include directives are evaluated according to the current context.  For example:

     count x 1 3
          include file.$(x)

would include the contents of the files file.1, file.2, and file.3.

Include understands the "quoting" of multiple words as one arg.  See $quote() for details.


5.10 Return

The "return" directive immediately "returns" from the current CML file or CML include file.  When encountered in a CML file, it terminates processing of that file, as if it had "run off the end" of the file.  If encountered in an included file, it immediately "returns" to the including file, and continues with the line after the include directive.

Return is particularly useful in CML include files that handle multiple conditions.  Return can be used to say "I'm done with this section", rather than use if/else if combinations to exclusively handle different conditions.  For example:

     if condition 1
        do something

     if condition 2
        do something else

A return in a main CML file has the same effect as a quit.


5.11 Quit

The "quit" directive immediately ceases processing of the current page, whether in a main CML or an include file.  No more processing is done of that file, or any file that may have "included" the file.

It is particularly useful in CML pages that need to handle special case or "error" conditions.  For example:

     if some "error" condition

     #---OK, go on with the main case here...
     "Content-type: text/html



5.12 Break

The "break" directive immediately exits the innermost "for", "count", or "while" loop, and continues execution of the CML script after the closing "end" of that loop.


5.13 Continue

The "continue" directive immediately starts the next iteration of the innermost containing "for", "count", or "while" loop.


5.14 Eval

The "eval" directive simply evaluates any CML functions on the rest of the line.  Any results from the evaluation are ignored (thrown away). 

Eval is really just a more straight-forward way of saying "set ignore some_function".