# VirtualDub source code - Lina

Lina is the HTML compiler for VirtualDub's help system.

## Syntax and input

The basic input format to Lina is almost XML, but not quite:

- All elements are either paired (`<p>...</p>`), or are self-closed (<p/>). There are no "provisionally open" tags, as in HTML 4 Transitional. Lina enforces this and thus makes it impossible to forget a closing tag.
- Correct tag pairing is enforced -- you cannot mix up end tags.
- The starting document must have only one root tag.
- XML violations: A schema/DTD is not required or used if present. Entities are not parsed. Attributes need not be quoted and attribute minimization (no value) is allowed.

Lina constructs a parse tree from her input and uses that tree to write output. Attributes are quoted as necessary, standalone tags are written without the self-close for greatest compatibility, and redundant whitespace is removed. As a result, it is difficult to make common HTML structural errors.

## Parsing phase

All control tags are of the form `<lina:`xxxx`>`. Two of these tags are special and execute as soon as they are parsed:

- `<lina:include src=`file`/>` begins parsing of a separate file at the current tree point. This inclusion is done on a file basis, so it is possible to begin a tag in one file and end it in another. When the included file has been processed, parsing resumes in the original file.
- `<lina:macro name=`name`>` creates a macro with the given name, containing the given contents. The macro is callable via the same `<lina:`xxxx`>` syntax.

These immediate tags are never placed in the tree; all other control tags are put in the tree and execute only after the entire tree has been parsed.

Lina requires that non-space character data only appear within tags that allow them, and will error if it is present elsewhere, such as immediately inside an `<html>` tag. The list of tags allowing CDATA can be augmented using `<lina:set-option>`.

## Execution phase

After parsing is complete, Lina then executes the parse tree from top to bottom:

- Text is output.
- Regular tags output themselves and their children.
- Macro and command tags fire when encountered.

In the process of doing so, three separate stacks are maintained:

- Execution stack: Holds all tags currently being executed.
- Context stack: Holds tags that establish reference points for data references -- macro calls, tag iterations. Relative paths use the top-of-stack as the starting point.
- Construction stack: Holds tags and files that are currently being created.

When tags are being constructed, plain text and tags copy themselves into the new tag. If a file is being written, the tags are output to that file. Otherwise, the output is discarded.

## Control tags

`<lina:apply name="macro">`...`</lina:apply>`
  Apply the named macro with each of the enclosed children as the given context.
`<lina:arg name="argname"/>`
  Output the named attribute argument from the current macro context.
`<lina:attrib name="att-name">`...`</lina:attrib>`
  Create an attribute in the currently constructing tag with the given contents.
`<lina:cdata>`...`</lina:cdata>`
  Insert the enclosed text and tags with whitespace collapsing enabled.
`<lina:data>`...`</lina:data>`
  Prohibit execution of enclosed tags. This tag is skipped during path searches.
`<lina:delay>`...`</lina:delay>`
  Copy tags verbatim without execution into the output.
`<lina:dump-stack/>`
  Dump current stacks to standard output for debugging.
`<lina:fireball src="src-file" dst="dst-file">`
  Copy a file.
`<lina:for-each name="path">`...`</lina:for-each>`
  Execute the tag body as a macro, with all tags referenced by the given path as the contexts.
`<lina:if-arg name="arg-name">`...`</lina:if-arg>`
  Executes the tag body only if the current macro context has the named attribute argument.
`<lina:if-not-arg name="tag-name">`...`/<lina:if-not-arg>`
  Executes the tag body only if the current macro context does not have the named attribute argument.
`<lina:if-not-present name="tag-name">`...`</lina:if-not-present>`
  Executes the tag body only if the current macro context does not have the named tag.
`<lina:if-present name="tag-name">`...`</lina:if-present>`
  Executes the tag body only if the current macro context has the named tag.
`<lina:pre>`...`</lina:pre>`
  Insert the enclosed text and tags without whitespace collapsing enabled.
`<lina:pull name="path"/>`
  Execute the contents of the tag specified by the given path in the current context.
`<lina:replace from="pattern" to="result">`...`</lina:replace>`
  Execute the tag contents, replace all instances of pattern with result in the output, and place the output into a new string tag.
`<lina:set-option name="link-truncate" baseurl="base-url" [notruncate]>`
  Toggles extension truncation for links with the given prefix.
`<lina:set-option name="output-dir" target="path">`
  Sets the output directory for file writes and file copies.
`<lina:set-option name="tag-info" tag="tag-name" cdata="y"|"n">`
  Allows or disallows inline character data (CDATA) for the given tags.
`<lina:source>`...`</lina:source>`
  Output the source to the enclosed tag structure as text in HTML.
`<lina:tag name="tag-name">`...`</lina:tag>`
  Create a tag with the given name and body as contents, and then execute the created tag.
`<lina:write file="filename">`...`</lina:write>`
  Execute the given body and write the output to a file.