|
Previous Next . Contents |
About . Documentation . License . Download |
All input characters that are not escape sequences are sent to the output if the output is active and discarded if the output is not active.
Every line starting with two successive hash marks is interpreted as a directive. Whitespace characters preceeding the hash marks are ignored. Directive lines can be continued by putting a backslash characters at the end of the line.
Before the directive line is parsed, variable references are resolved. However, @-escape sequences not forming a variable reference are not resolved at this stage. @-characters that are shadowed by a backslash character are not interpreted as the beginning or end of an @ escape. It is possible to quote a variable reference by preceeding the identifier with a colon.
For
The following example will define the macro FOO:
## define MyMacro macro FOO(X) ## @MyMacro@ X=@X@ ## endmacro |
However, the following will not work, since the
## define MyMacro macro FOO(X) ## define MyEndMacro endmacro ## @MyMacro@ X=@X@ ## ; This will NOT work! ## @MyEndMacro@ |
The dollar signs are used for mangling macro names and macro default parameters, and should be used for that purpose only. However, P18 does not enforce this.
Even though it is possible to use the names true and false (case is insignificant here), you probably don't want to do this, since these identifiers could not be used within an expression (see below).
A string value is represented by a string constant, which is a sequence of characters enclosed in a pair of double quotes ("). The string constant syntax is similar to the ANSI C string constant syntax, all backslash-escaped special characters valid in ANSI C are also valid in P18 string constants.
When defining a variable using the
When an expression is evaluated in a boolean context (either as a condition or as a part of a larger expression), then every value is read as TRUE, except for an undefined value and the boolean value FALSE. This means that an identifier in a boolean context evaluates to TRUE if and only if the variable is defined, since boolean values can't be bound to variables.
Here's the expression grammar in BNF:
| Expression: | |
|
EqualityExpression OrExpression | |
| EqualityExpression: | |
|
PrimaryExpression = PrimaryExpression PrimaryExpression != PrimaryExpression | |
| OrExpression: | |
|
AndExpression OrExpression | AndExpression OrExpression ^ AndExpression | |
| AndExpression: | |
|
UnaryExpression AndExpression & UnaryExpression | |
| UnaryExpression: | |
|
PrimaryExpression ! UnaryExpression | |
| PrimaryExpression: | |
|
( Expression ) StringConstant TRUE FALSE Identifier | |
The following binary operators are recognized:
The boolean constant values TRUE and FALSE are represented by the case-insensitive character sequences true and false. This means that variables bound to identifiers true or false (or FaLSe...) can't be referenced from within an expression. Avoid using such identifiers.
## if FOO == "foo" ; This is the magic "foo" case. ... ## endif ; End of the magic "foo" case. |
Description:
This directive must be used before the first non-whitespace character is sent
to the output. If the specified expression evaluates to FALSE,
then no output file is generated (i.e. the output is sent to
/dev/null). However, the input file is processed anyway.
Description:
Include the specified file. The contents of the file are read and inserted
into the input stream. The filename may be specified in C syntax or
without any delimiters. If the filename is specified without delimiters,
everything starting from the first non-whitespace character to the end of the
line is interpreted as the filename. Note that the
It is also possible to specify the filename using quoting characters as delimiters. In addition to the standard quoting characters singlequote (') and doublequote ("), the filename may also be quoted in angle brackets (i.e. the less-than and greater-than signs, < and >). Note that in contrast to the standard C preprocessor, all methods of quoting the filename are equivalent.
Description:
Mark the beginning of a conditional block. If the specified expression
evaluates to TRUE, then the initial condition of the block is TRUE (i.e. the
output is active if the conditions of all surrounding conditional block are
TRUE). If the expression evaluates to FALSE, then the initial condition of
the conditional block is set to FALSE (i.e. the output is deactivated).
Description:
This directive may appear only inside of a conditional block. For variant (a)
the condition of the inner-most conditional block is inverted. For variant
(b), if the condition of the inner-most conditional block is TRUE, it is set
to FALSE (unconditionally), if the condition is FALSE, it is set to the
evaluation result of the specified expression. (In plain english,
Technically, there's no reason why one should not have an arbitrary number of
Description:
Mark the end of a conditional block.
Description:
Define a variable or macro named name. If the value parameter
is omitted, the variable is defined to an empty string (which evaluates to
TRUE in a boolean context, see section
Expressions). The
If a value parameter is specified, the parameter is expected to be a
string constant value (see section Values). If the
value does not start with a double quote, the value is the entire string from
the first non-whitespace character following the name parameter up to
(but not including) the next newline character. If the value is not written
as a string constant, the
Note that lines continued with a trailing backslash character are interpreted as a single line.
Description:
Un-define a variable or macro. The
Variant (a) un-defines the nemed variable and all variables associated with
the specified name. A variables is associated with the specified name, if the
name of that variable starts with the specified name followed by a dollar
sign. Use variant (a) to remove a defined macro and all its default
parameters. Variant (b) only un-defines the variable with the exact name
specified. It is not an error if the specified variable or macro is not
defined, the
Description:
Define a variable or macro. Variant (a) is just a multi-line version of
The parameter list is a non-empty list of comma separated simple identifiers (identifiers not containing a dollar sign). The last of these identifiers may be preceeded by an ellipsis (three successive dots, "..."), indicating a variable argument list. The identifiers in the parameter list define the names of the parameters, arguments passed to the macro are available as variables bound the corresponding parameters names in the context of the macro expansion.
For every parameter. a default value may be specified. The default value is written behind the parameter name, separated by an equal sign (=). When the macro is called and an argument for a parameter with a default value is omitted, the specified default value is used in place of the omitted argument.
An example for a macro definition:
## macro FEATURE(feature = "NONE") ## if ENABLE_@feature@ || feature == "NONE" ## endmacro ## macro FEATURE_END ## endif ## endmacro |
The macro body is everything up to the next
When referencing a parameter passed to a macro, care should be taken if the argument text passed through the parameter should be parsed again. E.g. if an argument text might contain an I18N escaped, the parameter should be referenced as a macro, not as a variable. Here is an example:
## macro ITEM(title, text, link = "NONE") <li> ## if link == "NONE" <b><u>@title()@</u></b> ## else <a name="@link@"><b><u>@title()@</u></b></a> ## endif <br> @text()@ </li> ## endmacro |
Description:
Mark the end of a macro definition. People with a healthy brain will probably
only need variant (a) of this directive. The counter parameter in
variant (b) determines for how many expansions the directive should be
ignored, i.e. when the directive
Variant (b) is useful if you want to define a macro which in turn defines a macro when expanded. Counter values larger than 1 are probably hardly useful, but I am sure that someone, somewhere will define a macro, which defines a macro, which defines a macro...
For both variants, the name of the macro may be specified through the optional parameter name. If the name parameter is specified, it must match the name of the macro.
Description:
Delete the newline character preceeding the
Example:
## if some_condition foo ## dnl ## endif bar |
Description:
Enforce a variable substitution on the specified text argument text.
If the counter argument counter is 0, then the directive
is replaced by the specified text. If the counter argument is positive, the
directive is replaced by an equivalent
The
Note: The parameter text is an arbitrary sequence of
characters, possibly containing semicolons. As a consequence, the
Description:
Mark the beginning of a mute block. Within a mute block, all variable and
macro definitions take effect, but the preprocessor output is discarded.
Mute blocks are useful for include files defining a set of variables and
macros.
Mute blocks can be nested. The
Description:
Mark the end of a mute block. The
## macro LINK(link, text, frame = "NONE") <a href="@link()@" ## dnl ## if frame != "NONE" target="@frame()@" ## dnl ## endif >@text()@</a> ## endmacro |
## macro LINK(link, text, frame = "NONE") <a href="@link()@" ##+if frame != "NONE" target="@frame()@" ##+endif >@text()@</a> ## endmacro |
In all block end directives (i.e.
The grammar for variable and macro references in BNF:
| VariableReference: | |
| @ Identifier @ | |
| MacroReference: | |
|
@ SimpleIdentifier
( MacroArgumentList ) @ @ Identifier () @ | |
| MacroArgumentList: | |
|
MacroArgument MacroArgumentList , MacroArgument | |
An Identifier is a sequences of alphanumeric characters, underscores,
and dollar signs. A SimpleIdentifier is a sequences of alphanumeric
characters and underscores. Both Identifier and
SimpleIdentifier may not start with a digit. A MacroArgument
is an arbitrary sequence of characters not containing an unquoted comma or
closing parenthesis. Note that for MacroArgument all whitespace is
significant, i.e. the escape "
The expanded text of a variable reference is sent to the output, while the expanded text of a macro reference is pushed back to the input stream and is parsed again.
The arguments passed to a macro are separated by unquoted commas and terminated by an unquoted closing parenthesis. If an argument contains a comma or a closing parenthesis, the comma or parenthesis has to be quoted by a preceeding backslash character. Before the arguments are assigned to the parameter variables, one level of quoting is removed (i.e. you may use all standard quoting sequences to quote characters).
If the called macro is defined with a variable argument list, then the last parameter receives the unassigned rest of the argument list. Example:
## macro varargs(arg1 = "ARG1", ...arg2 = "ARG2") arg1="@arg1@"; arg2="@arg2@" ## endmacro 1: @varargs()@ 2: @varargs(X)@ 3: @varargs(X,)@ 4: @varargs(X, Y, Z)@ |
1: arg1="ARG1"; arg2="ARG2" 2: arg1="X"; arg2="ARG2" 3: arg1="X"; arg2="" 4: arg1="X"; arg2=" Y, Z" |
Note: If a macro is expanded, the beginning of the
macro body will be treated as if it was on the beginning of a line. This
makes it possible to start a macro with an
## macro A(b) b=@b()@ ## endmacro @A(##\\## something)@ @A(## something)@ |
The syntax for I18N escapes is described by the following grammar:
| I18NEscape: | |
|
_( Message )_ _( Message) MessageArgumentList _ _( Message) MessageOptionsExtension _ _( Message) MessageOptionsExtension MessageArgumentList _ | |
| MessageOptionsExtension: | |
| [ MessageOptions ] | |
| MessageOptions: | |
|
LanguageID LanguageID / MessageType / MessageType | |
| MessageArgumentList: | |
|
{ MessageArgument } MessageArgumentList {MessageArgument} | |
A Message is a sequence of characters not containing an unquoted closing parenthesis. A LanguageID is a language identifier, as described in section Language Identifiers. A MessageType is a message type identifier as described in section Message Types. A MessageArgument is a sequence of characters not containing an unquoted closing brace (}) and not starting with an unquoted dollar sign (the dollar sign at the beginning of a message argument is reserved for future extensions).
For the parameter MessageOptions all variable references are resolved, before the parameter is split into LanguageID and MessageType. The Message and all MessageArguments are passed through a normalization step. This normalization step is described in section Message Normalization. A Message may contain a variant specifier, as described in section Message Variants.
What happens when a message is perocessed depends on the operation mode of P18 (see section Invocation):
In the translated message, references to message parameters are resolved by substituting the parameter references with the specified message arguments. A parameter reference is an unquoted dollar sign ($) followed by a sequence digits forming the parameter number. The parameter number may be enclosed in curly braces, which is useful in case the parameter reference is followed by a digit. While resolving the parameter references, one level of quoting is removed from the message text.
Example:
## define OPT "en/HTML"
<head>
<title>_(The Book of Yendor)[@OPT@]_
##+
- _(Chapter $1, Section $2)[@OPT@]{<?=$chapter?>
}{<?=$section?>}_</title>
</head>
|
By default the expanded I18N escape is prepended with a quoting directive and pushed back to the input for reparsing (you can change this by using a preput extension, see below). The quoting directive is prepended to avoid expanded messages starting with a double-hash to be interpreted as a directive.
<< and >>. The text enclosed within
these delimiters is prepended to the translated message instead of a quoting
directive. You may also specify an empty preput extension, causing the
translated message to be interpreted as a directive if it starts with a
double-hash.
Example:
_<<## define FOO >>(BAR)_ |
BAR is bound to the variable
FOO. Note that translated messages are normalized
(see Message Normalization),
so if the translated message does not contain quoted newline characters, the
entire message text is bound to the variable FOO. However,
you will run into problems if the translated message starts with a quoting
character or contains quoted newline characters.
|
Previous Next . Contents |
About . Documentation . License . Download |