pragma - inline compiler directive


<!-- pragma [push|pop] name [value] -->
<!-- pragma if expr -->
<!-- pragma elif expr -->
<!-- pragma else -->
<!-- pragma endif -->

The pragma directive, unlike any other directive, can appear anywhere in the script, including inside a function. Pragmas typically alter the way code is lexically analyzed, so that the pragma can be applied only to certain code sections if desired. Since they appear in comments, earlier Vortex versions that are not aware of a particular pragma will ignore them silently (unless --warn-unknown-pragma is in effect, here). The pragmas available are:

  • strictcomment on|off Turn on or off strict comment parsing. With strict comments on, comments must start with "<!--", not just "<!"; thus tags such as "<!DOCTYPE>" are directly printable and do not get interpreted as comments. The default is on. Added in version 3.01.986950000 20010410.

  • nestcomment on|off Turn on or off nesting of comments. With nesting on, comments may be nested. The default is off. Added in version 3.01.986950000 20010410.

  • literalprint on|off Whether to allow literal text and/or variable printing. With literal printing off, printing text or variables by simply placing literal text or $-var references in the code is not allowed and will generate the compile error "Literal/variable printing not allowed when pragma literalprint off". Whitespace is still allowed but is silently ignored (instead of being output where not part of indentation); comments are also still permitted and ignored.

    Turning off literal printing can be useful in some situations - such as when generating an image - to ensure that all output is being generated by explicit code, e.g. via <fmt>, and no inadvertent whitespace or mistyped code is causing extraneous output, e.g. calls to non-existent functions being interpreted as literal tags.

    The default is on. Added in version 5.01.1223689000 20081010.

  • compilesqlexpressions on|off Whether to compile SQL expressions into the .vsc object file where possible, rather than interpret them on the fly at run-time. SQL expressions are used in parenthetical variable assignments (e.g. <$x = ($y + 5)>) and complex <if> statements, amongst other places. Compiling them speeds up script execution, as the original expression then does not need to be re-interpreted by the SQL engine every time the statement is run. The default is the value of the texis.ini setting [Texis] Compile SQL Expressions; if that is unset, the default is on. Added in version 6.01.

  • syntaxversion N[.N[.N]]

    Sets the version (major, optional minor, and optional release) of Texis to attempt Vortex script syntax compatibility with. The valid values are 7 through the version of the Texis executable. Currently only the major version number has any effect.

    This setting controls various legacy functionality and idiosyncrasies that have been fixed or changed in recent releases. It affects SQL expressions (in <sql>, <if>, <while>, and variable assignments), especially quoted strings and "$" in quoted strings; most loopable statements; and </local> tags. (The -translate-from-version option - here - attempts to handle some of these changes, as noted below; it is preferable to translate/update a script rather than use the syntaxversion pragma, which may be deprecated in the future.)

    When syntaxversion is set to less than 8 (e.g. 7), deprecated/old behavior is in effect. This includes:

    • $ loses its special meaning in quoted strings in SQL-expression Vortex assignments and <if>/<while> statements, or in single-quoted SQL literal strings in the SQL of <sql> statements. Hence $$ and $var mean $$ and $var in those circumstances, not $ and (illegal) variable-parameter as they would in quoted strings in non-SQL-expression statements, which is inconsistent. For example, <$x = (stringformat( "price: %s" $$19.95" ))> would set the variable $x to a string with two - not one - dollar signs. Thus the parsing of $rank or $$rank in SQL expression statements could be affected. --translate-from-version attempts to fix this.

    • Quoted-string arguments to functions, <export> etc. consisting solely of a variable (e.g. "$var" with quotes) are allowed (and are taken as a variable), instead of causing an Argument must be single variable or literal error (as most any other variable embedded in a quoted string would be, e.g. "foo$var"). Note also that since <sql> is the only statement to allow embedded variables in its argument(s) (for SQL parameters), and can take its SQL statement as a variable, <sql "$stmt"> takes the $stmt variable as the SQL statement if version 7 syntax, but as a SQL parameter (to an empty SQL statement) if version 8 or later.-translate-from-version attempts to fix this.

    • Quotes must be HTML-valid, not just SQL-valid, in SQL contexts. I.e. they must balance at the start and end of the HTML "attribute" (space-separated text fragment) they appear in too, not just open/close each other. E.g. <if stringformat("foo" ) = "foo"> (no space between open-parenthesis and first double-quote, but space between second double-quote and close-parenthesis) would cause a Missing start double quote in value error. With version 8 or later syntax, only SQL validity checks are made (after double-to-single quote translation and escapement); the statement would be valid.

    • Quotes within (as opposed to surrounding) an HTML "attribute" name or value might not be translated for SQL (double to single quote, and quoted single quote escaped as two single quotes) as attribute-surrounding quotes are. E.g. <$x = (stringformat("/foo"))> (no spaces to separate quotes from adjacent "attributes") may cause an error (Parse error: Expected NAME_OP after RENAME_OP, but got op 0). With version 8 or later syntax, all quotes are translated if needed, making the statement valid.

    • Simple <if>/<while> expressions - i.e. $operand$ $op$ $operand$ where $op$ is relational, nmod, div or / - are evaluated by Vortex, not Texis SQL, and <sqlcp arrayconvert> (here) does not apply (e.g. only the first value of multi-value variables in expressions will be used). With version 8 or later syntax, all expressions are evaluated by Texis SQL, and array conversion always applies.

    • The <switch> value must be a single value or literal, not a Texis SQL expression, and <sqlcp arrayconvert> (here) does not apply (nor does it in <case>). With version 8 or later syntax, a Texis SQL (i.e. SELECT) expression may be used in <switch>, and arrayconvert applies to both <switch> and <case>.

    • SQL expression "assignments" with no left-hand-side target variable, e.g. <(func($param))> (as opposed to <$x = (func($param))>, are not permitted. In version 8 syntax, these are permitted, as a shorthand to merely call a SQL function with no (or an ignored) return value.

    • A closing </local> tag will not end fully optional-loop statements (those whose loop/non-loop syntax is solely determined by a matching end tag in version 7 syntax, not an option etc.), e.g. <stat>, <cal>, <calrule>, resulting in a compile error such as "</LOCAL> with <LOCAL>" and/or "unterminated <stat> here".

    • Loopable statements revert to version 7 syntax for determining loopiness: when not self-closed, some are fully optional-looping and loop only if a matching close tag is given (<stat>, <cal>, <calrule>); some are looping if certain options are given (<xtree>, <rex>, <split>, <fetch>, <nslookup>); and others are always looping (<sql>, <timport>, <readln>). All default to accumulating values in returned variables (i.e. ROW is accepted, and defaults to off), and can be non-looping in version 7 or later if self-closed (e.g. "<sql ... />"). With syntaxversion 8 or more, version 8+ syntax is used: all loopable statements are non-looping if self-closed, looping otherwise (regardless of options or close tag), and return values never accumulate in looping versions (thus ROW is redundant and not accepted). The exceptions to all of this are <loop> and <while>, which are always looping and do not change with this pragma. --translate-from-version attempts to fix loopable statements, and may warn if non-ROW behavior was used.

    • Some <xtree> behavior changes (in addition to looping changes above) for version 7 syntax:

      • $ret.count/$ret.seq are not set in the non-looping version

      • Some actions (e.g. SET/GET) cannot be performed in the looping syntax

    • Some <fetch> behavior changes (in addition to looping changes above) for version 7 syntax:

      • PARALLEL is not allowed for non-looping syntax (while allowed in version 8+ syntax, it is ignored: single fetch), and is required for looping syntax

      • The RAWDOC attribute name is not allowed; the raw doc must be given as an arg after the URL, and only for non-looping syntax

      • The URL argument need not be labelled URL[S], but must be after all other options

      • Non-looping syntax is not self-closed
      With version 8+ syntax, all options (including URLs, and excepting loop vars) must be labelled, can be in any order, and can be given in both looping and non-looping syntax. -translate-from-version attempts to handle <fetch> changes.

    • Some <nslookup> syntax changes (in addition to looping changes above) for version 7 syntax:

      • The last unlabelled attribute is the $hostOrIp argument (in version 8+ it must be labelled)

      • The PARALLEL flag determines loopiness

      • The BYADDR and BYNAME flags are allowed
      In version 8 and later syntax, BYADDR and BYNAME are disallowed as redundant, as the $hostOrIp argument must be labelled HOSTS= or ADDRS=.

    • Some <readln> syntax changes (in addition to looping changes above) for version 7 syntax:

      • $, $ret.size are not set

      • The OFFSET option is not available

    • In version 7 syntax, <fmt> will clear $ret; in version 8 syntax, it is left unaltered.

    • The <return> statement does not take a parenthetical expression as a SQL expression, nor may multiple values be given, in version 7 syntax.

    • The $ret.code, $ret.token, and $ret.msg variables are not set in version 7 syntax.

    The default for the syntaxversion pragma is the value of the --translate-from-version option (here) if given; otherwise it is the value of the texis.ini setting [Texis] Compatibility Version (taking versions below 7 as 7). If neither is set, the default is the version of the Texis executable.

    Caveat: Since Compatibility Version may change after the script is compiled, and thus change the default syntax version, changing Compatibility Version will force an automatic recompile of scripts when they are next run, so that the correct syntax version is always used.

    Changing the value of this pragma in a script after an affected statement but before its associated end tag or enclosing block statement results in undefined behavior. This pragma should generally only be used at the top of a script.

    Caveat: this pragma was added in version 8. Its supported version number range may change in a future release (e.g. version 7 will eventually be dropped), as older behavior is deprecated. Its existence is only to ease transition of old code when upgrading to Texis version 8 or later, and thus should only be used temporarily. Old code should be updated to reflect version 8 behavior - and this pragma removed from code - soon after upgrading.

  • if value [op value]

  • elif value [op value]

  • else

  • endif

    The value op value expression is evaluated, and if true, code following (up to the next matching elif, else, or endif pragma) is compiled normally; if false, the code is ignored. This provides a way to conditionally include code, e.g. depending on Texis version.

    Each value is interpreted as an integer. It may be a literal integer, or one of the following tokens:

    • texisVersionMajor The major version of Texis

    • texisVersionMinor The minor version of Texis

    • texisReleaseDate The Texis GMT release date, as an 8-digit $YYYYMMDD$ integer

    • syntaxVersionMajor The major version of syntaxversion (here) currently in effect

    • syntaxVersionMinor The minor version of syntaxversion currently in effect

    Any other token is silently (unless --warn-all is used, here) taken as 0. This allows an older version of Texis to test for a feature token it knows nothing about (i.e. from a future release), without causing a compile error. (Production/release compilations, however, should use --warn-all to detect typos or incorrect uses of tokens.)

    The op is one of the relational operators < <= = != >= >. Alternatively, the entire expression may just be a single value, in which case it is true if the value is nonzero. The elif pragma provides a way to combine an else and an if without additional nesting.

    Since (as of version 7.07.1612305160 20210202) Vortex scripts are automatically recompiled whenever the Texis release changes (not just when the Vortex compiled object file format changes, as in previous versions), a script with an if pragma that uses e.g. texisReleaseDate will execute the correct if block even when a newer Texis executes a script compiled by an older Texis (assuming both are version 8 or later).

    Added in version 8.

In version 7 and later, pragmas (except for if etc.) can be pushed or popped on a stack. Pushing a pragma sets the value given, but first preserves the current value; popping restores that previous value. Pushes may be nested to any depth. This allows local sections of code to alter a pragma's value, while still preserving and restoring the outer code's value (without needing external "magic" knowledge of what it is):

literalprint could be on or off here (original value)
<!-- pragma push literalprint off -->
<!-- literalprint is off here -->
<!-- pragma pop literalprint -->
literalprint is back to its original value

Each pragma has its own independent stack, which starts out empty (causing the pragma's default value to be in effect). A normal pragma "set" directive (i.e. a pragma with neither push nor pop) acts as a pop (if stack is not empty), followed by a push. It is an error to explicitly pop a pragma when its stack is empty.

Pragmas are in effect only for the <script> block they appear in, i.e. they are reset (stack cleared) for each new <script> block or module.

In this example, nestable comments are turned on. Thus the "print bio of author" comment, which is inside a larger comment, nests properly, and the entire inner <SQL> statement is commented out:

<!-- pragma nestcomment on -->
<A NAME=main>
  <SQL "select Title, Author from books
        where Keywords like $query">
    Title: $Title       <!-- print title -->
    Author: $Author     <!-- print author -->
<!-- this section commented out:
    <SQL "select Details from author
          where Author = $Author">
      Bio: $Details     <!-- print bio of author -->


Copyright © Thunderstone Software     Last updated: Jul 17 2021
Copyright © 2021 Thunderstone Software LLC. All rights reserved.