ESCR Program and Callable System

Last updated 27 September 2020


Commands

Commands are whole source lines that cause specific actions to be taken by the scripting system. Commands start with the command name, which is possibly followed by parameters. The command name and parameters are separated from each other by one or more spaces.

There are two types of commands, intrinsic and user-defined.

Intrinsic commands are built into the ESCR system. They are all available by default. Applications can remove specific intrinsic commands and add their own. The ESCR program leaves all the default intrinsic commands and defines none of its own.

User-defined commands are defined by script code using the COMMAND command. Once defined, these commands are indistiguishable from intrinsic commands to code that invokes them. See the COMMAND description for more information about user-defined commands.

Command names are case-sensitive. All intrinsic command names contain only lower case letters. User-defined command names can contain both upper and lower case letters. Parameters to the intrinsic commands are case-insensitive to the extent possible.

Depending on the application, a special sequence of characters may be required to identify commands. This is generally required in pre-processor mode to distinguish commands from data.

The ESCR program uses no special syntax to identify commands. The first non-blank character on a line is the start of a command name keyword.

The ESCR system intrinsic commands are:

APPEND name arg ... arg

Append the concatenation of all the arg arguments to the end of the string in the variable name. Name must be the name of a variable with string data type.

BLOCK

Starts a new execution block. The block is ended with the endblock command. This type of execution block can not take arguments. Inside the block, the arg inline function will resolve arguments for the next innermost block that can take arguments, such as a subroutine ... endsub block, for example.

CALL name [arg ... arg]

Executes the subroutine of name name. Execution returns to after the call command when the subroutine ends.

There may be zero or more arg parameters separated by spaces. These become the execution block arguments inside the subroutine. They are available to the subroutine via the arg inline function. Arguments are numbered sequentially starting at 1. The special argument 0 is always name.

The arguments are interpreted as raw collection of characters. One or more blanks separate arguments. Characters enclosed in quotes ("...") or apostrophies ('...') are treated as one entity and are not broken into individual arguments even if they contain blanks. However, the whole string, including the enclosing quote characters, becomes the argument value.

Note that, as with all commands, any inline functions are first evaluated before the command is interpreted.

Some examples of calls to subroutine XYZ and the resulting value of the arguments inside the subroutine are:

call xyz

Arg 0: xyz

call xyz a b "a b" "don't"

Arg 0: xyz
Arg 1: a
Arg 2: b
Arg 3: "a b"
Arg 4: "don't"

call xyz 1 2 [+ 3 4]

Arg 0: xyz
Arg 1: 1
Arg 2: 2
Arg 3: 7

COMMAND name

Create a user-defined command of name name.

Code following command is considered part of the command until an endcmd command is encountered. The code from command thru endcmd will not be executed when the command is being defined. User-defined commands are invoked just like intrinsic commands.

The code from command thru endcmd is an execution block. This type of execution block can take arguments, which are taken from the command parameters. Argument 0 is always the command name as it appeared on the command line. Any arguments supplied to the command will be available in the command routine as numbered arguments starting at 1. The argument passing mechanism is the same as implemented by the call command for subroutines. See the call command description for how arguments are parsed from the command line and passed to the command routine.

When a command is invoked, execution jumps to the first line after the defining command command. Execution continues until a return or endcmd command is encountered. Execution is then resumed on the line following the command invocation.

CONST name [dtype] = value

Create a new constant of name name.

The optional dtype parameter specifies the data type of the constant. The default data type is string.

DEL [objtype] name

Delete the object named name. Objtype specifies the type of object, and can be one of the following:

SYM

ESCR symbol of any type.

VAR

ESCR variable.

CONST

ESCR constant.

VCON

ESCR variable or constant.

SUBR

ESCR subroutine.

MACRO

ESCR macro.

FUNC

ESCR function.

CMD

ESCR command.

LABEL

ESCR label.

FILE

File system non-directory object. Symbolic links are followed. The script will abort on error, such as name not found.

TREE

File system object. Symbolic links are not followed. If the file system object is a directory, then the entire tree from that directory on down is deleted. On error, the ESCR integer variable EXITSTATUS is set to 3, otherwise to 0. EXITSTATUS is created if it does not already exist. The script exit status value is raised to what EXITSTATUS is set to, if previously lower.

In these cases, name is a string that is the name of the object to delete. In the case of a ESCR symbol, the symbol name may be qualified. In that case, the symbol type, if included in the qualifier, must match the symbol type(s) specified by objtype.

When objtype is omitted, name is the name of a ESCR symbol directly, not a string.

DIR [cmd] directory

