prevnext   » SZS: Wiimms SZS Toolset » Guides » Parser Syntax

Parser Syntax

Contents

1.   Introduction

Wiimms SZS Tools have a powerful text parser (or text compiler) implemented. It support variables, functions, if..then..else structures, loops and user defined macros and functions.

The parser is used for ...

Single line parsing is used for ...

This article describes the general syntax and behavior of the text parser.

1.1   General Syntax

Here is a list with the general syntax of the text parser.
  1. The tools generate always Windows compatible text files with CR+LF as line termination. Unix system has no problems with it. If scanning a text file, Windows and Unix format are allowed.
  2. To identify the kind ot the text file, the first 4 characters of a text file must be an identifier like '#KMP' or '#MDL'. A byte order mark (BOM) as very first characters is detected and skipped.
  3. Spaces and tabs (=blanks) at beginning or end of line are ignored. Blanks (single or multiple) are used to separate columns.
  4. Empty lines (= lines containing only blanks) and lines beginning with a '#' are ignored.
  5. Lines beginning with a '[' signal the beginning of a new section.
  6. Lines beginning with a '@' are preprocessor directives.
  7. Lines beginning with a '$' (and followed by a name) are grouping markers or special commands.
  8. Lines beginning with a letter or digit are normal lines and contain lists of parameters. They may be split into multiple lines.
  9. A line beginning with a '>' is a continuation line of the previous line. The base line and all related continuation lines are logically used as one long input line.
  10. Names and keywords are sequences of letters (case ignored), digits and '_', '.' and '$', but never begin with a digit or '.'.
  11. Numbers are floats or integer values. Numbers will always start with a digit or with a '.'. Hexadecimal integers are prefixed with '0x'. Floats are detected by the decimal point or by an exponent. Vectors are entered by using the function v() or a similar one.
  12. The text scanner accepts variable names instead of numbers in any place of the text file. If the variable does not exist, a warning is printed and value 0 is assumed → see »Variables«.
  13. If the text scanner expects a 2D or 3D vector and scan a variable with a vector value or expression, all components of the read vector are used to read the vector in one step.

1.2   Sections

The whole file is divided into sections. Each section starts with »[NAME]« and ends at the beginning of the next section. If the same section exists two or more times, the later one overrides the previous definitions. It is planned to change this behavior to allow a more logical definition order.

The complete source is read in 2 passes. The first pass (global variable $PASS is set to 1) is used to define names. Warning and error messages are suppressed in this first pass. The second path ($PASS is set to 2) is the one that defines the objects.

The [SETUP] section is special and should stay at the beginning of the source file. The most important parameter is:

  REVISION = number
This numeric value is used to decide, how the following sections are read and handled. This may be important if the tools change the syntax and/or semantics. Any section may have a parameter
  @REVISION = number
to change the revision number only for the current section.

If an external tool add some sections at the end, they should first declare REVISION in each section to specify the data handling.

Example:

  [NAME]
  # Use syntax and semantics of tools revision 1234 for this section
  @REVISION = 1234

  # Calculated check points
  ...
→ Define and calculate global values in the [SETUP] section.

2.   Data types

The parser support the follwing data types: UNSET (or NONE), INT (integer), FLOAT (double precision floating point), VECTOR (a 3-tupel of type FLOAT), and as of v1.62a type STRING.

2.1   Data type UNSET

???

2.2   Data type INT

???

2.3   Data type FLOAT

???

2.4   Data type VECTOR

???

2.5   Data type STRING

???

3.   Elements

3.1   Variables and definitions

The text compiler supports variables in five name spaces. If searching a variable, this order is used:
  1. Private variables (defined with @PDEF).
  2. Local variables (defined with @LDEF or @DEF).
  3. Global variables (defined with @GDEF).
  4. Predefined constants (defined by the parser).
  5. User constants (defined with the --const option).
Each source file, macro or function have its own private name space. Loop variables and macro/function parameters are also stored into the private namespace.

The local name space is cleared every time when a new section begins. Variables of the global name space are held until the complete scanning and parsing is done.

Predefined constants are definition set by the parser. The user can add user constants by using the command line option --const name1=val1,name2=val2,... (or -c ...).

Some sections define automatically global variables for cross section links. The user can define private, local and global variables.
Syntax:

  @DEF   NAME [['?']'=' EXPRESSION] [, NAME= ...]...
  @PDEF  NAME [['?']'=' EXPRESSION] [, NAME= ...]...
  @LDEF  NAME [['?']'=' EXPRESSION] [, NAME= ...]...
  @GDEF  NAME [['?']'=' EXPRESSION] [, NAME= ...]...
'@PDEF' defines private variables, '@LDEF' local variables and '@GDEF' defines global variables. '@DEF' is an alternative name for '@LDEF'. The type of the variable is the result type of the expression. Multiple variables can be defined using a comma as separator.

An extension immediately behind the DEF command force the storing type:

It's also possible to define enumerated and shifted values with:

If an expression is defined, these assignment acts like the standard *DEF. If an expression is omitted, then the value is the 'previous_value+1' for ENUM and 'previous_value*2' for SHIFT.

The old commands @NUM, @GNUM, @INT, @GINT, @FLOAT and @GFLOAT are still allowed for compatibility reasons as alternatives for @DEF, @GDEF, @DEF.I, @GDEF.I, @DEF.F and @GDEF.F.

'NAME' is the variable name: A sequence of letters (case ignored), digits and '_', '.' and '$', but never begins with a digit or '.'. If the optional '?' before the equal sign is set, then an already existing variable is not redefined. 'EXPRESSION is a numerical expression (see below).

Examples:

  @def.i   my_item  = 0x0a + 3
  @gdef.f  origin  ?= 123.4, origin2 = origin/2
  @ldef    $a.num   = -12.3

If a vector with name 'NAME' is defined, then the 3 virtual variables 'NAME.X', 'NAME.Y' and 'NAME.Z' are also defined to access the 3 members. The access to these virtual variables is only possible, if no real variable with same name is defined.

If decoding a text file the scanned index names may be used for the new output.

3.2   Values

A value is a number (integer or float), or a string, or a variable name, or a function result, or an expression surrounded by parentheses. Each value can be preceded by any number of signs.

Syntax:

  VALUE    := [SIGN]... OPERAND
  SIGN     := '+' | '-' | '!' | '^'
  OPERAND  := INTEGER | BITFIELD | FLOAT | NAME | FUNCTION | '(' EXPRESSION ')'
  BITFIELD := '<' [BITPARAM] '>'
  BITPARAM := VALUE [ ':' VALUE ] [ ',' BITPARAM ]
  FUNCTION := FUNCNAME '(' [PARAMLIST] ')'

Signs are calculated from right to left:

sign description
+ Don't change the value.
- Mathematical negation.
! Logical negation. The result is either 0 (FALSE) or 1 (TRUE).
^ Bitwise negation. The result is always an integer.

A Bitfield is an easy way to set bits in an integer. For example value <2,4:6> is an integer with bits 2 and 4..6 set (=0x74).

3.3   Expressions

The text compiler supports C like numerical expressions. IF conditions and assignments are automatically scanned for expressions. Parameters of tables are only scanned for values. Use parentheses (...) to force expression scanning.

Syntax:

  EXPRESSION  := VALUE | EXPRESSION2 | EXPRESSION3
  EXPRESSION2 := EXPRESSION OPERATOR EXPRESSION
  EXPRESSION3 := EXPRESSION '?' EXPRESSION ':' EXPRESSION
  OPERATOR    := '**' | '*' | '/' | '%' | '+' | ...

The following operators are supported:

