CMD Macros
CMD macros were used in Surpac2, v3.0, v3.1, and v3.2. In Surpac v4.0, a more complete scripting language known as SCL (Surpac Command Language) was implemented. SCL is based on the widely available TCL (Tool Command Language).
Most, but not all CMD macros can still be played back. Compiled macros (.cmz files) can also still be executed using the MACRO PLAYBACK function.
Function and or control keys may be used to initiate the recording and end the recording of the macro.
MACRO RECORD START
| F4 | Start recording a macro. A form is displayed to name the macro. |
MACRO RECORD END
| F5 | End recording the macro. Exiting while recording the macro also ends recording of the macro. |
MACRO PLAYBACK
| F6 | macro playback - a form will be displayed to enter the name of the macro to be invoked, the macro playback options and up to 10 of the positional arguments which will be passed to the macro. |
Invoking Macros From the Command Line
Macros may also be invoked from the operating system command line by issuing the following command:
surpac2 macroname
Types of Macros
Three types of macros may be executed by the MACRO PLAYBACK function. These are:
- Uncompiled macros (.cmd files)
- Compiled macros (.cmz files)
Uncompiled macros are created by the MACRO START/END RECORD functions. The macro may be played back immediately and the macro may be modified by using a text editor to customise it to your needs. Almost all macros that exist are uncompiled macros.
These macros can only be recorded in versions of Surpac prior the V4.0 release. These macros can still be played back in the V4.0 and later releases as the macro interpreter system has been retained for just this purpose.
Compiled macros have been created by the MACRO START/END RECORD functions and then compiled into a binary format with the MACRO COMPILE function.
These macros can only be recorded in versions of Surpac prior to the V4.0 release. These macros can still be played back in the V4.0 and later releases as the macro interpreter system has been retained for just this purpose.
Note: The MACRO COMPILE function is no longer supported.
The MACRO PLAYBACK function recognises the type of macro being executed by its file extension. If no file extension is supplied the software assumes that a .cmd file was intended and it then attempts to execute an uncompiled macro. If a .cmd file of that name does not exist that an attempt to execute an SCL script is made by searching for a file with a .tcl extension. An explicit file extension, i.e. .cmd, .cmz or .tcl will cause the appropriate type of macro/script, uncompiled, compiled or SCL script respectively to be executed.
In each case the macro command file contains information that may execute any of the functions in the software. The following is an example of an uncompiled macro file which creates a Digital Terrain Model from a string file called drawdown1012.str.
@MENU
dtm_tools
|
This file may be edited by the user to include a number of powerful user defined functions which are described later in this section.
The following shows the macro file listed above to create a DTM, modified by the user so that different string files may be used with different spot height ranges each time the macro is run:
#
|
Invoking Macros with Arguments
All variables which must be assigned values during the macro execution may be assigned values at the start by using the @SET keyword. This makes it possible to get all inputs for a macro before processing commences. It is permissible to make use of the @SET keyword at any place within the macro to assign values to macro variables.
If a macro containing variables is invoked from within the program, a form will be displayed and the arguments may be passed to the macro here. If no arguments are passed via this form, the macro will commence execution and prompt for each argument at each @SET keyword.
As outlined earlier, macros may also be invoked from the operating system command line. To invoke Surpac with macro arguments from the command line, issue the following command:
surpac2 macroname arg1 arg2 arg3 arg4 ...
Command Line Switches for Macros
When running macros from the operating system command line it is possible to modify the behaviour of the macro playback by using an optional command line macro switch.
The default behaviour for macro playback from the command line is for the macros to use `fast motion' playback. In this mode the forms are only displayed if user input is required.
To use `slow motion' playback when invoking macros from the operating system command line you can use the `-s' or `/s' switch. For example,
surpac2 macroname -s arg1 arg2 arg3 arg4
...
This will cause all forms to be displayed for the required pause period regardless of data entry requirements.
Note: The switch must come after the macroname
but not necessarily before the macro arguments.
Playing back your macro from a menu always defaults to slow play back mode. You may force a macro to run in fast or slow playback mode by using:
- |-f (Fast Playback)
- |-s (Slow Playback)
Macro File Syntax Rules
Macro files consist of various keywords and phrases and uses a strict syntax to dictate the manner in which they are interpreted at run time. The table below describes the macro special characters and associated syntax rules:
| Special Character | Meaning |
|---|---|
| # | Comment character. If the first non-blank character in a line is "#" then the entire line is treated as a comment line and ignored completely. |
| \ | Line continuation character. If the last character on a non-comment line is "\" then the following line is appended to the current line as if they were all part of the one line. |
| @ | Keyword/Phrase prefix character. All lines which are not comments or continuation lines must have a "@" as the first non-blank character. This introduces the keyword which defines the type of macro directive represented by the line. @MACRO, @FUNCTION and @FORM directives also allow the use of the "@" character to indicate a textual replacement operator. |
White space characters in the context of macro directives are space and tab characters.
Textual Replacement Operators
The @MACRO, @FORM, and @FUNCTION macro directives are processed differently to all other macro directives in that they allow the use of two forms of textual replacement operators. The supported operators are:
- @(var) - where var is a variable name or a macro argument number. The value of the variable or argument is inserted in the directive to replace the @() operator.
- @expr(expr) - where expr is a general expression as described in the EXPRESSIONS section above. Expr is evaluated as a string and inserted in the directive to replace the @expr() operator.
It is preferable to use the @expr() operator in preference to the @() operator since it is more powerful and has a better defined syntax. The four forms of the @() directive are equivalent to the following @expr() directives:
| @() form | Equivalent @expr() form | Description |
|---|---|---|
| @(arg_no) | @expr(ARG(arg_no)) | Insert the textual value of the appropriate argument |
| @(var) | @expr(var) | Insert the textual value of variable var |
| @(var=default) | @expr(VAR_DEFAULT(var, "default")) | If var is set then insert the textual value of variable var otherwise insert the default text |
| @(var:prompt) | @expr(VAR_PROMPT(var, "prompt")) | If var is set then insert the textual value of variable var otherwise prompt for the value to insert using the prompt specifier. This format is only provided for backwards compatibility and you should use the GUI_STR function in an @ASSIGN directive instead. |
The fourth form above is not recommended and instead you should prompt for values using the GUI_STR function in an @ASSIGN directive.
If you wish to have an ``@'' character in a line not as a textual replacement operator then escape it as two ``@@'' characters.
Example Macro to Produce Plot Files
The example below shows a small part of a macro that produces plot files.
@FORM frm00224,action=apply,pause=2.000000,error=abort,
|mismatch=display\ |
To enable the macro to read in the most recent `.pf' file you will need to make some changes to your macro.
- Delete the line showing the input for the form. e.g. |name=aa.pf
-
Delete the line continuation character from the previous line.
ASSIGN
@ASSIGN varname=expr
The macro keyword assigns a named variable to be equal to the result of a calculated expression, for example @ASSIGN var1=''hello'', or @ASSIGN counter = counter + 1.
The named variable ``varnam'' may consist of any alphanumeric and underscore characters provided it does not start with a digit.
Expr can be any general expression described in the EXPRESSIONS section above including the macro specific functions described later.
UNASSIGN
@UNASSIGN varname
This macro keyword unsets a named variable. The named variable becomes non-existent.
FUNCTION
This key word indicates a function and must be preceded by an ``@''. The action which the macro must take when the function fails to complete successfully may be specified in the form:
@FUNCTION CREATE DTM,error=[continue|abort],mismatch=[display|ignore]
| error = tells the system how to react if errors are encountered during processing of the function. Two values are allowed for the error specifier and these are: | |
| continue | Continue processing the macro regardless of any errors which may have been encountered. |
| abort | Abort the current function or macro.
Macro interrupts will occur at the time when the next form is displayed.
An Abort will cause the currently executing macro and all other calling
macros to fail until the Function prompt is displayed and the system becomes
passive and is waiting for input.
Functions can be interrupted with the Abort key. If the abort key is pressed, a form is displayed requiring the Abort event to be either confirmed or cancelled. If the Abort event is confirmed then the currently executing function will terminate. If the Abort event is cancelled, the currently executing function will terminate. If the Abort event is cancelled, the currently executing function will continue. Not all functions will respond to the Abort event. Only those functions which have some form of processing feedback implemented, either hidden or visible, will respond to Abort events. |
The default value is abort.
The error action tells Surpac how to react if errors are encountered during processing of the function.
There are two examples:
@FUNCTION RECALL FILE,error=abort
(Stop processing of the macro if an error is encountered)
@FUNCTION RECALL FILE,error=continue
(Continue processing of the function)
Errors are generally introduced during editing of a macro due to incorrect syntax, and consequently you are most often going to want the macro to stop processing. (error=abort) However, there may be times when you do wish to continue, even though an error has occurred. An error may be reported for some functions when a form is cancelled within a macro.
| mismatch= tells the system how to react if forms are displayed that are not dealt with by the macro. For example, to prevent accidental overwrite of files, a form is displayed that requires confirmation prior to overwrite of an existing file. It is possible due to various circumstances that a mismatch between forms and macros can occur. If so the mismatch= specifier is applied. | |
| display | Display the form and wait for user input. |
| ignore | Ignore the form and continue processing. |
The default value is display.
These are two examples:
@FUNCTION RECALL FILE,error=abort,mismatch=display
(Display the form for user input)
@FUNCTION RECALL FILE,error=abort,mismatch=ignore
( Ignore the form and keep processing)
FORM
This key word indicates a data entry form. The action which is to be taken after a form is displayed and if errors are encountered in validating the input values on the form may be specified. Parameters to the form, i.e. the values which are to be assigned to each of the input fields, are specified using the following method.
@FORM
form_form_dtm,action=[apply|display|cancel],
error=[cancel|display|abort], \
mismatch=
[display|ignore],pause=time|par1=val1|par2=val2|par3=val3|...
| The action keyword defines the action to be taken after values have been entered into the form. | |
| apply | Apply the form and return all values to the function; in the same way as if the Apply button was pressed interactively. |
| display | Display the form and wait for user input or until Apply or Cancel buttons are pressed. |
| cancel | Cancel the form; in the same way as if the Cancel button where pressed interactively. |
The default value is apply.
Example: This can also be a very simple way to halt the macro to allow user input, simply record a macro and place the action=display against the appropriate form as shown below. The macro will halt allowing the form field values to be altered before pressing apply to continue.
@FORM form_form_dtm,action=display,pause=2.000000,error=abort, mismatch=display\
|anyspots=Y\
|id=1012\
|location=drawdown\
|spotrng=90,98
The pause keyword defines the time that the form will remain on the screen. The default is 2 seconds.
The error keyword defines the
action to be taken when an error is encountered in the processing of data
on a form. Form errors can be one of:
|
|
| display | If an error exists in the form then display the form for interactive data correction. After the Apply button has been pressed the macro will continue processing. |
| cancel | If an error exists on the form then act as if the Cancel button has been pressed, thus providing an exit path from the form. |
| abort | If an error exists on the form then exit from the macro immediately. |
The default value is display.
| mismatch=works in the same manner as the mismatch specifier for the function keyword |
| pause=A time period which will cause the form to be displayed when playing the macro back in slow motion |
MACRO
Invoke a macro from this macro. Arguments may be passed on the @MACRO command line using variables with pipe delimeters, e.g.:
@MACRO macroname,error=[continue|abort]|@(1)|@(varname)|text passed like this|@(3)|...
The error keyword works in an identical fashion to the error keyword specified for @FUNCTION.
| continue | Continue processing the macro regardless of any errors which may have been encountered. |
| abort | Abort from the macro if any error is encountered during the processing of a function. |
The default value is abort.
Scoping rules will apply when a macro invokes another macro. All variables, with the exception of positional variables
@(0),@(1),@(2) etc. will be inherited from the parent or calling macro. If a variable ``varname'' exists in the parent macro and a variable of the same name is created (by using @ASSIGN) in the child macro then the variable ``varname'' in the child macro will be a unique variable to the child macro and the value will not be exported to the parent macro.
To ensure that a variable ``varname'' does not inherit a value from a parent macro, an explicit ``@UNASSIGN varname'' must be used to destroy the inheritance characteristic from the parent macro.
Note the syntax in the following example:
@MACRO intersect,error=abort|12030|pit|200
In the macro intersect.cmd, the first 3 positional variables will inherit the values, @(1)=12030, @(2)=pit, @(3)=200
PAUSE
@PAUSE
@PAUSE(expr)
Note: There is no whitespace between @PAUSE and the ``(`` character.
To have an explicit pause in the playback of the macro file. PAUSE has an optional numeric argument which is the duration of the pause in seconds. If no argument is given to PAUSE then the macro will pause until a key is pressed on keyboard.
For example,
#
# Pause for 10 seconds
@PAUSE(10)
#
# Pause until user presses a key
@PAUSE
#
# Pause with a more complicated expression
# Pause for 2 seconds if the variable fast
#is "true" otherwise pause for 10 seconds
# (See the description of the conditional
#operator in the Expressions section for
#an explanation
# of the ?: operator)
@PAUSE(fast ? 2 : 10)
MESSAGE
@MESSAGE(expr)
Note: There is no white space between @MESSAGE and the ``(`` character.
Display a user specified text string in the message window.
For example,
#
# Display a simple message
@MESSAGE("Display this text")
#
# Display the result of an calculated expression
@MESSAGE("CPUTIME used so far is " . cputime())
ALERT
@ALERT
@ALERT(expr)
Note: There is no whitespace between @ALERT and the ``(`` character.
Will cause the macro to sound the terminal bell. If the optional expression is present then it will be displayed in the same manner as the MESSAGE directive.
RETURN
@RETURN
Causes an immediate return from the current macro.
MENU
@MENU(expr)
Note: There is no whitespace between @MENU and the ``(`` character.
Evaluate the expression and use it as the name of an menu to display. The @MENU directive is primarily available so that recorded macros display the correct sequence of menus. It is not intended for general use.
WHILE
@WHILE(expr)
body
@ENDWHILE
This keyword allows a group of macro directives to be repeatedly executed while the expr evaluates as ``true''. The body can be any macro directives. For example,
#
# Loop while we have data to process
@assign num_processed = 0
@while (num_processed < num_to_process)
#
# process the data
@assign num_processed = num_processed + 1
@endwhile
RANGE
@RANGE(var=expr)
body
@ENDRANGE
This keyword allows a body to be executed for each member of a given range. The expression is evaluated as a range specification (see the section on Range Specifications) and then var is assigned to each member of the range in turn and the body executed. The value of var after the last execution of the body is undefined. For example,
#
# Loop from 1 to 10
@RANGE(I=''1,10,1'')
@message(``In iteration ``. I)
@ENDRANGE
GOTO
@GOTO label
@LABEL label
The GOTO directive allows you to transfer execution to another part of a macro in an unstructured manner. When a GOTO directive in encountered control is transferred to the LABEL directive with the same label. LABEL directives are otherwise ignored. It is not possible to jump into the body of a RANGE, WHILE or IF directive from outside that body. It is possible, however, to exit the body of one of these directives using the GOTO directive. Labels are alphanumeric strings where the first character is not a digit. For example,
#
# Use of a GOTO to exit an endless loop
@WHILE (``true'')
...
@IF (need_to_quit)
@GOTO quit_while_label
@ENDIF
...
@ENDWHILE
@LABEL quit_while_label
IF
@IF(expr)
body
@ELSEIF(expr)
body
@ELSE
body
@ENDIF
The IF directive allows you to execute one or none of a number of separate blocks of code depending on some calculated expressions. There may be any number of ELSEIF parts and/or an ENDIF part. The body associated with the first expr which evaluates as ``true'' is executed or if no expression evaluates as ``true'' and an ELSE part is present, the body associated with the ELSE part is executed. For example,
#
# Print a message indicating the value range
@IF (I >= 0 && I < 10)
@MESSAGE("I has one digit")
@ELSEIF (I >= 10 && I < 100)
@MESSAGE("I has two digits")
@ELSEIF (I >= 100 && I < 1000)
@MESSAGE("I has three digits")
@ELSE
@MESSAGE("I has more than three digits")
@ENDIF
Obsolete Features
Some of the older macro directives are still supported (eg. @SET and @UNSET) although their use is not recommended; @ASSIGN and @UNASSIGN should be used instead of @SET and @UNSET.
The old forms of @MENU, @PAUSE, and @MESSAGE are still recognised and are distinguished from the new forms by the following ``(`` character in the new forms. The new forms should be used in preference to the old forms.
The use of the textual replacement operators in some old form directives other than @MACRO, @FUNCTION and @FORM directives is still supported but also not recommended. Use the new GUI_FILE and GUI_STR functions with the @ASSIGN directive to obtain the behaviour of the @(var:prompt) operator.
The reason for restricting the use of the textual substitution operators is that they make it very difficult to provide extensions to the macro language while still allowing upwards compatibility of existing macros.
Macro Expressions
The expression syntax used in macro directives is the general expression syntax described in the Expressions section. As well as the normal functions there are also some macro specific functions available for use with macros. These are:
| Function | Description |
|---|---|
| ISSET(var) | var must be a variable name and returns true if var is set to a value |
| ARG(n) | evaluate n as an integer and return the value of the corresponding argument to the macro. If n is 0 then return the macro name. |
| VAR_DEFAULT(var, b) | if var is set return the value of var otherwise return the value of b. Same as the old @(var=b). If var is an integer then it is taken as an argument number. |
| VAR_PROMPT(var, b) | if var is set return the value of var otherwise prompt for a value using the old style prompt specifier b. Same as the old @(var:b). If var is an integer then it is taken as an argument number. |
| GUI_STR(a) | evaluate a as a string and parse it as a Graphical User Interface (GUI) definition. Then invoke the form or menu so defined and return the name of the button pressed to dismiss the form or menu. Form fields are initialised from variables of the same name and if a form is applied then variables of the same name as the fields are set to the field values. See below for a detailed description of the GUI definition syntax. |
| GUI_FILE(a) | as for GUI_STR except a is interpreted as a filename from which to load the GUI definition. |
| GUI_DIGITISE(prompt) | Prompt the user to digitise a point on the screen. prompt is the prompt to display to the user before the operation proceeds. The macro variables (gui_objectx, gui_objecty, gui_objectz) are set to the coordinates of the digitised point. The function returns "apply" if the user completes the operation and "cancel" if the user cancels the operation. |
| GUI_SELECT_POINT(prompt) | Prompt the user to select a point on
the screen.
prompt is the prompt to display to the user before the operation proceeds. The macro variables gui_layer, gui_string_id, gui_segment_no, and gui_point_no are set to the layer name, string id, segment number (starting at 0 for the first segment in the string), and point number within the selected segment (starting at 0 for the first point in the segment) of the selected point respectively. The macro variables (gui_objectx, gui_objecty, gui_objectz) are set to the coordinates of the selected point. The macro variable gui_description is set to the description fields of the point separated by commas in the same format as it appears in the string file. The function returns "apply" if the user completes the operation and "cancel" if the user cancels the operation. |
| GUI_SELECT_TRIANGLE(prompt) | Prompt the user to select a triangle on the screen. prompt is the prompt to display to the user before the operation proceeds. The macro variables gui_layer, gui_triobject_id, gui_trisol_id, and gui_triangle_no are set to the layer name, triobject id, trisolation id, and triangle number respectively. The function returns "apply" if the user completes the operation and "cancel" if the user cancels the operation. |
| GUI_RECT_CENTER_CORNER(prompt) GUI_DRAG_RECT_CENTER_CORNER(prompt) |
Drag a rubberbanded rectangle between two arbitrary points on the screen. The first point is the center of the rectangle and the second is a corner of the rectangle. prompt is the prompt to display to the user before the operation proceeds. The macro variables (gui_objectx1, gui_objecty1, gui_objectz1) are set to the coordinates of the first point and the macro variables (gui_objectx2, gui_objecty2, gui_objectz2) are set to the coordinates of the second point. The function returns "apply" if the user completes the operation and "cancel" if the user cancels the operation. |
| GUI_RECT_CORNER_CORNER(prompt) GUI_DRAG_RECT_CORNER_CORNER(prompt) |
Drag a rubberbanded rectangle between two arbitrary points on the screen. The points are taken as diagonally opposite on the rectangle. prompt is the prompt to display to the user before the operation proceeds. The macro variables (gui_objectx1, gui_objecty1, gui_objectz1) are set to the coordinates of the first point and the macro variables (gui_objectx2, gui_objecty2, gui_objectz2) are set to the coordinates of the second point. The function returns "apply" if the user completes the operation and "cancel" if the user cancels the operation. |
| GUI_LINE(prompt) GUI_DRAG_LINE(prompt) |
Drag a rubberbanded line between two arbitrary points on the screen. prompt is the prompt to display to the user before the operation proceeds. The macro variables (gui_objectx1, gui_objecty1, gui_objectz1) are set to the coordinates of the first point and the macro variables (gui_objectx2, gui_objecty2, gui_objectz2) are set to the coordinates of the second point. The function returns "apply" if the user completes the operation and "cancel" if the user cancels the operation. |
| GUI_DRAG_STRING(prompt) | Drag a string on the screen. prompt is the prompt to display to the user before the operation proceeds. The macro variables gui_layer and gui_string_id are set to the layer name and string id of the dragged string respectively. The macro variables (gui_objectdx, gui_objectdy, gui_objectdz) are set to the change in coordinates indicated by the drag. The function returns "apply" if the user completes the operation and "cancel" if the user cancels the operation. |
| GUI_DRAG_SEGMENT(prompt) | Drag a segment on the screen. prompt is the prompt to display to the user before the operation proceeds. The macro variables gui_layer, gui_string_id, and gui_segment_no are set to the layer name, string id and segment number of the dragged segment respectively. The macro variables (gui_objectdx, gui_objectdy, gui_objectdz) are set to the change in coordinates indicated by the drag. The function returns "apply" if the user completes the operation and "cancel" if the user cancels the operation. |
| GUI_DRAG_POINT(prompt) | Drag a point on the screen. prompt is the prompt to display to the user before the operation proceeds. The macro variables gui_layer, gui_string_id, gui_segment_no, and gui_point_no are set to the layer name, string id, segment number, and point number of the dragged point respectively. The macro variables (gui_objectdx, gui_objectdy, gui_objectdz) are set to the change in coordinates indicated by the drag. The function returns "apply" if the user completes the operation and "cancel" if the user cancels the operation. |
| GUI_DRAG_STRING_CONSTRAINED (prompt, contraint) | Drag a string on the screen subject to constraints. prompt is the prompt to display to the user before the operation proceeds. constraint can have one of the values "XYZ" to allow unconstrained dragging, "X" to constrain dragging along the X axis, "Y" to constrain dragging along the Y axis, "Z" to constrain dragging along the Z axis, "XY" to constrain dragging in the XY plane, "XZ" to constrain dragging in the XZ plane, "YZ" to constrain dragging in the YZ plane. The macro variables gui_layer and gui_string_id are set to the layer name and string id of the dragged string respectively. The macro variables (gui_objectdx, gui_objectdy, gui_objectdz) are set to the change in coordinates indicated by the drag. The function returns "apply" if the user completes the operation and "cancel" if the user cancels the operation. |
| GUI_DRAG_SEGMENT_CONSTRAINED (prompt, constraint) | Drag a segment on the screen subject to constraints. prompt is the prompt to display to the user before the operation proceeds. constraint can have one of the values "XYZ" to allow unconstrained dragging, "X" to constrain dragging along the X axis, "Y" to constrain dragging along the Y axis, "Z" to constrain dragging along the Z axis, "XY" to constrain dragging in the XY plane, "XZ" to constrain dragging in the XZ plane, "YZ" to constrain dragging in the YZ plane. The macro variables gui_layer, gui_string_id, and gui_segment_no are set to the layer name, string id and segment number of the dragged segment respectively. The macro variables (gui_objectdx, gui_objectdy, gui_objectdz) are set to the change in coordinates indicated by the drag. The function returns "apply" if the user completes the operation and "cancel" if the user cancels the operation. |
| GUI_DRAG_POINT_CONSTRAINED (prompt, constraint) | Drag a point on the screen subject to constraints. prompt is the prompt to display to the user before the operation proceeds. constraint can have one of the values "XYZ" to allow unconstrained dragging, "X" to constrain dragging along the X axis, "Y" to constrain dragging along the Y axis, "Z" to constrain dragging along the Z axis, "XY" to constrain dragging in the XY plane, "XZ" to constrain dragging in the XZ plane, "YZ" to constrain dragging in the YZ plane. The macro variables gui_layer, gui_string_id, gui_segment_no, and gui_point_no are set to the layer name, string id, segment number, and point number of the dragged point respectively. The macro variables (gui_objectdx, gui_objectdy, gui_objectdz) are set to the change in coordinates indicated by the drag. The function returns "apply" if the user completes the operation and "cancel" if the user cancels the operation. |
| FILE_ACCESS(filename, mode) | checks a file to see if permission is allowed to open it for reading, writing or appending if mode is "read", "write", or "append" respectively. Returns true if the access is allowed and false otherwise. |
| FILE_OPEN(filename, mode) | opens a file for reading, writing a new file, or appending to an existing file depending on the mode argument, where mode can be one of "read", "write", or "append". On failure handle_var will become the empty string "". As a future mode may allow the opening of files in binary mode as well as text mode. FILE_OPEN returns a handle for use with the other FILE_ functions. |
| FILE_READLINE(handle_var) | reads and returns a line from a file without the line terminator characters. The handle_var must have been previously assigned the value of a FILE_OPEN with mode == "read". If the end of the file has been detected the empty string "" will be returned. To determine if an empty line has been read or if the end of the file has been reached use FILE_EOF whenever FILE_READLINE returns the empty string. |
| FILE_WRITELINE(handle_var, line_string) | writes a line to a file. The line_string should not include the line terminator characters as they will be output after the line_string. The handle_var must have been previously assigned the value of a FILE_OPEN with mode == "write" or "append". Returns "" on success and an error message on failure. |
| FILE_EOF(handle_var) | test a file opened for reading to see if the end of the file has been reached. Returns true if end of file has been reached during a previous read. |
| FILE_CLOSE(handle_var) | close a previously opened file. Returns "" on success and an error message on failure. |
A further extension with macro expressions is the predefined variable _MACRO_STATUS which is set to the status of the most recent function or macro invocation. A negative value typically means that an error occurred or the cancel button was pressed. A positive value or zero normally means that the function or macro completed successfully. (NOTE - Some functions, typically graphical selection functions, do not return a correct status at present (they always return zero, even on error) so the value of _MACRO_STATUS should be treated with caution).
Macro GUI (Graphical User Interface) Functions
The macro GUI functions GUI_STR and GUI_FILE interpret a GUI definition for user interaction. The low level GUI toolkit used is the same as that used for all GUI interaction and the GUI definition can be quite complicated. A subset of the GUI definition syntax is described here so that you can easily create useful forms and menus for use within macros. There are four types of GUI definitions:
- Menus
Menu definitions start with ``(menu '' and finish with a matching ``)''. Since it is possible to create menu definitions using the custom menu tools they will not be further described here.
- Generic Forms
Generic form definitions start with ``(form '' and finish with a matching ``)''. As the form syntax can be quite complicated, and since not all aspects of forms are supported for use within macros, they are not generally available for use. There is no guarantee that a form definition which works with one release of the software will still work with a later release. It is preferable to use simple forms and dialogue forms since they will always work with future releases.
- Simple Forms
Simple form definitions start with ``(simple_form '' and finish with a matching ``)''. A simple form allows you to lay out labels and prompting fields for a number of macro variables on the one form. The format of a simple form is
`(simple_form
(heading "heading text")
(label "label text 1") (field variable_name_1" attributes)
(label "label text 2") (field "variable_name_2" attributes)
...)'where attributes are described below. A field may be present without a corresponding label and likewise a label may be present without a corresponding field. Eg.
`(simple_form (heading "This is a simple form")
(label "This is a simple form with one output and two entry fields")
(label "Output Only:") (field "output_only_field" (input disallowed))
(label "Input 1:") (field "field1")
(label "Input 2:") (field "field2"))'. - Dialogue Forms
Dialogue form definitions start with ``(dialog_form '' and finish with a matching ``)''. A dialogue form only allows one value to be prompted for but it does guarantee that the prompt will not overlap the image on the viewport and so prompting will not force a redraw of the current picture. This is usually preferable when complicated pictures are displayed. The format of a dialogue form is
`(dialog_form (label "label text") (field "variable_name" attributes ))'where the attributes are described below. Eg.
`(dialog_form (label "Angle Increment:") (field "increment_angle" (format decimal_angle)))'
The field attributes available for use with simple forms and dialogue forms are:
| Attribute | Option | Description |
|---|---|---|
| input | (input allowed) | input/output field (default) |
| (input disallowed) | output only field | |
| null | (null allowed) | value may be empty (default) |
| (null disallowed) | value must not be empty | |
| low_bound | (low_bound number) | numeric value must be greater than or equal to number |
| high_bound | (high_bound number) | numeric value must be less than or equal to number |
| translate | (translate mixed) | do not change case (default) |
| (translate upper) | convert all characters to uppercase | |
| (translate lower) | convert all characters to lowercase | |
| echo | (echo normal) | echo characters normally (default) |
| (echo asterisks) | echo characters as asterisks | |
| (echo none) | do not echo characters | |
| max_length | (max_length n) | maximum allowed input length. Default is 32 |
| display_length | (display_length n) | Displayed length of field. Default is 32. If present this must be the first attribute for the field. |
| format | (format none) | (default) |
| (format integer_4) | format value as an integer*4 | |
| (format integer_2) | format value as an integer*2 | |
| (format real_exp) | format value as a real with an explicit exponent, e.g. 123.456E10 | |
| (format real_8) | format value as a real*8 | |
| (format real_4) | format value as a real*4 | |
| (format decimal_angle) | format value as a decimal angle | |
| (format dms_angle) | format as degrees,minutes,seconds ie. ddd.mmsss | |
| (format datetime) | format as "yyyy-mm-dd hh:mm:ss" | |
| (format range) | format as a range specifier | |
| (format string_field) | format as a string field identifier, e.g. X, Y, Z, D1, D2, D3, ..., D100 | |
| (format db_charset) | format as a database identifier, ie. a valid database table or field name | |
| (format colour) | Format as a colour name. This option also attaches a non-exclusive browser of standard colour names. To specify an arbitrary colour use a value of the form "r=0.5 g=0.75 b=0.0". | |
| value_in | (value_in exclusive "value1" "value2" ...) | Ensure that the value entered is a member of the specified list of values. This option also attaches a browser to the field. |
| (value_in non_exclusive "value1" "value2" ...) | Attach a browser to the field for the specified list of values but also allows you to enter values which are not in the list of values. | |
| (value_in "value1" "value2" ...) | same as (value_in exclusive ...) | |
| decimals | (decimals n) | Specify the number of decimal places to use when formatting a real value. This only has effect with a real_8 format. |
Finally here is an example of the use of the GUI_STR function to display a menu:
@assign menu = '(menu "demomenu" (size 30 10) (heading "MENU") \
(no_entries 8)\
(item (function "menu1") \
(text "Menu1")) \
(item (function "menu2") \
(text "Menu2")) \
(item (function "menu3") \
(text "Menu3")) \
(item (function "menu4") \
(text "Menu4")) \
(item (function "menu5") \
(text "Menu5")) \
(item (function "menu6") \
(text "Menu6")) \
(item) \
(item (function "menu previous") (text "Previous")) \
)'
@assign status = GUI_STR(menu)
@while (status ne 'exit' && status ne 'cancel' && \
status ne 'menu previous')
@message('Menu status was ' . status)
@assign status = GUI_STR(menu)
@endwhile
|
and an example of using a simple form:
@assign field1 = "Loaded from string"
@assign field2 = "Initial value, please change me"
@assign field3 = "goodbye"
@assign field4 = 32
@assign form = '(simple_form \
(heading "Example simple layout form from a string") \
(label "This is an example of a simple form which automatically") \
(label "formats the fields in label/entry area columns") \
(label "") \
(label "FIELD 1:") (field "field1" (input disallowed)) \
(label "FIELD 2:") (field "field2") \
(label "FIELD 3:") (field "field3") \
(label "Integer FIELD:") (field "field4" (format integer_4)) \
)'
@assign form_status = GUI_STR(form)
@message('form status was "' cat form_status cat '"')
@if (form_status eq 'apply')
@message(' field 1 was "' cat field1 cat '"')
@message(' field 2 was "' cat field2 cat '"')
@message(' field 3 was "' cat field3 cat '"')
@message(' field 4 was "' cat field4 cat '"')
@endif
|
and an example of using a dialog form:
@assign angle = 1.112
@assign form = '(dialog_form \
(label "ANGLE:") (field "angle" (format decimal_angle)))'
@assign form_status = GUI_STR(form)
@message('form status was "' cat form_status cat '"')
@if (form_status eq 'apply')
@message(' angle was "' cat angle cat '"')
@endif
|
The example below shows how some of these macro features can be combined to prompt a user for input and control the flow of the macro by using conditional statements and control flow statements.
@LABEL start
@ASSIGN input=GUI_STR('(simple_form(heading "End of Month Report")\
(label "Month")(field "month"(input allowed)(value_in "jan" "feb" "mar" "apr" "may")\
(help "Enter the month to be reported"))\
(label "Lowest Level Mined")(field "level1"(input allowed)(format integer_4)(help "Enter the lowest level mined"))\
(label "Highest Level Mined")(field "level2"(input allowed)(format integer_4)(help "Enter the highest level mined"))\
)')
@IF (input eq 'cancel')
@GOTO return_label
@ENDIF
@IF (level1 > level2)
@ALERT
@ALERT
@MESSAGE You must enter the lowest level first
@GOTO start
@ENDIF
@MACRO intersect,error=abort|12030|pit|200
@MACRO GCREPORT,error=abort
@ASSIGN step=5
@RANGE(level = level1.','.level2.','.step)
@MACRO plot,error=abort|@(level)
@ENDRANGE
@LABEL return_label
|
Troubleshooting
As the creation of macros inevitably involves the use of a text editor, this can lead to errors in syntax when playing back your macros. Following are some tips you may like to follow when trying to track down problems within your macro:
-
When a macro aborts, check the message window.
The error messages echoed to your message window will always indicate the type of problem and give you some idea where to look for the problem. You may have to scroll back through you message window to find where the macro failed. When an error is encountered with a Surpac Function the line number will be displayed. This doesn't mean that the problem is exactly at this line, but may be just after the line number. Remember that when Surpac reports an error for a FORM that you use a continuation character (\) within macros so that you don't end up with incredibly long lines for each form. However when Surpac reports an error for a form it will always indicate this as being the first line, it may in fact be further down than this.
-
Check Variable Names
Variable names are case sensitive, so that a variable called level is different to a variable called Level. Always check that the spelling for variable names is consistent.
-
Check that brackets and apostrophes always close
An error indicating a parsing problem, or a problem evaluating a function more often than not indicates that brackets and quotations aren't closed. Every "(" should have a corresponding" )".
-
Check that there are no characters after a continuation character
Any characters (eg a TAB or a space) which fall directly after a continuation character within a form will cause the macro to fail with a parsing error.