Manipulates file system directories in the underlying operating system.

Directory is a string that is the name of a directory.

Cmd specifies the operation to perform. It can be one of the following:

GO

Set the current directory to directory. This is the default when cmd is not supplied.

MAKE

Creates the directory directory. It is an error if directory previously exists as any file system object.

EXIST

Creates the directory directory if it does not already exist. Nothing is done if directory previously exists as a directory. It is an error if directory previously exists, but is not a directory.

EXISTGO

Same as EXIST followed by GO with the same directory. This command ensures that the named directory exists, then sets it as the current working directory. It is an error if directory previously exists, but is not a directory.

ENDBLOCK

Ends the definition of the current execution block, which must have been started with a block command. This command functions like quit when executed.

ENDCMD

Ends a command definition started with the last command command. Code following this command is no longer considered part of the command definition, and will be executed if code execution was enabled when command was encountered.

If endcmd is encountered while executing a command, it functions just like return .

ENDFUNC

Ends a function definition started with the last function command. Code following this command is no longer considered part of the function definition, and will be executed if code execution was enabled when function was encountered.

If endfunc is encountered while executing a function, it acts like return .

ENDLOOP

Ends a loop execution block. If this command is encountered when the loop is being executed, then it functions like repeat .

ENDMAC

Ends a macro definition started with the last macro command. Code following this command is no longer part of the macro, and will be executed if code execution was enabled when the macro command was encountered. If endmac is encountered while executing a macro, then execution returns to immediately after the macro invocation (just like quitmac in this case).

ENDPICK

Ends the block started with the last pick command. It is an error if not currently in any pick block.

ENDSUB

Ends a subroutine definition started with the last subroutine command. Code following this command is no longer considered part of the subroutine, and will be executed if code execution was enabled when the subroutine command was encountered.

If endsub is encountered while executing a subroutine, it functions just like return.

FUNCSTR arg ... arg

Sets the concatenation of the string representation of all the arguments to the return value of the innermost function being executed. This command is only allowed inside a function routine.

The resulting characters are returned by the function as a string, not as a sequence of characters. To return raw characters, use the FUNCVAL command.

The return value of a function is initialized to nothing. A FUNCSTR command explicitly sets the return value, replacing any previously defined return value. Unlike FUNCVAL, multiple FUNCSTR commands are not cumulative.

FUNCTION name

Create a user-defined function of name name. Name will now refer to the new function regardless of its previous meaning, if any. Name will revert to its previous meaning when this symbol is deleted.

Following code is considered part of the function until a endfunc command is encountered. The code from function thru endfunc will not be executed when the function is being defined. User-defined functions are invoked just like intrinsic functions.

The code from function thru endfunc is an execution block. This type of execution block can take arguments, which are taken from the function parameters. Argument 0 is always the function name as it appeared in the function reference. Any arguments supplied to the function will be available in the function routine as numbered arguments starting at 1. The argument passing mechanism is the same as implemented by the call command for subroutines. See the call command description (above) for how arguments are parsed and passed to the function.

The current version of the function name symbol becomes the previous version inside the function. This means that the default is to call the previously-defined version of a function, not recursion, when using a function within itself. It is possible for a function to call itself recursively by referencing the +1 relative version of the function name.

Consider this example, using ESCR program syntax:

  function +
    funcval [+ [arg 1] [arg 2] 1]
    endfunc
  show [+ 3 4] " " [+:1 3 4]

This script produces the output:

  8 7

The first command in the script defines a new version for the function "+". Note that the function is not run at this time. It is essentially stored so that it can be recalled and run later as needed.

When the show command envokes the "+" function, the user-defined version is run instead of the intrinsic version of "+". This user defined version assumes there are two integer arguments. It returns their sum plus 1. This results in the "8" written to the output.

Note that a "+" function is used inside the function. The current version of a function is the one previous to the one that invoked the current code. Outside the function, such as in the show command, "+" refers to the user-defined function. Inside the user-defined function block, "+" refers to the previous version of that symbol, which is the intrinsic addition function. The "+" reference in the funcval command therefore causes normal addition. This is where the additional 1 is explicitly added.

The second invocation of the "+" function in the show command explicitly references the absolute version 1 of symbol "+", and therefore gets normal addtion with the result being 7 instead of 8.

FUNCVAL arg ... arg

Appends the concatenation of the string representation of all the arguments to the return value of the innermost function being executed. This command is only allowed inside a function routine.

The resulting characters are returned by the function as a sequence of characters, not as a string. Use the FUNCSTR command to return a string value.

The return value of a function is initialized to nothing. Each FUNCVAL command adds characters to the return value.