operator prio description
** 1 Power of
* 2 Multiplication
/ 2 Division
% 2 Modulo
+ 3 Addition
- 3 Subtraction
<< 4 Shift left
>> 4 Shift right
> 5 Greater than
>= 5 Greater than or equal
< 5 Less than
<= 5 Less than or equal
== 6 Equal value
!= 6 Non equal value
=== 6 Equal type AND equal value
!== 6 Non equal type OR non equal value
& 7 Bitwise AND (parameters are converted to INT)
| 8 Bitwise OR (parameters are converted to INT)
^ 9 Bitwise EOR (parameters are converted to INT)
&& 10 Logical AND (all non zero values and strings with >1 character are TRUE)
|| 11 Logical OR (all non zero values and strings with >1 character are TRUE)
^^ 12 Logical EOR (all non zero values and strings with >1 character are TRUE)
@ 13 Concatenation: Both operands are converted to strings and concatenated
? : 14 Alternation
Syntax: EXPRESSION '?' EXPRESSION ':' EXPRESSION
Operations with a higher priority (less prio value) are calculated first. Operations with same priority are calculated from left to right. Use parenthesis (...) to change the predefined order.

4.   Parser functions

The parser supports different kinds of functions. Some general functions are available for all tools, some other functions only in in a specific context like KMP parsing. Additionally a user can define or overwrite functions using the '@FUNCTION' command.

Syntax:

  FUNCTION  := FUNCNAME '(' [PARAMLIST] ')'
  FUNCNAME  := Any combination of a-z (case ignored), 0-9, '.', '_' and '$'.
  PARAMLIST := EXPRESSION [ ',' PARAMLIST ]

4.1   List of functions

This command prints the list of parser functions. Parser functions are available during encoding and scanning of text files. There is a set of function avaialble for all file types. Other functions are only available if scanning a special type of file.

Function Reference
File
Type
Return Value
& Function Name
& Parameters
Description
* int
$
(...)
This debug function returns the number of parameters.
* *
abs
(val)
Returns the absolute value of 'val'. If 'val' is a vector, the absolute value of each component is calculated. The return type is identical to the type of 'val'.
* flt|vec
acos
(val)
Returns the arc cosine of 'val' in degree. If 'val' is a vector, the arc cosine of each component is calculated.
KMP int
area$dest
(area_idx)
Returns the destination index (e.g. camera index) of an area.
KMP int
area$mode
(area_idx)
Returns the mode of an area.
KMP int
area$n
()
Returns the number of areas.
KMP vector
area$pos
(area_idx)
Returns the position of an area.
KMP vector
area$rot
(area_idx)
Returns the rotation of an area.
KMP vector
area$scale
(area_idx)
Returns the scale of an area.
KMP int
area$set
(area_idx,​val_idx)
Returns setting 0..3 of an area.
KMP int
area$type
(area_idx)
Returns the type of an area. Cameras are type 0.
KMP int
area$unknown
(area_idx)
Returns the unknown value of an area.
* flt|vec
asin
(val)
Returns the arc sine of 'val' in degree. If 'val' is a vector, the arc sine of each component is calculated.
* flt|vec
atan
(val)
Returns the arc tangent of 'val' in degree. If 'val' is a vector, the arc tangent of each component is calculated.
* float
atan2
(x,​z)
Returns the arc tangent of 'z/x' in degree, using the signs of the two arguments to determine the quadrant of the result. Both arguments are converted to a float before operation. If 'x' is a vector, its x component is used. If 'z' is a vector, its z component is used.
* vector
axisRot
(pt,​deg,​axis1,​axis2)
The point 'pt' is rotated around the axis 'axis1->axis2' by 'deg' degree, which is a scalar. The other 3 parameters are converted to vectors before operation.
* int
be
(val,​n)
Convert 'val' to integer, limit it to 'n' bytes (1-8) and mark it for big endian usage.
* flt|vec
bezier
(pos,​v1,​va​[,vb],​v2)
Calculate the position 'pos' on a bezier curve going from 'v1' to 'v2'. 'va' and 'vb' are helper points. If 'vb' is not set, a quadratic bezier curve is calculated. Otherwise 'va' and 'vb' are set and a cubic bezier curve is calculated. Position 0.0 returns 'v1' and position 1.0 'v2'. All position values between 0.0 and 1.0 return a point of the calculated bezier curve between points 'v1' and 'v2'. If 'pos' is a vector, different positions for each coordinate are used.

If any parameter is a vector, all parameters are converted to vectors and the result is a vector. Otherwise all parameters are converted to floats and the result is a float.

