The Definition File

The definition file is used to tell Fern which HTML syntax problems to check for, and what messages to display. The definition file consists of variables, conditionals, rules, and settings.

The definition file is text-based and can be edited with any standard text editor. Special formatting text editors, such as WordPerfect or Microsoft Word, should not be used to edit the definition file.


Variables

Fern uses "variables" to store common values. To definite a variable in the definition file, you use the "define" keyword.

syntax: define variable value
example: define hello Howdy
define error Error: there appears to be a problem

Variables can consist of letters, numbers, and the symbols underscore, tilda, and period:

ABCDEFGHIJKLMNOPQRSTUVWXYZ
abcdefghijklmnopqrstuvwxyz
0123456789
_~.
The variable name is case-sensitive. Thus, the variables "Hello" and "hello" have different values. By default, all variables are undefined.
Value
The value is any text string and can contain any character including spaces. For formatting reasons, there is one special character: "\". Characters after the "\" have special meaning:

\na new-line character -- same as pressing "enter" or "control-M"
\ra return character -- same as pressing "control-J"
\ta tab character
\aan alarm (bell) character -- same as pressing "control-G"
\(any other character)the character following the back-slash
This is refered to as a "quoted character" because the character is interpreted as it's literal meaning. For example:
\# is a pound-sign. Normally, "#" is used to denote a comment.
\\ is a back-slash. Normally, "\" is the quoting character.
\$ is a dollar-sign. Normally, "$" is the quoting character.

Please note, unlike Unix programming, a "\" at the end of a line does not continue the text on the next line.

Including variables
Variables are used by conditionals, rules, and as values in other definition statements.

To use a variable as a value, enclose it in "${" and "}". For example:

define error An error has occurred 
define problem ${error} and it's a problem
define oh_no Oh, no! ${problem}\n
This sets the value of ${error} to "An error has occurred" and the value of ${problem} to "An error has occurred and it's a problem". The value of ${oh_no} is defined as "Oh, no! An error has occurred and it's a problem" followed by a new-line.

The value of a variable is not interpreted until it is used by a conditional or a rule. To prevent infinite looping when it is interpreted, rules can only be nested (or self-referenced) up to 8 times. For example:

define many_very very ${many_very}
The value of ${many_very} is "very very very very very very very very".

Variables may be defined multiple times. Only the last definition is used. Since a variable's value may include other variables and is only interpreted when used, the final value will only include the last definition.

System variables
In addition to the user-defined variables, there are a few system variables. The system variables keep track of the HTML document and rules. These variables consist of a dollar-sign and a single character.

$0The tag that triggered the rule.
$1The first parameter of the rule.
$2The second parameter of the rule.
$lThe current line number. This is the line number where the rule was found. Please note: if a rule was triggered at the end of a line, then this number will be the next line.
$bThe number of beginning tags associated with $0.
$eThe number of ending tags associated with $0. Please note, some rules may change the value of $e.
$nThe self-"nesting" of the tag $0. A nested tag is when there are multiple "begin" tags before an "end" tag. For example: <ol> $n of tag "ol" is "0".
<li> item 1
<ol> $n of tag "ol" is "1" -- it is one deep.
<li> item 1 subitem 1
<li> item 1 subitem 2
</ol> $n of tag "ol" is "1" -- it is one deep.

<li> item 2
</ol> $n is zero again.
$UThe URL. This is only defined when the setting "PROCESS URL TRUE" is used.

Command-line variables
In addition to within the definition file, variables can be defined on the command-line. To define a variable on the command-line, include:

variable=value

