In addition to simple strings, you can use expressions to set the value of an attribute. Within expressions, you can refer to other attributes to obtain their value, and you can also use various operators.

General Syntax

Usually, expressions have to be enclosed in parentheses (``(...)'') and may appear after the equal-sign (``='') of an assignment (see below for an exception!).

String constants must be enclosed inside any kind of quotes - different to values outside expressions, where the quotes can be omitted under certain circumstances. As a difference from most ``real'' programming languages, the same is true of numeric constants!

To refer to the value of another attribute, simply use its name, without any enclosing quotes. The source attribute must exist, either defined via <$define> or by being part of a macro declaration.

Furthermore, it must have been assigned a value, for example using <$let>, or by setting it within a macro call. Attributes defined without a default value or not being set within a macro call do not contain any data and therefore will have to be updated using <$let> before using them.

<$define image:string="hugo.gif">
<img SRC=(image) ALT="image">

will be converted to

<img SRC="hugo.png" ALT="image">


Unary Operators

not expression
Negate (boolean) expression
set attribute
True, if attribute has been set (read: passed a value) within macro call.
defined attribute
True, if attribute was defined with <$macro> or <$define>
Exists(local uri)
True, if document at local URI exists (bool). This can also be specified as a Project Relative URI.
Example: Exists("index.html"), Exists(":image/next.gif")
True, if a file exists (bool). If you do not specify a full filename (including a device name), it will be relative to the source root directory.
Example: fExists("sepp:hugo/resi.hsc"), fExists("///child.txt"), fExists("include/global.hsc")
Yields the character whose ASCII code is number. If number is greater than 255, it will be taken modulo 256. An empty value, zero or a non-numeric value yields an empty string.
Yields the numeric ASCII code of character. If the expression passed to ord() is a string of more than one character, all but the first are ignored. An empty string yields zero.
Get value of an environment variable.
Example: GetEnv("Workbench")
GetFileSize(local uri)
Get size of a specific document. You can use the attribute HSC.Format.FileSize to change the appearance of the result.
Example: GetFileSize("../../download/hugo.lha"), GetFileSize(":nudes/resi.jpg")
Get current Greenwich Mean time. You can use the attribute HSC.Format.Time to change the appearance of the result.
Get current local time. You can use the attribute HSC.Format.Time to change the appearance of the result.
Get the modification time of a file You can use the attribute HSC.Format.Time to change the appearance of the result.
To show the time of the last change to a page, this is often a more logical choice than GetTime(), especially if you include a lot of macros and use only a few in a certain document.
Example: Last change: <(GetFileDate(hsc.source.file))>
Returns the part of a string before the last period. If the name has no extension, returns the entire input string.
Returns the extension of a filename, i.e. the part after the last period, or the empty string if there is no extension.
Returns the kind or URI for its argument as a three-character string:
  • abs: Absolute URI, i.e. relative to your project root (starts in ':')
  • ext: External URI, not on your server.
  • rel: Relative URI
  • rsv: Server-relative URI
Unfortunately, these are sort of ``internal'' terms that are not quite compatible with what the docs on project-relative URIs say, but you can easily find out of what kind an URI is using the expression <(urikind (myuri))>.

Binary Operators

Integer arithmetics

These operators are fairly simple. Division by zero is caught, but no overflows or stuff like that. But as long as you don't do scientific maths in your HTML macros, you should be fine.
Empty strings count as ``0'', any text not consisting only of digits counts as ``1'' (no warnings). This seems to make sense for auto-casting BOOL.
expression & expression
Addition. Weird operator, but using '+' for string concatenation seems to make sense as it is the far more frequent operation.
expression - expression
Subtraction. As ``-'' is also a legal character in attribute names, you must enclose it in whitespace, lest it be interpreted as part of the next or previous word.
expression * expression
Multiplication. Straightforward...
expression / expression
expression MOD expression
Modulo (the remainder of an integer division).
expression < expression
Less than.
expression > expression
Greater than.
expression <= expression
Less than or equal.
expression >= expression
Greateer than or equal.