* float
calcNormals
(p1,​p2​[,helper]​[,r]])
This function calculates 3 right-angled normals (index 0..2) for the vector 'p1..p2', 'normal[0]' is the direction of this vector. Is 'helper' is set, it is used to determine the direction of normal[1]. All 3 normals are multiplied by the factor 'r'. The function returns the distance between 'p1' and 'p2'. To get the normals, use function getNormal().
KMP int
came$n
()
Returns the number of cameras.
KMP int
came$next
(came_idx)
Returns -1 or the link to the next camera.
KMP int
came$ocam
()
Returns the index of the opening camera.
KMP vector
came$pos
(came_idx)
Returns the position of a camera.
KMP int
came$route
(came_idx)
Returns -1 or the link to the related route.
KMP int
came$scam
()
Returns the index of the selection camera.
KMP float
came$time
(came_idx)
Returns the run time of a camera in 1/60 sec.
KMP int
came$type
(came_idx)
Returns the type of a camera.
KMP int
came$unknown_02
(came_idx)
Returns the unknown value at offser 0x02 of a camera.
KMP int
came$unknown_04
(came_idx)
Returns the unknown value at offser 0x04 of a camera.
KMP int
came$unknown_0a
(came_idx)
Returns the unknown value at offser 0x0a of a camera.
KMP vector
came$unknown_18
(came_idx)
Returns the unknown value at offser 0x18 of a camera.
KMP vector
came$viewpt_begin
(came_idx)
Returns the start position of the view point.
KMP vector
came$viewpt_end
(came_idx)
Returns the end position of the view point.
KMP int
came$viewpt_speed
(came_idx)
Returns the view point speed in units per 100/60 sec.
KMP float
came$zoom_begin
(came_idx)
Returns the zoom beginning angle of a camera.
KMP float
came$zoom_end
(came_idx)
Returns the zoom ending angle of a camera.
KMP int
came$zoom_speed
(came_idx)
Returns the zoom speed in units per 100/60 sec.
* *
ceil
(val)
Returns the smallest integral value that is not less than 'val'. If 'val' is a vector, the calculation is done for each component. The return type is identical to the type of 'val'.
* int
chat$n_races
(n)
Create a chat modus for LE-CODE setup. N is a values between 1 and 512 and defines the number of races. The parameters are used to select random scenarios between 1 and 8.
* int
chat$vehicles
(...)
Create a chat modus for a vehicle group. 0 to N values are expected as function parameters. Each parameter is either from the group VEH$SMALL, VEH$MEDIUM, VEH$LARGE and VEH$ANY_SIZE for size selections and/or from the group VEH$KART, VEH$OUT_BIKE, VEH$IN_BIKE, VEH$BIKE, VEH$ANY_TYPE for type selections. Negative values are an alias for 'all of group except'. VEH$ANY is a short cut for VEH$ANY_SIZE,VEH$ANY_TYPE.
KMP int
ckph$len
(ckph_idx)
Returns the number of check points of a check point group.
KMP int
ckph$n
()
Returns the number of check point groups.
KMP int
ckph$next
(ckph_idx,​val_idx)
Returns link 0..5 to the next check point group.
KMP int
ckph$prev
(ckph_idx,​val_idx)
Returns link 0..5 to the previous check point group.
KMP int
ckph$start
(ckph_idx)
Returns the check point start index of a check point group.
KMP int
ckph$unknown
(ckph_idx)
Returns the unknown value of a check point group.
KMP vector
ckpt$left
(ckpt_idx)
Returns the left position of a check point.
KMP int
ckpt$mode
(ckpt_idx)
Returns the mode of check point.
KMP int
ckpt$n
()
Returns the number of check points.
KMP int
ckpt$next
(ckpt_idx)
Returns the index of the next check point.
KMP int
ckpt$prev
(ckpt_idx)
Returns the index of the previous check point.
KMP int
ckpt$respawn
(ckpt_idx)
Returns the respawn index of a check point.
KMP vector
ckpt$right
(ckpt_idx)
Returns the right position of a check point.
KMP int
cnpt$effect
(cnpt_idx)
Returns the efffect value of a canon point.
KMP int
cnpt$id
(cnpt_idx)
Returns the ID of a canon point.
KMP int
cnpt$n
()
Returns the number of canon point points.
KMP vector
cnpt$pos
(cnpt_idx)
Returns the position of a canon point.
KMP vector
cnpt$rot
(cnpt_idx)
Returns the rotation of a canon point.
* flt|vec
cos
(val)
Returns the cosine of 'val', where 'val' is given in degree. If 'val' is a vector, the cosine of each component is calculated.
* vector
cross
(v1,​v2)
Returns the cross product of the 2 vectors 'v1' and 'v2'.
* float
dir
([v1,​]v2)
The 3D direction in degree from position 'v1' to 'v2' is calculated. If 'v1' is not set, v(0,0,0) is used. The Z coordiante of the result is always 0.0.
* float
dot
(v1,​v2)
Returns the dot product of the 2 vectors 'v1' and 'v2'.
* *
echo
(p1,​...)
This debug function prints all parameters, each in a separate line, and returns the first parameter.
KMP int
enph$len
(enph_idx)
Returns the number of enemy points of an enemy point group.
KMP int
enph$n
()
Returns the number of enemy point groups.
KMP int
enph$next
(enph_idx,​val_idx)
Returns link 0..5 to the next enemy point group.
KMP int
enph$prev
(enph_idx,​val_idx)
Returns link 0..5 to the previous enemy point group.
KMP int
enph$start
(enph_idx)
Returns the enemy point start index of an enemy point group.
KMP int
enph$unknown
(enph_idx)
Returns the unknown value of an enemy point group.
KMP float
enpt$hDir
(enpt_index​[,next_index])
Calculate the horizontal direction in degree of an enemy point. The 'next_index' is only used, if multiple links are available.
KMP int
enpt$n
()
Returns the number of enemy points.
KMP int
enpt$next
(enpt_index​[,next_index])
Returns the index of the next enemy point. The 'next_index' is only used, if multiple links are available.
KMP vector
enpt$pos
(enpt_idx)
Returns the position of an enemy point.
KMP int
enpt$prop
(enpt_idx,​val_idx)
Returns property 0 or 1 of an enemy point.
KMP float
enpt$scale
(enpt_idx)
Returns the scale of an enemy point.
* flt|vec
exp
(val)
Returns the value of e (the base of natural logarithms) raised to the power of 'val'. If 'val' is a vector, the calculation is done for each component.
* str
extract
(str,​pos1,​pos2)
Extract all characters of string STR including position POS1 and excluding position POS2. Positions <0 are relative to the end of STR and adjusted. If POS1 ëÑPOS2, an empty string is returned.
* float
float
(val)
Converts 'val' to a float value. Strings are scanned for a float.
* *
floor
(val)
Returns the largest integral value that is not greater than 'val'. If 'val' is a vector, the calculation is done for each component. The return type is identical to the type of 'val'.
* vector
getNormal
(index)
This function returns the normal 'index' (0..2) of the last call of function calcNormals(). If 'index' is invalid, $NONE is returned.
KMP int
gobj$id
(gobj_idx)
Returns the object ID of a global object.
KMP int
gobj$n
()
Returns the number of global objects.
KMP int
gobj$pflags
(gobj_idx)
Returns the presence flags of a global object.
KMP vector
gobj$pos
(gobj_idx)
Returns the position of a global object.
KMP vector
gobj$rot
(gobj_idx)
Returns the rotation of a global object.
KMP int
gobj$route
(gobj_idx)
Returns -1 or the index of a related route of a global object.
KMP vector
gobj$scale
(gobj_idx)
Returns the scale of a global object.
KMP int
gobj$set
(gobj_idx,​val_idx)
Returns setting 0..7 of a global object.
KMP int
gobj$unknown
(gobj_idx)
Returns the unknown value of a global object.
* float
hDir
([v1,​]v2)
'hDir()' is the old name for 'yDir()'. The horizontal direction in degree from position 'v1' to 'v2' is calculated. If 'v1' is not set, v(0,0,0) is used.
* float
hLen
(v1​[,v2])
Returns the horizontal length of the vector 'v1' (ignoring the y component). If 'v2' is set, the horizontal distance of both points is returned.
* float
hLen2
(v1​[,v2])
Returns the square of the horizontal length of the vector 'v1' (ignoring the y component). If 'v2' is set, the horizontal square distance of both points is returned.
* vector
hRot
(pt,​deg​[,origin])
'hRot()' is the old name for 'yRot()'. The point 'pt' is horizontal rotated around 'origin' by 'deg' degree. If 'pt' is a scalar, 'vz(pt)' is used. If 'origin' is not set, v(0,0,0) is used.
* int
if$engine
(...)
Create a condition for KMP/GOBJ references. The parameters are used to select engine types. Available values: EN$BATTLE, EN$50, EN$100, EN$150 and EN$200. Use EN$150M, EN$200M for mirror modes. Additional short cuts: EN$150X for EN$150,EN$150M, EN$200X for EN$200,EN$200M, and EN$MIRROR for EN$150M,EN$200M. A negative index deselects an engine mode. '*' is a short cut for all modes.
* int
if$random
(...)
Create a condition for KMP/GOBJ references. The parameters are used to select random scenarios between 1 and 8. A negative value deselects a scenario. '*' is a short cut for the parameter list '1,2,3,4,5,6,7,8'.
* int
ifLevel
()
This debug function returns the current IF..ENDIF level (number of active '@if's).
* int
int
(val)
Converts 'val' to an integer value. Strings are scanned for an integer.
* int
isDef
(name)
Returns 2, if variable 'name' is defined, or 1, if a variable with the base name is defined as vector, or 0, if it is not defined.
* int
isFloat
(name)
Returns 2, if variable 'name' is defined as float with a value >0, or 1, if it is a float with a value <=0. Otherwise it returns 0.
* int
isFunction
(name)
Returns 1, if 'name' is defined as system function, or 2, if 'name' is defined as user function, or 3, if 'name' is defined as system and as user function. Otherwise it's not a function and 0 is returned.
* int
isInt
(name)
Returns 2, if variable 'name' is defined as an integer with a value >0, or 1, if it is an integer with a value <=0. Otherwise it returns 0.
* int
isKCL
()
Returns 2, if the source is a KCL or OBJ named 'course.kcl' or 'course.txt' or 'course.txt.kcl', 1 if the source is any other KCL or OBJ, and 0 else.
* int
isKMP
()
Returns 2, if the source is a KMP (binary or text) named 'course.kmp' or 'course.txt' or 'course.txt.kmp', 1 if the source is any other KMP (binary or text), and 0 else.
* int
isLEX
()
Returns 2, if the source is a LEX (binary or text) named 'course.lex' or 'course.txt' or 'course.txt.lex', 1 if the source is any other LEX (binary or text), and 0 else.
* int
isMacro
(name)
Returns 2, if 'name' is defined as user function, or 1, if 'name' is defined as simple macro. Otherwise it's not a macro or user function and 0 is returned.
* int
isMDL
()
Returns 1, if the source is a MDL (binary or text). Otherwise it returns 0.
* int
isNumeric
(name)
Returns 1, if variable 'name' is an integer, float or vector. Otherwise it returns 0.
* int
isScalar
(name)
Returns 2, if variable 'name' is an integer or float with a value >0, or 1, if it is an integer or float with a value <=0. Otherwise it returns 0.
* int
isStr
(name)
Returns 2, if variable 'name' is defined as string with 1 or more characters, or 1, if it is a string without characters. Otherwise it returns 0.
* int
isVector
(name)
Returns 1, if variable 'name' is defined as vector. Otherwise it returns 0.
KMP int
itph$len
(itph_idx)
Returns the number of item points of an item point group.
KMP int
itph$n
()
Returns the number of item point groups.
KMP int
itph$next
(itph_idx,​val_idx)
Returns link 0..5 to the next item point group.
KMP int
itph$prev
(itph_idx,​val_idx)
Returns link 0..5 to the previous item point group.
KMP int
itph$start
(itph_idx)
Returns the item point start index of an item point group.
KMP int
itph$unknown
(itph_idx)
Returns the unknown value of an item point group.
KMP float
itpt$hDir
(itpt_index​[,next_index])
Calculate the horizontal direction in degree of an item point. The 'next_index' is only used, if multiple links are available.
KMP int
itpt$n
()
Returns the number of item points.
KMP int
itpt$next
(itpt_index​[,next_index])
Returns the index of the next item point. The 'next_index' is only used, if multiple links are available.
KMP vector
itpt$pos
(itpt_idx)
Returns the position of an item point.
KMP int
itpt$prop
(itpt_idx,​val_idx)
Returns property 0 or 1 of an item point.
KMP float
itpt$scale
(itpt_idx)
Returns the scale of an item point.
KMP int
jgpt$effect
(jgpt_idx)
Returns the effect value of a respawn point.
KMP int
jgpt$id
(jgpt_idx)
Returns the ID of a respawn point.
KMP int
jgpt$n
()
Returns the number of respan points.
KMP vector
jgpt$pos
(jgpt_idx)
Returns the position of a respawn point.
KMP vector
jgpt$rot
(jgpt_idx)
Returns the rotation of a respawn point.
* vector
kcl$fall
(pt,​width​[,typemask])
If a reference KCL is defined, search the lowest point below 'pt', that can be reached without collision. The point is expanded to a cube with edge length 'width' for the collision tests. If 'typemask' is set, only KCL types with related bit number set are recognized. Use kcl$fallFlag() to get the corespondent KCL flag.
* int
kcl$fallFlag
()
This functions returns the corespondent KCL flag of the last call of kcl$fall(). The return value is the KCL flag of the colliding triangle, or -1 if no collision was found.
KMP int
ktpt$id
(ktpt_idx)
Returns a start point ID.
KMP int
ktpt$n
()
Returns the number of start points.
KMP vector
ktpt$pos
(ktpt_idx)
Returns a start point position.
KMP vector
ktpt$rot
(ktpt_idx)
Returns a start point rotation.
KMP int
ktpt$unknown
(ktpt_idx)
Returns the unknown value of a start point.
* int
le
(val,​n)
Convert 'val' to integer, limit it to 'n' bytes (1-8) and mark it for little endian usage.
* str
left
(str,​len)
Extract the left LEN characters of string STR. If LEN<0, then extract all but not the last -LEN characters.
* int/flt
len
(v1​[,v2])
If 'v1' is a string, then 'v2' is ignored and the length of the string is returned as integer. Otherwise the length of the vector 'v1' is returned as float. If 'v2' is set, the distance of both points is returned.
* float
len2
(v1​[,v2])
Returns the square of the length of the vector 'v1'. If 'v2' is set, the square distance of both points is returned.
* int
line
()
This debug function returns the current line number.
* flt|vec
log
(val​[,base])
If base is not set or invalid, the function returns the natural logarithm of 'val'. Otherwise base is converted to a float and logarithm with the entered base is returned (=log(val)/log(base)). If 'val' is a vector, the calculation is done for each component.
* int
loopCount
([level])
This debug function returns the loop counter of the specified loop level. If 'level' is omitted, the loop count of the current loop is returned.
* int
loopLevel
()
This debug function returns the current loop level (number of active loops).
* *
max
(p1,​...)
Returns the maximum value of all parameters. If at least one parameter is a vector, the result is a vector too and the maximum value of each component is calculated.
* *
mean
(p1,​...)
Returns the arithmetic mean of all parameters. If at least one parameter is a vector, the result is a vector too and the maximum value of each component is calculated. The result type is UNSET, FLOAT or VECTOR, but never INT.
* str
mid
(str,​pos​[,len])
Extract LEN characters of string STR beginning at postition POS. If POS<0, then a position relative to the end of STR is used. If LEN<0, then extract all but not the last -LEN characters. If LEN is not set, then extract all characters until end of string.
* *
min
(p1,​...)
Returns the minimum value of all parameters. If at least one parameter is a vector, the result is a vector too and the minimum value of each component is calculated.
* *
minMax
(val,​minval,​maxval)
Returns 'max(min(val,minval),maxval)': Limit the value 'val' by 'minval' and 'maxval'. The return type is identical to the type of 'val'.
* int
mSec
()
Returns the number of milliseconds since an unspecific timer start. Use differences between 2 calls to get the elapsed time. The 3 functions sec(), mSec() and uSec() use the same time base.
KMP int
mspt$effect
(mspt_idx)
Returns the efffect value of a battle point.
KMP int
mspt$id
(mspt_idx)
Returns the ID of a battle point.
KMP int
mspt$n
()
Returns the number of battle points.
KMP vector
mspt$pos
(mspt_idx)
Returns the position of a battle point.
KMP vector
mspt$rot
(mspt_idx)
Returns the rotation of a battle point.
* *
param
(index)
Returns the value of the macro or function parameter with the entered 1-based index. Therefor the private variable '$N' and one of '$1', '$2', ... are read.
* flt|vec
pos
(pos,​p1,​p2)
This function returns the relative position 'pos' on the axis 'p1' to 'p2' by calculating 'p1+pos*(p2-p1)'. If one of the 3 arguments is a vector, the result is also a vector.
KMP int
poti$back
(route_idx)
Returns the forward+backward value of a route (route header byte at offset 0x03).
KMP int
poti$n
()
Returns the number of routes.
KMP int
poti$nn
()
Returns the total number of points of all routes.
KMP int
poti$np
(route_idx)
Returns the number of points of a route.
KMP vector
poti$pos
(route_idx,​pt_idx)
Returns the position of a point of a route. The point index is relative to the route.
KMP int
poti$set
(route_idx,​pt_idx,​val_idx)
Returns setting 0 or 1 of a point of a route. The point index is relative to the route.
KMP int
poti$smooth
(route_idx)
Returns the smooth value of a route (route header byte at offset 0x02).
* flt|vec
pow
(a,​b)
Returns the value of 'a' raised to the power of 'b'. If 'a' is a vector, each component is raised by 'b'. The operator ** does the same, but have integer support.
* str
print
(format,​...)
Create a string like sprintf() of other programming languages. See https://szs.wiimm.de/doc/print for details.
* int
ptInConvexPolygon
(pt,​p1,​..,​pN)
All parameters are converted into vectors, but only the x and z coordinates are used. 'p1..pN' are up to 100 vertices of a convex polygon. The function returns 1, if the point 'pt' is inside the polygon (including the lines), and 0 otherwise.

