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, settings, and registration.
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.
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.
\n | a new-line character -- same as pressing "enter" or "control-M" |
---|---|
\r | a return character -- same as pressing "control-J" |
\t | a tab character |
\a | an 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.
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}\nThis 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 10 times. For example:
define many_very very ${many_very}The value of ${many_very} is "very very 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.
$0 | The tag that triggered the rule. |
---|---|
$1 | The first parameter of the rule. |
$2 | The second parameter of the rule. |
$l | The 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. |
$b | The number of beginning tags associated with $0. |
$e | The number of ending tags associated with $0. Please note, some rules may change the value of $e. |
$n | The 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.
|
$T | The entire tag being processed. |
$U | The URL or filename being processed. This is only defined as the URL when the setting "PROCESS URL TRUE" is used. |
$V | Fern's version and copyright statement. |
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".
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 |
| the first conditional area |
else if query2 | define an alternate conditional area |
| the second conditional area |
else | define an alternate conditional area |
| the third conditional area |
endif | end 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.
|
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 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".
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:
nested ol /ol The tag $0 is nested
"
within title head The tag $1 is not in $2
"
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:
|
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_TAG | $1 | * | displayed when TRUE | Ignore (don't check) all fields within the tag. Useful for ignoring tags such as <@...@> and <!--...--> |
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 <!-- ... -->
where $1 is "!--" and $2 is "--".
The message is displayed when "$2" is not found.
Note: If the value of $1 is not a letter or number, then the SURROUND_TAG may be a partial match. For example, if $1 is "=" and $2 is "%", then this will match "<=@ ... @=%>". |
TAG_ERROR | $1 | $2 | displayed when TRUE | Special.
This rule specifies messages for invalid tags.
The possible values for $1 are:
|
Complex Rules using
Extended Regular Expressions (ERE) to define tags.
In these tags, the values of $1 and $2 are immediately evaluated. Variables such as $T, $U, and tags relating to the HTML file being processed will not be set. The EREs are compared against the entire tag. The entire tag consists of all characters after the initial "<", including the final ">". (The entire tag matches the regular expression ".*>".) EREs can be used to check values within tag fields, but the use of EREs may increase Fern's processing time. See ERE for a little more information about ERE's. | ||||
ERE | $1 | * | displayed when TRUE | Compares the extended regular expression (ERE) in $1 with the entire tag. |
ERE | $1 | $2 | displayed when TRUE | Compares the extended regular expressions (ERE) in $1 and $2 with the entire tag. Displays the message when the tag "matches ERE $1 but not ERE $2". |
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_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:
|
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 ContentThe 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. |
Setting | Parameter | Purpose |
---|---|---|
Register | registration-code | Provides the registration code for Fern. See "How To Register" for more details. (Depricated.) |