Introduction
This chapter introduces the structure of the STx programming and execution environment.
Contents
Shell
In STx, the term shell denotes the combination of a command interpreter and its execution environment, i.e. the environment executing the loaded code objects. A shell is created with the SHELL
command and ends when the last macro running in the shell is finished (command EXIT
). All shells are registered in the application environment. A shell can exchange messages with other shells.
Message Loop
A shell can receive and send messages. This mechanism is used to communicate with other shells, with the shell items owned by a shell, and with the main window of the application.
To access the message queue and process messages the, command MSG
or the library macros GETMESSAGE
, DISPATCHMSG
, MSGQUEUE
, POSTMESSAGE
and SETMSGHANDLER
can be used.
Shell Items
A shell maintains a list of shell items it owns. A shell owns an item if and only if the item was created in a macro or member function executed by the respective shell. Shell items are managed with the commands NEW
and DELETE
.
- Normally a shell item is visible only inside a shell, but it is possible to share items between shells by using ???. This technique is used for the workspace and the project.
- All shell items belonging to a certain shell must be deleted before the respective shell is terminated. If, using the BScript application, the shell executes a user script, an application cleanup function is used to delete leftover shell items. There is no such automatism for scripts not invoked using the BScript application.
There are shell items connecting STx with the operation system and its peripherals:
- The graphical user interface (GUI) is implemented by the display items, the graph items and the dialog items.
- The file item may be used to create and access files of several formats, but also to test the existence of a file and to scan directories.
- table items implement simple database features but can also be used as numerical objects in expressions.
- The wave item addresses signals stored in soundfiles and/or virtual sequences of synthetic signals. The wave items also interface to the physical sound devices of the computer, hereby enabling playback and recording.
- By means of the SPU items, programmable signal processing circuit subsystems may be implemented. Such SPUs can be connected to graph items, value items, and to other SPU items, thereby creating larger, more complex SPUs.
- An instance of the value item can be used as an input for SPU items, as a numerical object in numerical expressions, and as a timer.
- DCOM and DDECONV items implement interfaces to other applications.
Shell Variables
Each running shell has, as a part of its execution environment, a variable space of its own. This shell-wide variable space can be accessed from all macros and classes the respective shell is executing. STx uses a variant of "Hungarian notation" with a prefix for variable names indicating the scope of the respective variable. The shell-wide variable space containing the shell variables mentioned here is a special case insofar as it is indicated by the empty prefix. In layman's terms, every variable starting with a letter is stored in the shell variable space.
There are a number of predefined shell variables. Most important are the following ones:
name | description | see also |
---|---|---|
SHELL | The numerical id of the shell and of the parent shell, separated by a blank character (thisshell parentshell ). This variable is used by some library macros to communicate with other shells.
|
POSTMESSAGE
|
BDATASET | The name of the project instance. This variable must be used to access the content of the current project file. | BDATASET
|
BSTXINI | The name of the workspace instance. This variable must be used to access the content of the current workspace file. | BSTXINI
|
APPNAME | The name of the application. Only valid if the shell implements an STx application and was started via the application management system. | APPMAIN
|
APPTITLE | The title of the application. Only valid if the shell implements an STx application and was started via the application management system. | APPMAIN
|
APPMODE | This is the run mode of the application. It is available, and valid, only if the shell implements an STx application and was started via the application management system.
|
APPMAIN
|
PARENT | The name of the display used as parent window of the application. | CREATEMENU
|
RC | The completion code of the last shell command | |
EMSG | The text message corresponding to RC | |
CSF | The full path of the currently selected soundfile. If this variable is empty, no soundfile is selected. | LOAD SOUNDFILE
|
CSFH | The header parameters of the currently selected soundfile in the format samplingrate channels numberOfSamples samplingCode fileFormat accessMode
|
LOAD SOUNDFILE
|
Application Environment
The application environment contains all the data structures and functionalities which are available to the whole application.
Loaded Source Files
All scripts, macros, classes and SPUs (signal processing units) must be loaded from the respective source file before they can be executed or instantiated. All loaded sources are available to the whole application.
See also: shell commands LOAD
,
UNLOAD
and LIST
Open Soundfiles
All soundfiles which are being held open by STx are stored in a global list and may be accessed by all running shells. Before the content (signal or metadata) of a soundfile can be accessed, the file must be opened using the command LOAD SOUNDFILE
.
See also: shell commands LOAD
,
UNLOAD
and LIST
; wave items
Active Shells
All running shell are registered in the application environment.
See also: shell commands SHELL
, and LIST
Global Variables
The application environment contains a global variable space, which can be accessed from the whole application, i.e. from every running shell. The name prefix character @
is used to denote the global variable space. The global variables are used for configuration purposes and should not be changed. The following table shows some of the most important global variables.
name | description |
---|---|
@WORK | The full pathname of the working directory |
@ROOT | The full pathname of the STx installation directory |
@TEMPDIR | The full pathname of the directory for temporary files |
@DATASETFILE | The full pathname of the active project file |
@MASTER | The id of the master shell |
@OSVER | The operating system version |
@PROFILE | The full pathname of the workspace file |
See Global Variables for more details.
Macros
A macro is a collection of command lines. Macros are used to implement an application, a script or a library function. The macro source code is defined in a source file which must be loaded before the macro can be executed.
During its execution the macro can access:
- all loaded files (macros, classes, signal processing units (SPUs) and soundfiles)
- the global variables (whose names start with the
@
character) - all items of the shell executing the macro
- the shell variables
- the local variables of the macro (whose names start with the
#
character)
Macro Variables
The execution environment of a macro (basically, its local variable space) is created when the execution of the macro starts and deleted at the end of the macro execution. Besides user-defined local variables, there are a number of pre-defined local variables shown in the following table:
Variables assigned on macro call:
name | description |
---|---|
#ARGV, #ARGC | The macro argument string without parsing information and the number of arguments passed to the macro. These variables are used for "read:"-style argument passing. (see: macro header, READVAR )
|
#QARGV, #QARGC | The macro argument string with parsing information and the number of arguments passed to the macro. These variables are used for "arg:" and "argopt:"-style argument passing. (see: macro header, ARG , SHIFT )
|
#MAC | The name of the called macro. |
Additonal local variables assigned on member function call:
name | description |
---|---|
#THIS | The name of the instance item owning the member function. |
#THISMF | The name of the called member function. |
Local variables generated/used by commands:
name | description |
---|---|
#READ | The result returned by the last READ command. Normally this is the number of assigned variables
|
#MSG | The result string returned by the last MSG command.
|
#NEW | The result string returned by the last NEW command. Normally the ID of the shell item created.
|
Local Items
Normally the shell items created in a macro remain existing when the macro is finished. But in some cases temporary shell items are created, which are automatically deleted at the end of macro execution. Read the introduction to shell items for more information.
Classes, Instances
A class is a special type of macro which enables the programmer to use object-oriented programming techniques. There a two possibilities to "execute" classes:
- A class can be used like a macro if its name is used as command.
classname arguments
NEW INSTANCE classname
A member function of an instance can be called by using the following syntax:
instanceItemName memberFunctionName {memberFunctionArguments}
A member function is a part of a class source code starting at the member function label and ending with an EXIT
command.
During its execution the member function can access:
- all loaded files (macros, classes, SPUs and soundfiles)
- the global variables (whose names start with the
@
character) - all items of the shell executing the macro
- the shell variables (whose names are devoid of a prefix)
- the local variables of the member function (whose names start with the
#
character) - the member variables of the class instance (whose names start with the
&
character)
The local variable space of a member function exists only during the runtime of the function itself. In addition to the special local variables as described for macros, the following variables are stored in the local variable space whenever a member function is called:
name | description |
---|---|
#THIS | The name of the instance item. This variable is used by some library macros to communicate with other shells. |
#THISMF | The name of the member function. |
The member variable space of an instance has the same lifetime as the instance itself. This means it exists from the creation to the deletion of the instance item. No special member variables are defined.
The member variables can be accessed from outside the instance as follows:
- Assign a value to a member variable:
instance.variablename := value instance.&variablename := value
- Directly retrieve a value of a member variable:
target := instance[!VARIABLE,variablename] target := instance[!VARIABLE,&variablename]
- Parse the contents of a member variable:
READVAR instance.variablename targetvar1 … READVAR instance.&variablename targetvar1 …
Note: In the above scenarios, the member variable prefix character &
is optional and may be omitted. This is due to the fact that the context makes it absolutely clear that it is a member variable that is to be accessed: After all, the instance.variable
syntax would not make sense for other types of variables.
If a member variable of an instance is bound to a control of a dialog (e.g. EDIT or COMBOBOX) the full syntax instance.variablename
(with or without &
) must be used, not the simple &variablename
. This is absolutely vital so that the dialog item item is able always to access the variable.
Signal Processing Units (SPU)
An SPU is a circuit connecting one or more Signal Processing Atom together. The ciruit (its SP atoms, inputs, outputs, and internal connections) is defined in a SPU section of a source file. This SPU source file must be loaded before the SPU item (i.e. the runtime instance of the circuit) can be created.
Script Commands
The commands executed by a script are grouped into three different command types. The general command syntax:
commandid argstring
commandid
- denotes the command to be executed. It must be an unquoted string separated from
argstring
by one or more whitespace characters. Thecommanid
can not be abbreviated. argstring
- contains the arguments and options to be passed to the command
commandid
.
Built-In Commands
shellcommand argumentstring
shellcommand
- a build-in command of the shell command interpreter
argstring
- the arguments and options supplied to the command
The argstring
of a shell command consists of arguments and options. An argument is separated from each other by blanks or by quotes. If an argument contains whitespace characters (blank, tab, …), it must be enclosed in quotes.
Argument Examples
arg1 arg2'arg3' arg4 'arg 5'
The above argument string consists of five arguments with the values arg1
, arg2
, arg3
, arg4
and arg 5
.
'arg1 arg2 arg3'arg4'arg 5'
The above argument string consists of three arguments with the values arg1 arg2 arg3
, arg4
and and arg 5
.
Options
If a shell command supports options, they must be specified using the syntax /optionname
(for switches) or /optionname=optionvalue
. The option must start with the character /
(slash). It must not be inside a quoted part of argstring
. Only the first character of optionname
is significant. Normally the options are not case sensitive, but there are a few exceptions from this rule (e.g.: the options /U
and /u
of the NEW
command).
Option Example
arg1 /a/b '/c=arg3' /d='arg4' /e=evalue
The above argument string consists of the arguments arg1
, /c=arg3
, arg4
and the options a
, b
and e=evalue
.
Special characters inside an argument
If a parsing character (like /
or '
) or a special tag character (like $
or [
) should be part of an argument, it has to be escaped with the backquote ("`").
See the following example:
`/oname `$vname iname`[aname`]
This argument string consists of the arguments /oname
, $vname
and iname[aname]
. Without escaping, the arguments would be, in this order, the following:
- value of variable vname
- attribute aname of shell item iname
- Furthermore, the command would be supplied the option
o
.
Command results
A built-in command has two return values: The completion code and the command result:
- The completion code indicates if the command execution was successful or has failed. It consists of a numerical code, which is stored in the variable
RC
(0 indicating success), and the corresponing error description, stored in the variableEMSG
(empty ifRC
=0). - The command result is the value returned by the command. This value replaces the command statement and is used in (optional) assignments. For a lot of commands, the completion code is also used as the command result.
Note: Some arguments are keywords, selecting a specific subfunction or value (e.g. a color value). Such keywords are always case insensitive and can be abbreviated to the shortest unique form. A keyword can also be replaced by its index of the keyword-list (if this index value is known).
Call Commands
A call command is a statement which is used to call a source code object implemented in a script. There a several possible call commands:
macroname argstring
Calls the macro macroname with the arguments argstring.
classname argstring
Calls the class classname
, supplying it the arguments argstring
. If a class is called like this, it is executed like a macro. This statement type is used to implement static class functions.
GOSUB subrlabel argstring
Calls the local subroutine subrlabel
with the arguments argstring
. The label subrlabel
is the entry-point of the subroutine and must be a label of the macro containing the call statement.
institem memfun argstring
Calls the member function memfun
of the instance institem
, supplying it the arguments argstring
. memfun
must be a member function of the class of institem
and must be visible to the caller.
memfun argstring
This call statement can only be used in a member function. It calls the member function memfun of the same instance.
The argument parsing rules are depending on the parsing-style used in the source code of the function.
- ARG- or ARGS-style
- Same rules as for build-in commands without options.
- ARGOPT-style
- Same rules as for build-in commands with options. For details read the chapter definition of macros and the description of the build-in command ARG.
- READ-style
- This is the older parsing method, but it is used by the most standard macros and classes. The argument string is passed to the function after command-line processing (parsing information is removed!) and the READVAR command is used to parse the arguments which are stored in the variable
#ARGV
. Macros using this method do often use the semi-colon (;) to seperate arguments.
- Examples:
testmacro this is a 'test message'
- The argument string stored in
#ARGV
isthis is atest message
butil msgbox 'msg ; hallo'
- This statement is a call to the standard library macro BUTIL and should display a message box with the text hallo. The call will not work, because the argument string
msgboxmsg ; hallo
is passed and the function msgboxmsg is not implemented. A valid statement format is:butil 'msgbox msg; hallo'
.
A call command has only one return value: the function result. The value is generated by the EXIT command, which ends the execution of the called function. This value is stored in the variable RESULT
and also used in (optional) assignments.
Control Commands
Normally the commands are executed in the order as they appear in the source file. The control commands, can be used to change this natural order of execution.
Miscellaneous
GOTO labname
- Unconditional jump. Continue execution at the label labname.
IF condexpr condcmd
- Conditional command execution. The command condcmd is executed if the condition condexpr is true. condcmd must not be a control command!
IF-THEN-ELSE-END
- Block IF. A block IF may consist of one or more THEN-clauses (one is required) and an ELSE-clause. The commands of the first THEN-clause where condexpr is true are executed. If no condition is true, the commands of the ELSE-clause (if any) are executed.
IF condexpr THEN ... {ELSE IF condexpr THEN ... } {ELSE ... } END
COND condexpr ? truecmd : falsecmd
target := COND condexpr ? truecmd : falsecmd
- Conditional execution and conditional assignment. If the condition condexpr is true, the command truecmd is executed, otherwise falsecmd is executed. If a target is specified, the result of the executed command is assigned. Both commands must not be a control command!
DISPATCH function arglist ...
- Dispatch a call to a multi-function macro.
Examples:
// type depending item processing if $#item[?] == table then // process table item else if $#item[?] == wave then // process value item else butil msgbox msg ; no processing for items of type "$#item[?]" implemented end // display a table cond '$#item[?]' == table ? showitem $#item : butil msgbox msg ; $#item is not a table
Loops
WHILE condexpr
- While loop. The commands in the loop are executed while the condition condexpr is true.
WHILE condexpr ... END
FOR initcmd TO condexpr STEP stepcmd
- For loop. The commands in the loop are executed while the condition condexpr is true. Before the loop is entered, the initcmd is executed. After each execution of the command block the stepcmd is executed. All parts of the command are optional.
FOR {initcmd} TO {condexpr} STEP {stepcmd} ... END
FOREVER
- Run forever. The execution of the commands block will never end. Only the EXIT and BREAK command can be used to leave the loop.
Inside a loop the commands CONTINUE and BREAK can be used to start the next iteration or to leave the loop.
Examples:
// use a for-loop to sum the integers from 1 to #n #nsum := 0 for #i := 0 to $#i < $#n step #i := int $#i+1 #nsum := int #nsum + $#i end // find all occurrences of a value in an extended table (version 1) #pos := set '*' while '$(#pos := find $#table $#pos keyfield'$#keyvalue')' // process table entry $#pos end // find all occurrences of a value in an extended table (version 2) for #pos := set '*' to '$(#pos := find $#table $#pos keyfield'$#keyvalue')' step // process table entry $#pos end
Alphabetical list of control commands
BREAK | break loop execution (only allowed in loops) |
COND | conditional assignment |
CONTINUE | continue with next loop iteration (only allowed in loops) |
DISPATCH | dispatch functions, for use in multi-function macros |
DO | old loop command (DO WHILE, DO FOR, DO FOREVER) Note: The DO command should not be used in new scripts! |
ELSE, ELSE IF or ELSE IFNOT | opens the else- or a else-if-clause in a block-if |
END | end tag for block-ifs and loops |
EXIT | exit from one/more function levels and return result |
FOR .. TO .. STEP | begin of a for-loop |
FOREVER | begin of an infinite loop |
GOTO | unconditional jump |
IF or IFNOT (.. THAN) | conditional command execution or first clause of a block-if |
WHILE | begin of a while-loop |
Note: Control commands can not be used as inline functions!
Conditional Expressions
All commands using conditions use the same syntax and evaluation rules. A condition consists of one or more comparisons which are joined with logical (binary) operators. Each comparison compares two values and can evaluate to true or false.
General syntax for a condition:
comparison {loperator comparison {loperator ..}}
- comparison
- A comparison comprising two expressions separated by a comparison operator.
- loperator
- A logical operator, which combines the results of two comparisons. Logical operators are evaluated strictly from left to right; bracketing is not possible; it is explicitly undefined if a part of an expression that is strictly not required for judging on the truth, or falshood, of the whole expression, gets evaluated, or not. So you should not use expressions with side-effects.
General syntax for a comparison:
expression coperator expression
- expression
- A numerical expression or a string.
- coperator
- A comparison operator.
- Logical operators
- The logical operators supported by STx conditional commands are the following:
AND
returns true if both comparison results are true &&
the same as AND
OR
returns true if either of the comparison results are true ||
the same as OR
- Simple comparison
- A simple comparison will be numerical if both arguments are numerical. Otherwise, a case-insensitive string comparison will be performed.
==
evaluates to true if both sides are equal. !=
evaluates to true if sides are not equal <
evaluates to true if the left hand side is less than the right hand side >
evaluates to true if the left hand side is greater than the right hand side <=
evaluates to true if the left hand side is less than or equal to the right hand side >=
evaluates to true if the left hand side is greater than or equal to the right hand side
- Wildcard Pattern Matching
- The left side expression is called string and the right side expression is called mask. The mask can contain wildcard characters
*
(one or more characters) and?
(one character). - Note that, instead of a string, the argument to a pattern matching comparison may also be an STx name, i.e. a string subject to the syntax restrictions for STx names. You can discern the full string comparison operators from the name comparison operators by there second character which is S for string comparison (e.g.
!SI
), and N for name comparison (e.g.!NI
).
string operator name operator description =SI
=NI
returning true if string matches mask, ignoring the case !SI
!NI
returning true if string does not match mask, ignoring the case =SR
=SR
returning true if string matches mask, respecting the case !SR
!NR
returning true if string does not match mask, respecting the case
- POSIX regular expression pattern matching
- The left side expression is called string and the right side expression is called mask. The mask is a POSIX regual expression. Regular expressions make heavy use of characters that have a special meaning for STx. In order to use such characters, you need to escape them with the STx escape character, "
`
" (back-tick). The STx regular expressions are implemented using the TRE library.
string operator name operator description =RSI
=RNI
returns true if the string matches the regular expression, ignoring case !RSI
!RNI
returns true if string does not match the regular expression, ignoring the case =RSR
=RNR
returns true if the string matches the regular expression, respecting case !RSR
!RNR
returns true if the string does not match the regular expression, respecting the case
Note: Each part of a conditional expression (expression, loperator, coperator) must be a seperated argument!
Variables, Item Attributes, Inline Functions
The STx script language uses a simple string replacement technique to implement the access to variable values.
Variables
Each occurrence of $varname
in a command line is replaced by the value of the variable varname. If varname is not defined, its value is the empty string.
Examples:
#y := int $#x^2
#fileitem := new file * '$@work\$#filename.txt' /read /text
The existence of a variable depends on the context or the visible variable environments. The variable environments are addressed by a tag-character, preceding the varible name.
- Global variables (@)
- Global variables are preceded by the character @ and are accessible from all classes and macros. The global variables are used for the program configuration and to hold important runtime information.
- Local variables (#)
- Local (or Macro) variables are preceded by the character # and are only accessible by the owner of the local variable environment. A local variable environment is created when a macro, a local subroutine of a macro or a member function of an instance is called. The local variable environment exists while the called code is running and is destroyed when the return statement is excuted.
- Member variables (&)
- Member variables are preceded by the character & and are only accessible by the member functions of the instance owning the member variable environment. The member variable environment of an instance has the same lifetime as the instance itself.
- Shell variables
- All variables not preceded by one of the tag characters, @, # and & are stored in the shell variable environment and are visible for all macros and classes executed in this shell.
Item Attributes
Each occurrence of itemname[attrid]
in a command line is replaced by the value of the attribute attrid of the shell item itemname. If the attribute is not defined, its value is the empty string. The attrid can be a single word or a list of comma seperated sub id's.
Examples:
writelog 'Fileitem $#fileitem is connected to the textfile $#fileitem[!path].'
for #row = 0 to $#row < $#tableitem[!nrow] step #row := int $#row+1 for #col = 0 to $#col < $#tableitem[!ncol] step #col := int $#col+1 writelog '$#tableitem`[$#row,$#col`] = $#tableitem[$#row,$#col]'
Note: The shell item attribute names are always case insensitive and can be abbreviated to the shortest unique form. To distinct between internal (pre-defined) shell item attributes and user defined shell item attributes (e.g. table fields), the internal attributes start always with an exclamation mark (!).
Inline Functions
Each occurence of $(ifuncall)
in a command line is replaced by the return value of the inline function call ifuncall. The string ifuncall can be any valid build in command or function call, but not a control command. It can also include an assignment.
Examples:
#list := set 'first second third' writelog 'This is the $(word 2 $#list) word of variable #list.' writelog '"third" is has the index $(#index := keyword 'third' $#list).' writelog 'The word following "second" is "$(#nextword := word $(keyword 'second' $#list)+1 $#list)"'.