Function status() will return the direction of the polygon: -1 for counterclockwise, +1 for clockwise and 0 for unknown.

* int
ptsInConvexQuad
(q1,​q2,​q3,​q4,​pt1,​...,​ptN)
All parameters are converted into vectors, but only the x and z coordinates are used. 'q1..q4' define a convex quadrilateral, and 'pt1..ptN' is a list of up to 100 points. The functions returns the number of points, that are inside the quadrilateral. Points on the line are counted as inside too.

Function status() will return the direction of the quadrilateral: -1 for counterclockwise, +1 for clockwise and 0 for unknown.

* int
ptsInConvexTri
(t1,​t2,​t3,​pt1,​...,​ptN)
All parameters are converted into vectors, but only the x and z coordinates are used. 't1..t3' define a convex triangle, and 'pt1..ptN' is a list of up to 100 points. The functions returns the number of points, that are inside the triangle. Points on the line are counted as inside too.

Function status() will return the direction of the triangle: -1 for counterclockwise, +1 for clockwise and 0 for unknown.

* int
ptsInCuboid
(cube_min,​cube_max,​pt1,​...)
All parameters are converted to vectors. 'cube_*' describe 2 diagonal corners of a rectangular cuboid, assuming that 'cube_min<=cube_max' is true for each coordinate. The functions returns the number of points ('pt1', 'pt2', ...) that are inside of the cube including the border.
* int
ptsInCuboidS
(cube1,​cube2,​pt1,​...)
This is the sloppy version of ptInCuboid(): All parameters are converted to vectors. 'cube*' describe any 2 diagonal corners of a rectangular cuboid. The functions returns the number of points ('pt1', 'pt2', ...) that are inside of the cube including the border.
* *
random
([max])
Returns a random number between 0 and 'max', but never equal 'max'. The return type is identical to the type of 'max'. If 'max' is not set, use float 1.0 instead. If 'max' is a vector, a vector with three random floats will be returned.
* str
remove
(str,​pos1,​pos2)
Create a copy of string STR and remove all characters including position POS1 and excluding position POS2. Positions <0 are relative to the end of STR and adjusted. If POS1 ëÑPOS2, nothing is removed and the complete STR is returned.
* *
result
()
Returns the last include, macro or function result. The value is usually '$NONE', unless the command '@RETURN' is used.
* str
right
(str,​len)
Extract the right LEN characters of string STR. If LEN<0, then extract all but not the first -LEN characters.
* vector
rot
(pt,​deg_vector​[,origin])
The point 'pt' is rotated around 'origin'. The rotation is done for the x-, y- and z-axis in this order. All parameters are converted to vectors before the operation. If 'origin' is not set, v(0,0,0) is used.
* *
round
(val)
Returns the rounded integer value of 'val'. If 'val' is a vector, the calculation is done for each component. The return type is identical to the type of 'val'.
* scalar
scalar
(val)
If 'val' is a string, it is scanned for a number and converted first. If 'val' is a float or a vector, a float value is returned. Otherwise an integer value is returned.
* *
scanExpr
(val)
If 'val' is a string, scan it for an expression. Otherwise return 'val'.
* *
scanVal
(val)
If 'val' is a string, scan it for a value. Otherwise return 'val'.
* int
sec
()
Returns the number of seconds since an unspecific timer start. Use differences between 2 calls to get the elapsed time. The 3 functions sec(), mSec() and uSec() use the same time base.
* *
select
(sel,​p0,​p1,​...,​pN)
First convert 'sel' to an integer. If 'sel' is less or equal 0, 'p0' is returned. If 'sel' is greater or equal N, 'pN' is returned. Otherwise 'sel' is between 0 and N and 'p(sel)' is returned.
* int
sideOfLine
(a,​b,​pt)
All parameters are converted into vectors, but only the x and z coordinates are used. Vectors 'a' and 'b' define a line (from a to b). The function returns -1, if the point 'pt' is on the left side of the line, or +1, if the point is on the right side, or 0 if the point is on the line.
* *
sign
(val)
Returns the sign of 'val': -1 if 'val<0'; 0, if 'val==0'; +1 if 'val>0'. If 'val' is a vector, the sign of each component is calculated. The return type is identical to the type of 'val'.
* flt|vec
sin
(val)
Returns the sine of 'val', where 'val' is given in degree. If 'val' is a vector, the sine of each component is calculated.
* int
sourceLevel
()
This debug function returns the current source level (number of open files and macros).
* flt|vec
sqrt
(val)
Returns the nonnegative square root of 'abs(val)'. If 'val' is a vector, the square root of each component is calculated.
* int
status
()
Some functions support a return value and an additionally status. This function will return the last set status.
KMP int
stgi$byte
(stgi_idx,​val_idx)
Returns setting byte 0..11 of a stage info.
KMP int
stgi$n
()
Returns the number of stage infos.
* str
str
(val)
Converts 'val' to a string value.
* flt|vec
tan
(val)
Returns the tangent of 'val', where 'val' is given in degree. If 'val' is a vector, the tangent of each component is calculated.
KCL int
tri$create
(kcl_flag,​pt0,​pt1,​pt2,​...)
This function appends new triangles at the end of the triangle list with the entered parameters. If more than 3 points are entered, all points must be in the same plane and the polygon is split into multiple (N-2) triangles. The function returns the index of the first new triangle or -1 if failed.
KCL int
tri$createAntiArrow
(flag,​pt1,​pt2,​ptX,​r,​n,​a_flag​[,a_size]​[,b_flag]​[,b_ht])
This function creates an antiprism based arrow with radius 'r' and N faces from 'pt1' to 'pt2', where 'pt2' is the place of the arrowhead. The point 'ptX' is used for the orientation (direction of first edge). 'flag', 'a_flag' and 'b_flag' are KCL flags to define the color. 'a_size' is the addition size factor of the arrowhead, the default is 1.0. If 'b_flag' is not set or @-1@, no base is drawn. If 'base_height' is set, a pyramid is drawn as base. The function returns the index of the first new triangle or -1 if failed.
KCL int
tri$createAntiPrism
(kcl_flag,​pt1,​pt2,​ptX,​r,​n​[,base_flag]​[,base_height])
This function creates an antiprism with radius 'r' and N faces from 'pt1' to 'pt2' by adding 2*N triangles. The point 'ptX' is used for the orientation (direction of first edge). If 'base_flag' is set and not @-1@, the base is printed with ths kcl flag value. If 'base_height' is set, a pyramid is drawn as base. The function returns the index of the first new triangle or -1 if failed.
KCL int
tri$createArrow
(flag,​pt1,​pt2,​ptX,​r,​n,​a_flag​[,a_size]​[,b_flag]​[,b_ht])
This function creates a prism based arrow with radius 'r' and N faces from 'pt1' to 'pt2', where 'pt2' is the place of the arrowhead. The point 'ptX' is used for the orientation (direction of first edge). 'flag', 'a_flag' and 'b_flag' are KCL flags to define the color. 'a_size' is the addition size factor of the arrowhead, the default is 1.0. If 'b_flag' is not set or @-1@, no base is drawn. If 'base_height' is set, a pyramid is drawn as base. The function returns the index of the first new triangle or -1 if failed.
KCL int
tri$createCuboid
(kcl_flag,​pos,​size​[,rot])
This function creates a cuboid by adding 12 triangles. If 'size' is a scalar, a cube with the entered edge length is created. If 'rot' is set, the cube is rotated. As last operation the center (origin) of the cube is shifted to 'pos'. The function returns the index of the first new triangle or -1 if failed.
KCL int
tri$createJoist
(kcl_flag,​length,​pt1,​pt2,​pt_dir​[,n_marker]​[,mark5_flag])
This function appends a triangular joist from 'p1' to 'p2' to at the end of the triangle list. 'length' the length of the body and 'pt_dir' is a helper point for its direction. If 'n_marker' is >0, markers representing the number are added. If 'mark5_flag' is >0, every 5 markers are replaced by one of the entered flag. The function returns the index of the first new triangle or -1 if failed.
KCL int
tri$createOctahedron
(kcl_flag,​pos,​radius​[,rot])
This function creates a octahedron by adding 8 triangles. If 'radius' is a scalar, a regular octahedron created. Otherwise it is a vector and define different radiuses for each axis. If 'rot' is set, the octahedron is rotated. As last operation the center (origin) of the cube is shifted to 'pos'. The function returns the index of the first new triangle or -1 if failed.
KCL int
tri$createPrism
(kcl_flag,​pt1,​pt2,​ptX,​r,​n​[,base_flag]​[,base_height])
This function creates a prism with radius 'r' and N faces from 'pt1' to 'pt2' by adding 2*N triangles. The point 'ptX' is used for the orientation (direction of first edge). If 'base_flag' is set and not @-1@, the base is printed with ths kcl flag value. If 'base_height' is set, a pyramid is drawn as base. The function returns the index of the first new triangle or -1 if failed.
KCL int
tri$createPyramid
(kcl_flag,​apex,​pt1,​pt2,​...)
This function creates a pyramid by adding N triangles. 'pt1'..'ptN' descibribes the base polygon, which is not created. The function returns the index of the first new triangle or -1 if failed.
KCL int
tri$defColor
(argb​[,alpha])
Define a new color. 'ARGB' is a bytes coded color: alpha,red,green,blue. If 'ALPHA' is not set, the highest byte of 'ARGB' is used. If this highest byte is null, 0xff (no transparency) is used. The function returns -1, if already 200 colors defined. Otherwise it returns the virtual KCL flag for the user defined color.
KCL int
tri$defColor
(red,​green,​blue​[,alpha])
Define a new color. If ALPHA is not set, 0xff (no transparency) is used. For the 3 colors, values between 0x00 and 0xff are expected. The function returns -1, if already 200 colors defined. Otherwise it returns the virtual KCL flag for the user defined color.
KCL int
tri$flag
(tri_index​[,mode])
This function returns the KCL flag of the triangle 'tri_index' (0..). If mode is '1', the original source value is returned. If mode is '2', the original source value transformed by --kcl-flag is returned; if --kcl-flag is not set, it is the same as mode '1'. Otherwise the current value is returned. The current value is initialized by the value of mode '2'. Values >0xffff are possible and represent internal drawings.
KCL int
tri$getColor
(index)
This function returns the color defined by a previous tri$defColor() call. INDEX is the virtual KCL flag for the user defined color. On error, the value NONE (type 'undefined') is returned.
KCL int
tri$hRot
(tri_index,​degree​[,origin])
This function rotates the triangle 'tri_index' (0..) horizontal counterclockwise by the angle 'degree' around the point 'origin'. If the origin is not set, v(0,0,0) is used instead.
KCL int
tri$isRemoved
(tri_index)
This returns the status of the 'REMOVED' marker of the triangle 'tri_index' (0..). The return value is -1 for an invalid index, 1 if the triangle is marked as removed or 0 if not.
KCL float
tri$length
(tri_index)
This function returns the length of triangle 'tri_index' (0..).
KCL vector
tri$n
()
This function returns the number of triangles.
KCL vector
tri$normal
(tri_index,​norm_index)
This function returns the normal with index 'norm_index' (0..3) of triangle 'tri_index' (0..).
KCL vector
tri$pt
(tri_index,​pt_index)
This function returns the point with index 'pt_index' (0..2) of triangle 'tri_index' (0..).
KCL int
tri$ptsInCuboid
(tri_index,​cube_min,​cube_max)
Parameters 'cube_*' are converted to vectors. They describe 2 diagonal corners of a rectangular cuboid, assuming that 'cube_min<=cube_max' is true for each coordinate. The functions returns the number of points of the triangle 'tri_index' (0..), that are inside of the cube including the border. If 'tri_index' is invalid, -1 is returned.
KCL int
tri$remove
(tri_index)
This function marks the triangle 'tri_index' (0..) as 'REMOVED'. The return value is -1 for an invalid index, 1 if the triangle was already removed or 0 if not.
KCL int
tri$scale
(tri_index,​scale​[,origin])
This function scales the triangle 'tri_index' (0..) by the vector 'scale' relative to point 'origin'. If the origin is not set, v(0,0,0) is used instead.
KCL int
tri$setFlag
(tri_index,​new_flag)
This function sets the new KCL flag of triangle 'tri_index' (0..). The function returns -1 for an invalid index or the previous value of the KCL flag.
KCL int
tri$setPt
(tri_index,​pt0,​pt1,​pt2)
This function sets the coordinates of all 3 points of the triangle 'tri_index' (0..) to the vectors 'pt*'.
KCL int
tri$setPt
(tri_index,​pt_index,​pt)
This function sets the coordinates of the single point with index 'pt_index' (0..2) of triangle 'tri_index' (0..). to the vector 'pt'.
KCL int
tri$shift
(tri_index,​shift)
This function adds the vector 'shift' to all 3 points of the triangle 'tri_index' (0..).
KCL int
tri$type
(tri_index​[,mode])
This function returns the KCL type of the triangle 'tri_index' (0..). It works like tri$flag(), but the flag is transformed to a type. The return value is in the range of 0x00..0x1f (5 lowest bits of the flag), if it is a real KCL flag (<0x10000), or -1 otherwise (special type).
KCL int
tri$unremove
(tri_index)
This function clears the 'REMOVED' marker of the triangle 'tri_index' (0..). The return value is -1 for an invalid index, 1 if the triangle was removed or 0 if not.
* *
trunc
(val)
Returns the nearest integer not larger in absolute value than 'val' (rounding towards zero). If 'val' is a vector, the calculation is done for each component. The return type is identical to the type of 'val'.
* int
type
(name)
Returns the type of the variable 'name' (TYPE$UNSET, TYPE$INT, TYPE$FLOAT, TYPE$VECTOR, TYPE$STR, TYPE$X, TYPE$Y, TYPE$Z) or value 'TYPE$UNDEF', if it is not defined. It is guaranteed, that 'TYPE$UNDEF < TYPE$UNSET < all_others'.
* vector
unit
(v1​[,v2])
Returns the unit vector of the vector 'v1'. If 'v2' is set, then the unit vector for the difference 'v2-v1' is returned.
* int
uSec
()
Returns the number of microseconds since an unspecific timer start. Use differences between 2 calls to get the elapsed time. This timer has an overflow at about 35 minutes. The 3 functions sec(), mSec() and uSec() use the same time base.
* vector
v
([val])
Defines a vector. If 'val' is a vector, it is copied. Otherwise 'val' is used for the x coordinate and y and z are set to 0.0. If 'val' is not set, 0.0 is used.