IF condition [then]
THEN
ELSE
ENDIF

These commands are used to conditionally execute sections of code.

Condition is an expression of data type bool. There are two forms of the if construct, depending on whether the optional then keyword is given on the if command line.

The general form without the then keyword on the if command line is:

if condition
    code that is always executed
  then
    code executed when condition is true
  else
    code executed when condition is false
  endif

At least one of the then and else commands are required.

The general form with the then keyword on the if command line is:

if condition then
    code executed when condition is true
  else
    code executed when condition is false
  endif

The else command is optional.

INCLUDE pathname

Switch the input file to the indicated file. When the end of that file is encountered, reading of the original file is resumed on the line following the include command.

Pathname is a string. It must therefore be enclosed in quotes or apostrophies if it is a constant. See the string data type description for details. The pathname is relative to the directory containing the current source file.

LOOP [opt [arg]] ... [opt [arg]]

Starts an execution block intended for looping. The command name can be followed by a sequence of options, each of which may take arguments. Each opt parameter is a keyword, and is therefore case-insensitive.

There are several distinct loop types that can be created with this command. The options used determine the loop type and its specific characteristics. The loop types are:

Unconditional

This type of loop has no special looping logic or terminating condition. Repeat and endloop will cause execution to jump to immediately after the loop command. Only Quit will terminate the loop.

This loop type is a result of not specifying any loop options.

Counted

The loop iterates over a sequence of integer values. There is a fixed non-zero increment of the loop value from one iteration to the next. This increment can be positive or negative (the loop can count either up or down).

During loop execution, repeat and endloop update the loop value to the next iteration. If the new value satisfies the terminating condition (if any), then the loop is terminated and execution proceeds after endloop. If the new value does not satisfy the terminating condition or there is no terminating condition, execution jumps back to immediately after the loop command with the new iteration value in effect.

The loop parameters are determined and saved when the loop command is executed before the first iteration. These parameters can not be changed by loop code.

The loop is not run at all if the initial loop value satisfies the terminating condition.

The loop command options for counted loops are:

with const

Const is the name of an integer constant that will be created before the loop is first run. This constant will be set to the loop value before each iteration. Const will be local to the loop block, so it will not exist after the loop terminates.

The default is that no constant is created. In that case the loop code can not access the loop value.

from n

N is the loop value for the first iteration. The default is 1.

The loop starting value is implied when both the to and n options are used. All three of the from, to, and n options can not be used together.

to n

Specifies the last valid loop value. The loop terminates when the loop value would be past this ending value. The meaning of "past" depends on the sign of the increment. When the increment is positive, the loop terminates when the loop value would be > n. When the increment is negative, the loop terminates when the loop value would be < n. Note that the loop increment can not be 0.

When no ending value is specified, then there is no terminating condition and the loop repeats indefinitely. In that case, the loop can only be ended with the quit command.

The loop ending value is implied when both the from and n options are used. All three of the from, to, and n options can not be used together.

n n

Specifies the number of loop iterations.

When no number of iterations is specified, there is no terminating condition and the loop repeats indefinitely. In that case, the loop can only be ended with the quit command.

The number of iterations is implied when both the from and to options are used. All three of the from, to, and n options can not be used together.

by n

Specifies the amount to add to the loop value each iteration. This value must be non-zero. The default is 1.

For example:

loop with ii from 3 to 7

Loop values: 3, 4, 5, 6, 7

loop with ii from 2 to -1

Loop values: None. The loop code is never executed.

loop with ii from 2 to -1 by -1

Loop values: 2, 1, 0, -1

loop with ii from 2 to 7 by 2

Loop values: 2, 4, 6

loop with ii n 4 from 2 by 3

Loop values: 2, 5, 8, 11

loop with ii n 5 by -5 to 100

Loop values: 120, 115, 110, 105, 100

loop n 5

Loop values: 1, 2, 3, 4, 5. The loop value is not accessible to the loop code.

Symbols

Loops once for each symbol that was defined when loop was first executed. If a symbol is deleted by loop code before its iteration, then that iteration is skipped.

The loop command options for symbol loops are:

symbols const [VAR CONST VCON SUBR MACRO FUNC CMD LABEL]

Const is the name of a constant of type string that will created. It will be local to the loop block, so will not exist after the loop is ended. This constant will contain the name of a different symbol each iteration. Const is the name of the constant to create directly. It is not a string.

The constant will be set to the fully qualified name of successive symbols in the list of symbols that was saved when the loop command was first executed. Symbols newly created inside the block are therefore not on the list.