The latter four operators were present in HSC V0.917 already, but their semantics have changed (that's why they were undocumented in the first place)! They used to compare strings, now they compare numbers -- but they still have a string equivalent each, see below.

String operators

expression = expression
string comparison (case insensitive)
expression == expression
string comparison (case sensitive)
expression + expression
string concatenation
little IN big
search for substring little in big (case insensitive)
string MATCH pattern
Matches string against the regular expression pattern. RE syntax follows that of egrep or VIM's ``very magic'' mode, i.e. metacharacters ((|),[],{},.,+,*,?) are active by default and have to be backslash-escaped to be interpreted as literals.
string MATCHI pattern
Like MATCH, but case-insensitive.
expression LT expression
Less than.
expression GT expression
Greater than.
expression LE expression
Less than or equal.
expression GE expression
Greater than or equal.

These comparison operators, added in V0.920 to do the job of what are now integer operators, all work case-insensitively. Maybe that's not such a smart choice after all and they should be case-sensitive while you get a unary ``upstr'' operator to upcase strings yourself. Then again, who needs case-sensitive comparisons in HTML? Perhaps I'll change them, so don't complain later ;)

<$define name:string="hugo">
<$define here:string="here">

<img SRC=(name+".gif") ALT=(name+" was "+here)>
<$if cond=(name="hugo")>
This is hugo!
Maybe it's sepp?
<$if cond=("SePp" IN "hugo,sepp and resi")>
Sepp is among them.
AmigaOS version: <(GetEnv ("KickStart"))>

will be converted to

<IMG SRC="hugo.png" ALT="hugo was here">
This is hugo!
Sepp is among them.
AmigaOS version: 40.70 

At least on my machine.

Boolean Expressions

If you pass an expression to a boolean attribute, the expression is evaluated as before. If the expression returned an empty string, the boolean attribute is interpreted as false. This will cause the attribute to be removed from the tag/macro-call.

Any none-empty string will set the attribute to true, resulting in a value equal to the name of attribute. (In HTML, writing ISMAP is short for ISMAP="ISMAP", while in XHTML the latter has to be, and automatically is, spelled out.)

<img SRC=(name) ALT="nufin" ISMAP=(name="map.gif")>

will be converted to

<img SRC="hugo.png" ALT="nufin">

if name has been set to "hugo.gif", or to

<img SRC="map.png" ALT="nufin" ISMAP>

if name has been set to "map.gif". Note that only the second call enables the boolean attribute ISMAP, while it gets stripped for the first call.

The following operators yield a boolean (TRUE or FALSE) result and/or can be used to manipulate boolean values.

expression1 AND expression2
TRUE if both expression1 and expression2 are TRUE.
expression1 OR expression2
TRUE if expression1 or expression2 or both are TRUE.
expression1 XOR expression2
TRUE if either expression1 or expression2, but not both, are TRUE.


Important: Different to most programming languages, hsc does not support priorities for different operators. Therefor, expressions are simply processed sequentially (Programmer's lazyness rules).

But you can use nested brackets within complex expressions.

Symbolic References

Starting with V0.926, HSC can also handle a special kind of expressions called symbolic references (in PERL-speak), which are a bit of an exception to the above syntax. A symbolic reference is an expression whose value will be taken as the name of a variable. The following macro employs this mechanism:

<$macro NAMES SELECT:num>
  <$define NAME1:string="Hugo">
  <$define NAME2:string="Resi">
  This is <( {"NAME" + SELECT} )>

<NAMES SELECT=1> yields ``This is Hugo'', while <NAMES SELECT=2> yields ``This is Resi''.

A symbolic reference is an expression enclosed in ``curly braces'' (``{...}''). HSC takes its value as the name of an attribute, and the value of this attribute is the value of the entire expression. The above just concatenates the string "NAME" and the ``selector'' number and returns the value of the appropriate variable. This may not seem very useful, but for things like emulating arrays it can come in quite handy.

One major difference between a symbolic reference and a normal expression is that the former may be used on the left hand side of an expression, it yields a so-called lvalue. So you can not only read an attribute whose name is determined at compilation time, but also write to it:

<$let {"foo" + "bar"}='1'>

is the same as:

<$let foobar='1'>