This function is used if an internal conversion to a vector is needed.

* vector
v
(x​[,y],​z)
Defines a vector by using the entered coordinates. If 'y' is not set, use 0.0 instead. If 'x', 'y' or 'z' is a vector itself, the corespondent coordinate is used.
* vector
v3
(val)
Create a vector with all 3 components equal to 'val'
* *
var
(name,​val)
If variable 'name' is defined and valid, return its value. Otherwise return 'val'.
* vector
vd
(len,​deg​[,y])
Creates a vector of length 'len' and horizontal angle 'deg' (degree). Value 'y' (if not set: 0.0) is used for the height.
* vector
vx
(x​[,v])
Read the vector 'v' and replace the x component by 'x'. If 'x' is a vector, its x component is used. If 'v' is not set, use v(0,0,0) instead.
* vector
vy
(y​[,v])
Read the vector 'v' and replace the y component by 'y'. If 'y' is a vector, its y component is used. If 'v' is not set, use v(0,0,0) instead.
* vector
vz
(z​[,v])
Read the vector 'v' and replace the z component by 'z'. If 'z' is a vector, its z component is used. If 'v' is not set, use v(0,0,0) instead.
* float
x
(val_1,​...,​val_n)
Scan all parameters (at least 1 must exist) and find the first vector. If found, return its x component. If no vector exists, return the last value 'val_n'.