The optional keywords following const limit the types of symbols the loop will iterate over. These keywords can appear multiple times and in any order. The default without any keywords is to loop over all symbols. When one or more keywords are listed, then only symbols of those types will be in the list.

The meanings of the keywords are:

VAR

Variables.

CONST

Contants.

VCON

Variables or constants. This is equivalent to specifying VAR and CONST.

SUBR

Subroutines.

MACRO

Macros.

FUNC

Functions.

CMD

Commands.

LABEL

Labels.

Directory

Loops over all the entries in a directory.

The loop command options for directory loops are:

dir dirname [FILE LINK DIR]

Dirname is the name of the directory to enumerate. Dirname is a string. It can therefore, for example, be a fixed name in quotes, or the name of a string variable.

The optional keywords file, link, and dir specify the type of file system objects to list. These keywords can appear in any order and may be repeated. When none of these keywords are supplied, then all directory entries are included. When one or more of these keywords is supplied, then only those objects matching at least one of the keywords are included.

The meaning of each keyword is:

FILE

Ordinary data file.

LINK

Symbolic link.

DIR

Nested directory (subdirectory).

The loop will iterate once for each matching directory entry. Use the dent function to access the information about the directory entry for the current iteration.

Execution will return to immediately after the loop command with the loop state set to the next iteration when repeat or endloop is executed, and the terminating condition is not met by the new iteration state.

The loop is ended when any of the following conditions are met:

Ending the loop means that execution continues after the endloop command, and that any resources allocated when loop was first executed are released. This includes deleting all local variables created inside the loop.

Loop and endloop form an execution block. This type of execution block does not take arguments. The arg inline function will resolve arguments of the next enclosing execution block that does take arguments.

MACRO name

Defines a macro. These are defined just like subroutines, except that the definition starts with macro and ends with endmac.

Macros differ from subroutines in how they are called. A macro is called just like a native assembler macro. If the macro name appears syntactically as an opcode, then the macro is run and its output replaces the macro invocation line.

Arguments can be passed to the macro by placing them following the macro name on the macro invocation line. Argument handling inside the macro is identical to that of subroutine. See the call command description for more details on arguments. Note that the call argument syntax in the macro invocation differs from the call command. Macro arguments are separated by commas with any number of spaces before and after each comma.

If a label preceeds the macro invocation on the same line, then the special argument -1 is created that will be the label name. The special argument 0 is the macro name as given by name.

The macro invocation syntax is deliberately compatible with the MPASM macro invocation and instruction syntax. This allows, for example, existing MPASM directives or instructions to be "hooked" to execute preprocessor code.

Following code is considered part of the macro until an endmac command is encountered. The code from macro thru endmac will not be executed when the macro is being defined.

A macro ... endmac is an execution block that can take arguments.

OPTION value ... value

Starts a section of conditionally executed code in a pick...endpick block. The code section ends at the next option, optionif, optionelse, or endpick command.

This option is valid when at least one value matches choice supplied to the pick command.

It is an error if no value was supplied to this option command, no choice was supplied to the pick command, or the data type of a value can not be converted to the data type of choice.

The quitopt command aborts execution of the option.

OPTIONELSE

Starts a section of conditionally executed code in a pick...endpick block. The code section ends at the next option, optionif, optionelse, or endpick command.

The option is code is executed if no previous option was executed.

The quitopt command aborts execution of the option.

OPTIONIF condition

Starts a section of conditionally executed code in a pick...endpick block. The code section ends at the next option, optionif, optionelse, or endpick command.

The option is valid when condition is true. Condition must resolve to a value of type bool.

Condition may depend on choice supplied to the pick command. Choice is accessed with the pick function. See the pick function description for details.

The quitopt command aborts execution of the option.

PICK opt [BY choice]

Starts a block of options that are conditionally executed. Commands that specify options are option, optionif, and optionelse. The block is ended with the endpick command.

A quitpick command exits the pick...endpick block by jumping to immediately after the endpick command.

The code following each OPTIONxxx command is conditionally executed. The condition may depend on the value of choice. Choice, if provided, is evaluated when the pick command is executed, then the result saved. This saved result is available inside the pick block via the pick function.

The pick function can also be used to determine whether choice was supplied or not, how many previous options were encountered, and how many were run. See the pick function description for details.

Opt is one of the following keywords:

ONE

At most one option is allowed to be valid. It is an error if more than one valid option is found. A valid option is not required, as this can be handled with the optionelse command.

An optionelse option is always allowed, even if another option was valid.

FIRST

The first valid option is executed, then the PICK command ended. This functions like the ONE keyword, except that it is not an error if further options are valid. The optionelse option is only executed if there were no previous valid options.