Please be aware that the command-line interpreter may try to give a different meaning to characters such as spaces, "&", and quotes (" and '). In addition, Unix shells may interpret "$" and "\", while DOS will interpret "%".

Variables specified on the command-line over-ride "define" statements in the definition file. To follow the previous example, adding "many_very=once" to the command line sets the value of ${many_very} to "once".

Undefined variables
Variables can be "undefined" two ways:
  1. Undefined in the definition file. This is done by not specifying a value. "DEFINE many_very" undefines the variable ${many_very}.
  2. Undefined on the command-line. This is done by not specifying a value. "many_very=" undefines the variable ${many_very}. Undefining a variable on the command-line prohibits the definition file from defining the variable.
Note: system variables cannot be undefined.

Conditionals

Conditionals allow Fern to include some parts of the definition file and exclude other parts.

Each conditional is denoted by one of four keywords: "if", "else", "else if", and "endif". For the "if" and "else if" keywords, defined variables and operators are used to determine the conditional's value.

The part of the definition file between the "if" and matching "endif" is called the conditional block. Within the conditional block may be many conditional areas, defined as the part of the definition file between the conditional keywords. No more than one conditional area within a conditional block will be interpreted.

if query1 begin the conditional block
(some defines)
(some rules)
the first conditional area
else if query2 define an alternate conditional area
(some more defines)
(some more rules)
the second conditional area
else define an alternate conditional area
(and more defines)
(and more rules)
the third conditional area
endifend the conditional block

The syntax for the conditional keywords is fairly straight-forward.

keyword syntax Example Purpose
if query if var1 The "if" keyword begins a conditional block.
  • When the values of the query evaluates to a "TRUE" result, the conditional area following the "if" is read by Fern. When another keyword is found (denoting the end of the conditional area), Fern jumps to the end of the conditional block.

  • When the query evaluates to "FALSE", the conditional area after the "if" is ignored by Fern.
else if query else if var2 The "else if" keyword denotes an alternate conditional area. The "else if" is always found after an "if" keyword, or after another "else if" keyword.

Use of the "else if" keyword is optional within the conditional block.

When the previous "if" (or "else if") evaluates to "FALSE", the conditional area is skipped until an "else if" is found. The query for the "else if" is then evaluated. When the evaluation is "TRUE", the conditional area following the "else if" is interpreted, then Fern jumps to the end of the conditional block.

When the query evaluates to "FALSE", the following conditional area is skipped.

Note: if the previous "if" (or "else if") is evaluated to "TRUE", then all other "else if" keywords within the conditional block are ignored.

else else The "else" denotes the final alternate conditional area within the conditional block.

Use of the "else" keyword is optional within the conditional block.

When the previous "if" (or "else if") evaluates to "FALSE", the conditional area following the "else" is interpreted. But, when any of the previous "if" or "else if" keywords in the conditional block are evaluated to "true", then the conditional area following the "else" is ignored.

endif endif The conditional block is ended by an "endif" keyword. The part of the definition file after an "endif" is interpreted normally.

Queries
Queries consist of defined variables and operators. The value of the query is interpreted as "TRUE" if the combination of variables and operators is "defined". Otherwise, the value is "FALSE".

Queries do not look at the value of the variables, only if the variable is defined. Thus, a variable with a value of "FALSE" has a query value of "TRUE" because it is defined. Only undefined variables have a query value of "FALSE".

Multiple variables may be included in a query statement by using the conjunction operators, and the evaluation can be modified using the logic operators.

Conjunction operator Description
var1 & var2 AND. Evaluates to "TRUE" when variables "var1" and "var2" are defined.
var1 | var2 OR. Evaluates to "TRUE" when either variable "var1" or "var2" is defined.
Logic operator Description
! var1 NOT. Evaluates to "TRUE" when variable "var1" is not defined.
( ... ) Parenthesis. Parenthesis change the order of interpretation. Normally, queries are interpreted from left-to-right. Parenthesis can be used to change the interpretation. For example:
"var1 & var2 | ! var3 & var4" is the same as
"var1 & (var2 | ( (! var3) & var4 ) )". But with parenthesis, we can specify:
"(var1 & var2) | (! (var3 & var4)".
In the former example, the query is "FALSE" when ver1 is undefined. In the latter example, the query can still be "TRUE" if var3 or var4 is undefined.

Finally, conditional blocks can contain other conditional blocks. (You can have an "if" within another "if".) You must ensure that each "if" has a matching "endif".


Rules

Rules tell Fern how to read the HTML document. Each rule consists of an action, two parameters, and a message. Not all rules use both parameters, but both parameters must be present.

A "*" as a parameter denotes a special meaning, or an unused parameter. Even if the parameter is unused, a "*" must be specified.

There are two types of actions:

  1. Actions that display their message when the rule is true.
    For example,"nested ol /ol The tag $0 is nested"
    This message is only displayed when the <ol> tag is nested.
  2. Actions that display their message when the rule is false.
    For example,"within title head The tag $1 is not in $2"
    This message is only displayed when the <title> tag is not located within a <head>...</head>.

Action Parameter $1 Parameter $2 Message Type Purpose
Rules that define tag ordering.
BEFORE $1 $2 displayed when FALSE Expect all $1 tags to come before $2. Display the message when this rule is not true.
NESTED $1 $2 displayed when TRUE Allow tag $1 to be nested within other <$1>...</$1> tags. Display the message only when the tag is nested. Parameter $2 is unused.
NESTED * * displayed when TRUE Normally, tags should not be nested. Any nested tag that is not explicitly allowed with "NESTED $1 $2" will trigger this rule and display the message. The values for $1 and $2 are "*"; use $0 for the tag name. This tag modifies $n for $0.
RESET $1 $2 displayed when TRUE Normally, each <$1> is ended by a </$1>. But, sometimes another tag can act as a </$1>. For example, Netscape allows a <table> to be used in place of a </a> tag: <a href=url> Some text <table>. This rule resets $e and $n for $2.
WITHIN $1 $2 displayed when FALSE Each <$1> should be found within <$2>...</$2>. Otherwise, the message is displayed.
Rules that define individual tags.
FIELD $1 $2 displayed when FALSE Display the message when tag <$1> does not contain "$2=...". The tag should contain <$1 $2="...">.
FIELD_NOT $1 $2 displayed when FALSE The opposite of "FIELD". Display the message when tag <$1> contains "$2=...". The tag should not contain <$1 $2="...">.
FOUND $1 $2 displayed when TRUE Display the message when tag <$1> is found. Parameter $2 is unused (can be "*").
IGNORE_WITHIN $1 $2 displayed when TRUE Some tags denote special non-HTML regions within the document. For example, <script>...</script> or <comment>...</comment>. These regions should be ignored and a message is displayed.
IGNORE_WITHIN * * displayed when FALSE A special rule to determine what to display when "$2" from another "IGNORE_WITHIN" rule is not found. For example, when <script> is found but </script> is missing. Both parameters are "*"; "$0" represents the tag.
MATCH $1 $2 displayed when FALSE Each <$1> should match a </$1>, otherwise a message is displayed. $2 is unused.
MATCH * * displayed when FALSE Each <$0> should match a </$0>, otherwise a message is displayed. $1 and $2 are both "*".
MUST $1 $2 displayed when FALSE Each <$1> must be in the HTML code. $2 is unused.
NEVER $1 $2 displayed when FALSE The tag <$1> should never be in the HTML code. $2 is unused.
ONCE $1 $2 displayed when FALSE The tag <$1> should in the HTML code at most one time. $2 is unused.
OPTIONAL_NOT $1 $2 displayed when TRUE The tag </$1> is not required. $2 is unused. This rule modifies $n for $0.
SURROUND_TAG $1 $2 displayed when FALSE Not all tags are in the form "<$1>". This rules specifies that the tag should begin with "<$1" and end with "$2". For example, HTML comments are in the form <!-- ... --> The message is displayed when "$2" is not found.
TAG_ERROR $1 $2 displayed when TRUE Special. This rule specifies messages for invalid tags. The possible values for $1 are:
  1. bad_>
    The message is displayed when a ">" is found that is not part of a tag.
  2. bad_<
    The message is displayed when a "<" is found that is not part of a tag.
  3. bad_/
    The message is displayed when a "</tag>" is found before a "<tag>".
  4. bad_tag
    The message is displayed when a bad tag is encountered. Currently, this includes "</>".
  5. missing_> The message is displayed when a tag is missing a ">".
  6. too_long The message is displayed when a tag-name is longer than 4096 bytes.


Settings

Settings are used to determine how Fern processes the input and output.

Setting Parameter $1 Parameter $2 Message Type Purpose
PRINT_BEFORE $1 * always displayed The message is displayed prior to processing the HTML document. This is useful for creating headers or displaying an introduction prior to checking the HTML syntax.

Multiple PRINT_BEFORE statements can be defined. To ensure that they are displayed in the proper order, the value of $1 is used to sort the PRINT_BEFORE statements. Although the sort order is by character, we recommend using numbers, such as 4-digit integers. For example:

print_before 0100 * This line goes in the middle\n
print_before 0001 * This line goes first\n
print_before 9991 * This line goes last\n
Please note: because they are sorted by characters, and not numbers, the string "10" comes before "2". You should try to be consistant in the characters that you use.
PRINT_AFTER $1 * always displayed Similar to PRINT_BEFORE, except that the message is displayed after the HTML syntax has been checked.
PROCESS $1 $2 never displayed This rule tells Fern what type of input to expect. The values for $1 and $2 are specific to Fern:
  • $1 is "HTTP". $2 is "TRUE" or "FALSE". This informs Fern that the HTML file contains the HTTP meta-header. (Useful when checking HTML documents that have been directly retrieved from a web server.)
    Note: Fern will only process documents that have a content-type of "text/html". This ensures that Fern will not check graphics or archive-formatted files.
  • $1 is "URL". $2 is "TRUE" or "FALSE". This informs Fern that the first line of the HTML document contains the URL for the document. (Useful when checking HTML documents that have been directly retrieved from a web server.) The content of the URL is stored in "$U".
  • All other values for $1 are ignored.
FROM_HTTP $1 $2 never displayed When processing an HTTP meta-header (process HTTP TRUE), the meta-values can be stored in local variables. $1 is the name of the HTTP meta-field. $2 is the name of the local variable to store the HTTP meta-field's value. For example, if you wish to store the HTTP meta-header "content-type" (usually set to something like "text/html") into a variable for Fern to use, you could use:
from_http content-type Content
The value of the "content-type" is stored in ${Content}.

The first line of an HTTP meta-header contains the HTTP protocol version, the HTTP return code, and a message describing the return code. (E.g. "HTTP/1.1 404 File Not Found".) These can be accessed by setting $1 to "$http-protocol", "$http-code", and "$http-message", respectively.


[Running Fern] [Main Menu]
Document revision: 6 December 1998 for Fern 1.00
Copyright 1996-1998 N.A. Krawetz
Modification, republication, and redistribution of this document is strictly prohibited. All rights reserved.