Confirming the rules above, 'x(val)' means: If 'val' is a vector, return its x component. Otherwise convert 'val' to a float and return it.

* float
xDir
([v1,​]v2)
The functions returns the direction in degree of point 'v2' relative to the x-axis of point 'v1'. If 'v1' is not set, v(0,0,0) is used.
* vector
xRot
(pt,​deg​[,origin])
The point 'pt' is rotated around the x-axis of 'origin' by 'deg' degree. If 'pt' is a scalar, 'vy(pt)' is used. If 'origin' is not set, v(0,0,0) is used.
* float
y
(val_1,​...,​val_n)
Scan all parameters (at least 1 must exist) and find the first vector. If found, return its y component. If no vector exists, return the last value 'val_n'.

Confirming the rules above, 'y(val)' means: If 'val' is a vector, return its y component. Otherwise convert 'val' to a float and return it.

* float
yDir
([v1,​]v2)
The functions returns the direction in degree of point 'v2' relative to the y-axis of point 'v1'. If 'v1' is not set, v(0,0,0) is used.
* vector
yRot
(pt,​deg​[,origin])
The point 'pt' is rotated around the y-axis of 'origin' by 'deg' degree. If 'pt' is a scalar, 'vz(pt)' is used. If 'origin' is not set, v(0,0,0) is used. This is the classical horizontal rotation.
* float
z
(val_1,​...,​val_n)
Scan all parameters (at least 1 must exist) and find the first vector. If found, return its z component. If no vector exists, return the last value 'val_n'.