ALL

All valid options are executed. The optionelse option is only executed if there were no previous valid options.

The commands and functions related to pick blocks are:

QUIT

Exits the current execution block. Execution resumes with parameters in effect before the block was entered. Resources used internally in the script system to manage the block are deallocated and local variables defined in the block are deleted.

QUITMAC

Stops execution of a macro. Execution is returned to the line following the macro invocation.

QUITOPT

Aborts execution of the current option in a pick block. Execution skips to the next option, optionif, optionelse, or endpick command.

QUITPICK

Aborts the current pick...endpick block. Execution continues after the endpick command.

REPEAT

Go back to immediately after the command that started the current execution block.

If the execution block is a loop (started with loop), then the loop state is advanced to the next iteration and execution only returns to the start of the block if the new iteration state does not meet the terminating condition. If the new iteration state does meet the terminating condition, then the loop is ended and execution resumes immediately after the end of the block (functions like quit).

RETURN

Ends the execution of the current subroutine, user-defined command, or user-defined function. Execution resumes after where the routine was invoked.

RUN arg ... arg

Runs a external program. The concatenation of the string representation of all the arguments form the command line to execute. The first token of this resulting string must be the name of something the underlying operating system can execute. The remaining tokens are passed to that executable, and are generally interpreted as command line arguments by that executable.

The integer variable EXITSTATUS is set to the exit status code of the program that was executed. This variable is created if it does not already exist.

SET name value

Set the variable name to the value value. It is an error if value can not be converted to the data type of name, or if there is no such variable.

SHOW arg ... arg

Write the concatenation of the string representation of all arguments as one line to standard output. If no arguments are supplied, then a blank line is written.

STOP [exstat]

Completely ends this run of the script or preprocessor input file. No more input file is read, and no more output file written. Any open output files are closed, and the program exits.

The script exit status is set according to the following rules, in decending precedence:

  1. Exstat, if present.
  2. The value of the integer variable EXITSTATUS, if it exists. Note that this variable is automatically set (and created if needed) to the exit status returned by any external program run from the script.
  3. The exit status of the last nested script the application ran if the script state was not cleared afterwards.
  4. 0.

The script exit status is made available to the application program. It is up to each application program what, if anything, to do with it. The ESCR program returns the the script exit status code as its own program exit status code.

SUBROUTINE name

Define the entry point of a subroutine and define the symbol name to refer to that subroutine. The symbol name will now refer to the new subroutine regardless of its previous meaning, if any. Name will revert to its previous meaning when this symbol is deleted.

Following code is considered part of the subroutine until an endsub command is encountered. The code from subroutine thru endsub will not be executed when the subroutine is being defined. Subroutines are executed by using a call command, described below.

The code from subroutine thru endsub is an execution block. This type of execution block can take arguments, which can be set with the call command. Argument 0 is always the subroutine name as it appeared in the call command. The arguments passed from the call command are numbered sequentially starting at 1.

SYLIST

Write the list of all currently defined symbols and their values to the output file as data file comments. It is an error if there is no current output file.

VAR EXIST name [dtype] [= value]

Like var new, except that no new variable is created if name is already a variable or constant of the indicated type.

If a new variable is created, then it will be initialized to value, if supplied, else it will be initialized to the default for its data type. If the variable previously existed, then its existing value is preserved, whether value is supplied or not.

VAR LOCAL name [dtype] [= value]

Like var new except for the following:

VAR NEW name [dtype] [= value]

Create a new variable of name name. The symbol name will now refer to the new variable regardless of a previously existing variable or constant of the same name. Name will revert to its previous meaning when this symbol is deleted.

Dtype specifies the data type of the variable. The default data type is string.

The variable will be set to the value, if supplied. Otherwsie the variable's value will be the default for its data type.

WRITE arg ... arg

Write the concatenation of the string representation of all arguments as one line to the current output file. If no arguments are supplied, then a blank line is written.

It is an error if there is no current output file.

WRITEPOP

Ends writing to the file started with the most recently executed WRITEPUSH command. The output file is restored to what it was when WRITEPUSH was executed. In preprocessor mode, it is not possible to stop writing to the original output file.

WRITEPUSH name

Set the file that subsequent WRITE commands write to. The current output file can be restored with the WRITEPOP command. Name is a string, and indicates the name of the new output file. The file is created if it does not previously exist, and is overwritten if it does.

In preprocessor mode, there is always a output file. The top level output file is the file being pre-processed into.

In script mode, there is no output file until one is explicitly set up with the WRITEPUSH command. It is a error to attempt to write to the output file when there is no output file.