Confirming the rules above, 'z(val)' means: If 'val' is a vector, return its z component. Otherwise convert 'val' to a float and return it.

* float
zDir
([v1,​]v2)
The functions returns the direction in degree of point 'v2' relative to the z-axis of point 'v1'. If 'v1' is not set, v(0,0,0) is used.
* vector
zRot
(pt,​deg​[,origin])
The point 'pt' is rotated around the z-axis of 'origin' by 'deg' degree. If 'pt' is a scalar, 'vx(pt)' is used. If 'origin' is not set, v(0,0,0) is used.
The commands wszst FUNCTIONS, wkclt FUNCTIONS and wkmpt FUNCTIONS print a function list too.

4.2   Function print()

As of version v1.62a, the parser supports the data type string and some string functions. One of it is function print(). It produce output according to a format as described below. It is like functions sprintf() in other programming languages.

The general syntax: print( format, arguments, ... )

4.2.1   Format of the format string

The format string is a character string. The format string is composed of zero or more directives: ordinary characters (not %), which are copied unchanged to the output stream; and conversion specifications, each of which results in fetching zero or more subsequent arguments. Each conversion specification is introduced by the character %, and ends with a conversion specifier (conv). In between there may be (in this order) an optional argument index, zero or more flags, an optional minimum field width (fw), an optional precision (prec) and an optional modifier.

Syntax: "%" [ index "$"] [flags] [fw] ["." prec] [modifier] conv

The arguments are automatically converted to the requested data type. By default, the arguments are used in the order given, where each '*' (see Field width and Precision below) and each conversion specifier asks for the next argument. One can also specify explicitly which argument is taken, at each place where an argument is required, by writing "%m$" instead of '%' and "*m$" instead of '*', where the decimal integer m denotes the position in the argument list of the desired argument, indexed starting from 1.

4.2.2   Optional index

???

4.2.3   Optional flags

???
 #  alternative format
 0  zero padding
 -  left adjusted
    blank before a positive number
 +  '+' before a positive number (ignore blank above)
 >  sign at right side of int
 '  enable grouping of integers
 "  quote strings

4.2.4   Optional field width

???

4.2.5   Optional precision

???

4.2.6   Optional modifiers

???
 n  data type must match conversion character
 N  Like 'n', but also for FLOAT and VECTOR
 v  Print vectors as "v(x,y,z)" instead of "x,y,z"
 V  Force vector output for FLOATS.

4.2.7   Mandatory conversion character

???
 h    Print all datatypes in human readable format (one of d,f|g,s)
 y    Print all datatypes in machine readable format without loss of precision (d,a,s)

 d,i  Print signed integer
 u    Print unsigned integer
 b    Print unsigned integer (base 2, dual)
 o    Print unsigned integer (base 8, octal)
 x,X  Print unsigned integer (base 16, hexadecimal)

 f,F  Print float or vector as fixed numbers.
 e,E  Print float or vector with exponents.
 g,G  Print float or vector either in e,E or in f,F format
 a,A  Print float or vector in hexadecimal without loss of precision

 s    Print string.

 q    Print nothing, but disable warnings.

5.   Multiple text files

The source file can be divided into spearate files. The following commands control the input flow:

Syntax:

  INCLUDE := '@INCLUDE' '"' path/to/filename '"'
  EXEC    := ( '@EXEC | '@>' )  STRING_EXRESSION
  RETURN  := '@RETURN' [ EXRESSION ]
  EXIT    := '@EXIT'
  ASSERT  := '@ASSERT' EXRESSION

5.1   @INCLUDE "path/to/filename"

A file with the entered filename is searched. The path is relative to the directory of the current source file.

If the source file exists, then its content is virtually inserted into the current source file instead of the include command.

5.2   @EXEC string_exression

The expression is converted to a string. The result is virtually inserted into the current source file (like @INCLUDE) with respect for LF (LineFeed) as line separator.

Instead of '@exec exression' the shorter '@>exression' can be used.

This command is available since v1.62a (string support).

5.3   @RETURN [ expression ]

Normally a source file (or macros or functions) is read line by line until reaching the end of the source. The '@RETURN' command terminates the scanning of the current source (file, macro or function) and returns to the calling source.

The result of the expression is stored and can be accessed by the function result() or as function result (see below). If no expression is entered, the value $NONE is used.

5.4   @EXIT

The command '@EXIT' closes all sources of all levels (files, macros and functions) and terminates the scanning of the source. (See also command @FUNCTION.)

5.5   @ASSERT condition

The command '@ASSERT' closes all sources (files, macros and functions) and terminates the scanning of the source, if condition is false. (See also command @FUNCTION.)

5.6   Debugging functions

There are 2 debugging functions to examine the open file status:

6.   Macros and Functions

It is possible to define macros and functions on user level.

Syntax:

  MACRO_DEF    := '@MACRO' NAME ... '@ENDMACRO'
  FUNCTION_DEF := '@FUNCTION' NAME ... '@ENDFUNCTION'
  CALL         := CALL_LITERAL NAME [ PARAMETER ]
  CALL_LITERAL := '@CALL' | '@:'
  PARAMETER    := '(' [ expression [ ',' expression ]... ] ')'
  PARAM_CMD    := '@PARAM' VARNAME [ [','] VARNAME ]...

6.1   @MACRO name   ...   @ENDMACRO

The text between the command '@MACRO' and '@ENDMACRO' is stored in internal memory under 'name'. An already defined macro or function with the same same is deleted. All Macros are deleted before the second pass. The macro body is executed by using the command @CALL.

Example 1:

@macro item_point # (x,z)
  @assert $n >= 2
  0  $1  2000.0 $2  10.0   0 0
@endmacro

@call item_point(100,200)
@:item_point(300,400)

Example 2:

@macro sum
  @pdef sum = 0
  @for i=1;$n
    @pdef sum = sum + param(i)
  @endfor
  @return sum
@endmacro

@:sum(1,2,3,4)
@assert result() == 10

6.2   @FUNCTION name   ...   @ENDFUNCTION

A function is exactly like a macro with one extension: It can be called as function as part of an expression. The parameters are set in the same way as the command @CALL do it. The function result (defined by @RETURN) is used as value in the calling expression.

The new function takes precedence over already defined user and system functions with the same name.

Example:

@function sum
  @pdef sum = 0
  @for i=1;$n
    @pdef sum = sum + param(i)
  @endfor
  @return sum
@endfunction

@def sum2 = sum(1,2,3,4) * 2
@assert sum2 == 20

6.3   @CALL name ( parameters )

The call command starts the execution of a macro. Each line of the previous defined macro is executed like normal code. A macro is terminated, if the end of the source (@ENDMACRO or @ENDFUNCTION) is reached, or if the command @RETURN is executed.

It is possible to give parameters to the macro. Just enclose a comma separated list of expressions in parenthesis like func(a,b,c). The number of parameters is stored into the private variable $N and the parameters itself into the private variables $1, $2, ... By using the function param(index) it is possible to access a parameter by index. For usage examples see command @MACRO.

Instead of '@call name' the shorter '@:name' can be used. Here are some examples:

@call name          # $N == 0 : no parameters
@call name()        # $N == 0 : no parameters
@call name(a)       # $N == 1 : 1 parameter stored in $1
@call name(a,b,c)   # $N == 3 : 3 parameters stored in $1, $2 and $3

@:name              # $N == 0 : no parameters
@:name()            # $N == 0 : no parameters
@:name(a)           # $N == 1 : 1 parameter stored in $1
@:name(a,b,c)       # $N == 3 : 3 parameters stored in $1, $2 and $3

6.4   @PARAM name, name, ...

This command helps to give the parameters of macros and functions more intuitive names. The command expect a space or commas separated list of variables names. Each @CALL parameter is assigned to a variable name, step by step, in the private names space.

Example:

@macro test
    @param pos, width
    # line above is equivalent to: @pdef pos = $1, width = $2
    ...
@endmacro

6.5   Related functions

There are 2 functions to examine the existence of macros and functions and 2 other functions:

7.   IF .. ELIF .. ELSE .. ENDIF

The text parser supports nested if-then-else structures. Conditions are always expressions (see above).

Syntax:

 IF    := '@IF' EXRESSION
 ELIF  := '@ELIF' EXRESSION
 ELSE  := '@ELSE'
 ENDIF := '@ENDIF' | '@FI'

There is also an one line alternative: @DOIF.

7.1   @IF condition

If 'condition' is not null (=TRUE), then all lines until the next '@ELIF' or '@ELSE' of the same level are scanned and executed and all lines behind it until '@ENDIF' are skipped.

If 'condition' is null (=FALSE), the all lines until the next '@ELIF' or '@ELSE' of the same level are ignored.

The '@IF' command is the first command of a if-then-else structure.

7.2   @ELIF condition

This is an alternative condition for an already opened '@IF' structure. It works like the '@IF', but is only scanned if the '@IF' condition and all previous '@ELIF' conditions of the same if-then-else level are FALSE.

This command is optional and can be used multiple times.

7.3   @ELSE

The lines behind are scanned and executed if all '@IF' and '@ELIF' conditions of the same if-then-else level are FALSE.

This command is optional. If used it must be the last command before the '@ELIF' command of the same if-then-else level.

7.4   @ENDIF

A if-then-else structure is closed.

7.5   @DOIF ( condition ) anytext

'@DOIF' is an one line alterative for an IF..ENDIF structure.

Syntax:

 DO      := '@DOIF' '(' EXRESSION ')' ANYTEXT
 ANYTEXT := COMMAND_LINE | TEXT_TO_SCAN

The parentheses around the expression are mandatory to separate the ANYTEXT part. If the expression is true, the ANYTEXT part is read and executed like any text line. Otherwise the expression is false and ANYTEXT is ignored.

Examples:

@doif ( a < 4 ) @def b = 10           # conditional command
@doif(a<4)@def b=10                   # same command, but compact
@doif ( a < 4 ) 0 position scale 0 0  # conditional text (item route point)
@doif (a<4) @doif (b<5) @def c = 10   # two '@doif' in a row
@doif ( a<4 && b<5 ) @def c = 10      # ... same impact as line above
@doif ( isKCL() < 2 ) @return 0       # abort scanning, if not a course.* KCL

7.6   Debugging function

There is 1 debugging function to examine the if-then-else status:

8.   Loops

The text parser supports 5 kinds of nested loops.

Syntax:

  LOOP    := '@LOOP' -> '@ENDLOOP'
  REPEAT  := '@REPEAT' COUNT  -> '@ENDREPEAT'
  FOR     := '@FOR' VARNAME '=' START ';' END [ ';' STEP ] -> '@ENDREPEAT'
  FOREACH := '@FOR' VARNAME '=' EXPRESSION [ [';'] EXPRESSION ]... -> '@ENDEACH'
  WHILE   := '@WHILE' CONDITION -> '@ENDWHILE'

  BREAK   := '@BREAK' [ NUMBER ] [ '@IF' CONDITION ]
  CONT    := '@CONTINUE' [ NUMBER ] [ '@IF' CONDITION ]
COUNT, START, END, STEP, CONDITION and NUMBER are all expressions.

8.1   @ENDLOOP ... @ENDLOOP

  @LOOP
  @ENDLOOP
Execute an endless loop. Use '@BREAK' to exit the loop.

8.2   @REPEAT ... @ENDREPEAT

  @REPEAT count
  @ENDREPEAT
Execute the loop 'count' times. If 'count<1', the loop is skipped.

8.3   @FOR ... @ENDFOR

  @FOR varname = start_val ';' end_val [ ';' step ]
  @ENDFOR
Execute the loop multiple times. The variable 'varname' is set to 'start_val' in the very first loop. For each new loop, 'step' is added. If 'step' is not set, '1' is used instead.

The loop terminates

These entrance conditions are also tested before the first pass.

8.4   @FOREACH ... @ENDEACH

  @FOREACH varname = [EXPR [';' EXPR_LIST[... ]]
  @ENDEACH
The loop is executed N times, where N is the number of expressions in the list. The expressions may be separated by semicolons (';'). If the list is empty, the loop is not executed.

8.5   @WHILE ... @ENDWHILE

  @WHILE condition
  @ENDWHILE
The loop is executed until the condition becomes false (null). If the condition is initially false, the loop is not executed at all.

8.6   @BREAK

  @BREAK [ num ] [ '@IF' condition ]
The current loop is aborted. If 'num' is set and 'num>1', upto 'num' loops are aborted in a single step. If an '@IF'-condition is set, then the loop(s) are only aborted, if the condition is true (not null).

8.7   @CONTINUE

  @CONTINUE [ num ] [ '@IF' condition ]
The current loop is restarted with the next iteration value. If 'num' is set and 'num>1', upto 'num-1' loops are aborted and the loop 'num' is restarted. If a '@IF'-condition is set, then the command is only executed, if the condition is true (nut null).

8.8   Debugging functions

There are 2 debugging functions to examine the loop status:

9.   Miscellaneous

9.1   @ECHO and @WARN

The 2 commands '@ECHO' and '@WARN' expect of list of strings. The strings are concatenated to one message. '@ECHO' prints the message to standard output (stdout) and '@WARN' creates a warning printed to error output (stderr).

The strings of a message are:

Syntax:

  ECHO_CMD    := '@ECHO' STRING_LIST
  WARN_CMD    := '@WARN' STRING_LIST
  STRING_LIST := [STRING]...
  STRING      := QUOTED  | EXPRESSION
  QUOTED      = '"' any_printable_character_but_not_the_quote '"'
Examples:
  @ECHO "Test mode: " mode$test
  @WARN "Slot " mode$slot " defined, but not supported."

9.2   @DUMP-*

There are 6 commands to list variables to the standard output (stdout):
  @DUMP-PRIVATE
  @DUMP-LOCAL
  @DUMP-GLOBAL
  @DUMP-CONST
  @DUMP-PREDEF

  @DUMP-VAR
The first 5 commands (all except '@DUMP-VAR') list all variable of the corespondent name space. Command '@DUMP-VAR' list all variables of all names spaced with the exception of the predefined name space (this name space has many variables and is readonly by the user).

9.3   @SETUP-RANDOM ['='] expression

If starting the tools, the random number generator is initialized by a random number based on the current date and time. Pseudo random numbers can be generated with the random() function.

If using the command '@SETUP-RANDOM', the user can initialize the random number generator with a specific value. The random() function will deliver pseudo random numbers, but always the same sequence of numbers.