Macro Language Changes

This chapter gives details of the changes made in KEDIT for Windows 1.5 to KEDIT's macro language, KEXX.

Binary Strings

Hexadecimal strings have always been available in KEXX, and binary strings are now also available. They consist of strings of binary digits (``0'' or ``1''), with each group of four binary digits representing one hexadecimal digit. Binary strings are delimited by single or double quotes and are followed by the character ``b'' or ``B''.
'0010 0100'b    '11010111'b
These strings are equivalent to the strings
'24'x           'D7'x

New and Changed Keyword Instructions

CALL name [expr [,expr ...]]
CALL ON condition [NAME trapname]
CALL OFF condition

They are discussed in Section 7.5, ``Conditions''.

DROP var1 [var2 ...]

The DROP instruction resets the specified variables to their default values (that is, the name of the variables in uppercase), freeing up any space used to hold the variables and their current values. If you DROP a stem, the values of all compound variables whose names begin with the specified stem are also dropped.

New in KEDIT for Windows 1.5: The list of variables can also include variable names in parentheses. When a variable name in parentheses is encountered, the variable itself is not dropped, but its value is taken as a list of variables that should themselves be dropped. For example:

list = 'a b c.19'
drop v1 v2 (list) xyz
would drop the variables V1, V2, A, B, C.19, and XYZ.

INTERPRET expr

In previous versions of KEXX, instructions processed by INTERPRET could not CALL internal routines or invoke internal routines as functions. This limitation has been removed.

PROCEDURE [EXPOSE var1 var2 ...]

PROCEDURE EXPOSE is new in KEDIT for Windows 1.5. The PROCEDURE instruction is valid only at the start of a KEXX internal routine; it must be the first instruction encountered after the label that begins the internal routine. The PROCEDURE instruction tells KEXX to make all variables used in the routine local to the routine. Variables in the routine do not inherit values from the calling routine and variables set in the routine do not affect the values of variables of the same name in the calling routine. In contrast, when PROCEDURE is not the first instruction of an internal routine, all variables used in the routine are shared with the calling routine.

* PROCEDURE Example
 do i = 1 to 10
   say sum(i)
   end
 exit
sum: procedure
 * i in this procedure doesn't affect i in main routine
 total = 0
 do i = 1 to arg(1)
    total = total + i
    end
 return total
PROCEDURE can optionally be followed by the keyword EXPOSE and a list of variables that should not be local to the procedure, but should instead be shared with the caller of the procedure. That is, references to variables in the list are treated as references to variables of the same name in the calling procedure. For example:
x = 1
 y = 2
 call test
 say x y
 exit
test: procedure expose x
 x = 55
 y = 66
 return
would display ``55 2'', because changes made within TEST to the value of X are exposed to the caller, while changes made to Y are not.

The list of variables to be exposed can include simple variables, compound variables, and stem variables. Items in the list can also be variable names in parentheses. In this case, the variable in parentheses is first exposed, and then its value is taken to be a list of additional variables to be exposed. For example:

height = 12
 width  = 13
 depth  = 14
 globals = 'height width'
 call test
 exit
test: procedure expose (globals)
 say height width depth
 return
would display ``12 13 DEPTH'', since height and width are exposed, but depth is not.

SELECT
WHEN expr THEN clause
...
[OTHERWISE clause]
END

The SELECT instruction, and the related WHEN and OTHERWISE instructions, are new in KEDIT for Windows 1.5.

The SELECT instruction lets you execute one sequence of instructions out of a set of possible alternatives. SELECT offers a cleaner way of specifying what would otherwise be a sequence of IF -- THEN -- ELSE instructions.

An example of a SELECT instruction:

select
   when option = 'A' then call optiona
   when option = 'B' then call optionb
   when option = 'C' then do
      say 'Option C selected'
      call optionc
      end
   otherwise
      say 'Unknown option specified'
      return
 end
SELECT constructs begin with a SELECT instruction and end with an END instruction. In between, you use one or more instructions of the form
WHEN expression THEN instruction
Each WHEN expression is tested in sequence. As soon as one is found to be true (that is, has the value 1), the corresponding THEN instruction is executed. To execute more than one instruction when an expression is found to be true, group them together within a DO -- END pair. After the THEN instruction corresponding to the true expression has been executed, no additional WHEN expressions are evaluated, and execution continues with the instruction following the END that terminates the SELECT construct.

The set of WHEN -- THEN instructions can be followed by the keyword OTHERWISE and a sequence of zero or more instructions to be executed if none of the WHEN expressions are true. If you know that at least one of the WHEN expressions will always be true you can omit the OTHERWISE construct, but KEXX generates an error if none of the WHEN expressions are true and OTHERWISE is not present.

SIGNAL label
SIGNAL ON condition [NAME trapname]
SIGNAL OFF condition

The SIGNAL instruction is new in KEDIT for Windows 1.5. Use the SIGNAL instruction to immediately transfer control to some other location within a KEXX program. To do this, use

SIGNAL label
where label is the label to which you want to transfer control. Execution of any active DO, IF, SELECT, and INTERPRET instructions in the current routine is terminated, and execution continues at the specified label.

Also available are

SIGNAL ON condition [NAME trapname]
and
SIGNAL OFF condition
They are discussed in Section 7.5, ``Conditions''.

External Routines

External routines are new in KEDIT for Windows 1.5. With the CALL instruction and with function invocations, you can now call a separate KEXX macro as a subroutine. In the past, you could only invoke separate KEXX macros via the MACRO instruction, but this method provided no convenient way to return a result string from the external macro to the calling macro.

When searching for a function, KEDIT looks first for an internal routine with the specified name, then for a built-in function, an implied EXTRACT function, a Boolean function, and finally an external routine. (The search for an internal routine is bypassed if the name of the function is in quotes.)

The external routine can use PARSE ARG to access the arguments passed to it, and can use the RETURN instruction to pass a result back to the caller.

When searching for an external routine, the order of searching is the same as it is with the MACRO command: in-memory macros loaded via the DEFINE command are searched for first, and then macros in disk files (with a default extension of .KEX) are searched for, with the search order controlled by the current SET MACROPATH setting.

External routine names with drive or path components, or including special characters, must be specified as quoted names.

For example,

CALL 'F:\MACROS\SAMPLE' X, Y, Z
or
SAY '&&'(17)

New Built-in Functions

KEXX now supports all of the built-in functions described in Cowlishaw's The Rexx Language: A Practical Approach to Programming (Second Edition, Prentice-Hall, 1990), with the exception of the STREAM() function. It also supports the following functions, which are not included in Cowlishaw's book: BEEP(), DATECONV(), DELIMIT(), DOSENV(), DOSDIR(), ANSIUPPER(), ANSILOWER(), ANSITOOEM(), OEMTOANSI(), UPPER(), LOWER(), COUNTSTR() and CHANGESTR().

Here are the functions that are new in KEDIT for Windows 1.5:

B2X(binary-string)

Converts a string in binary notation (that is, consisting of zeroes and ones) into the equivalent hexadecimal string. Blanks may be included in binary-string, at four character boundaries.

b2x('1101')                 ==>      'D'
b2x('00001101')          ==>      '0D'
b2x('1011010011111')     ==>      '169F'

CHANGESTR(needle, haystack, newneedle)

Returns the result of changing all occurrences of the string needle in the string haystack into occurrences of the string newneedle.

changestr('a', 'abABab', 'x')               ==>      'xbABxb'
changestr('aa', 'aaabbaa', 'x')  ==>      'xabbx'
changestr('3', '123123123', '')  ==>      '121212'

CONDITION([option])

Returns information about the currently trapped condition. For information about condition handling, see Section 7.5, ``Conditions''. If no condition is currently being handled, the CONDITION() function returns the null string.

Possible values for option, which defaults to ``I'', are:

C

(``Condition name'') Returns the name of the current condition, which can be ERROR, FAILURE, HALT, SYNTAX, or NOVALUE.

D

(``Description'') Returns a description of the current condition. For HALT and SYNTAX conditions, this is the null string. For the ERROR or FAILURE condition, this is the command string that led to the error or failure. For the NOVALUE condition, this is the derived name of the variable involved.

I

(``Instruction'') Returns CALL or SIGNAL, depending on the method used to invoke the signal handler.

S

(``State'') Returns the state of the current condition: ON, OFF, or DELAY.

COUNTSTR(needle, haystack)

Returns the number of occurrences of the string needle in the string haystack.

COUNTSTR('a', 'abABab')             ==>      2
COUNTSTR('aa', 'aaabbaa')        ==>      2
COUNTSTR('3', '123123123')       ==>      3

ERRORTEXT(n)

Returns the text of KEXX error message n. If n is not the number of a KEXX error message, ERRORTEXT() returns the null string. KEXX error messages are currently in the range 93 -- 133.

errortext(100)              ==>      'Control stack full'
errortext(500)           ==>      ''

SOURCELINE([n])

SOURCELINE(), with no arguments, returns the number of lines in the currently-executing KEXX macro.

SOURCELINE(n), where n can be no greater than the number of lines in the current macro, returns the text of the nth line of the macro.

SYMBOL(name)

Returns ``BAD'' if name is not a valid KEXX symbol, returns ``VAR'' if name is a variable to which a value has been assigned, and otherwise returns ``LIT''. After

x = 17
a. = 'Hello'
drop a.17
drop y
the SYMBOL() function would yield:
symbol('==')        ==>      'BAD'
symbol('y')      ==>      'LIT' /* since y has no assigned value */
symbol('a.x')    ==>      'LIT' /* since a.17 has no assigned value */
symbol('x')      ==>      'VAR' /* since x has an assigned value */
symbol(x)                ==>      'LIT' /* since 17 is a literal */

TRACE([setting])

TRACE() with no arguments returns the trace setting currently in effect. That is, it returns `A', `C', `E', `F', `I', `L', `N', `O', or `R', possibly preceded by `?'.

If specified, setting is a new trace setting to put into effect, and can be `?', or one of `A', `C', `E', `F', `I', `L', `N', `O', or `R', optionally preceded by `?'.

VALUE(name [,newvalue])

Returns the value of the symbol specified by name, and optionally assigns to the symbol the value specified by newvalue.

After

a = 's'
a9 = 17
s = '9'
the VALUE() function would yield:
value('a')          ==>    's'
value(a)                         ==>      9
value('a'||s)      ==>    17
value('a', 'Tom')        ==>      's'    /* and sets a = 'Tom' */

X2B(hex-string)

Converts a string in hexadecimal notation to binary notation and returns the result. Blanks may be included in hex-string, at byte boundaries.

x2b('0d')           ==>      '00001101'
x2b('E2')                ==>      '11100010'
x2b(d2x(4095))   ==>      '111111111111'

Conditions

Condition handling is new to KEXX in KEDIT for Windows 1.5. Condition handling is an advanced feature of KEXX that most macro writers need not be familiar with.

You can have a KEXX macro automatically transfer control to a different location in your macro when certain special conditions occur. This allows your macro to, for example, display diagnostic information after a syntax error occurs, or ask a user of the macro who has pressed Ctrl+Break whether to terminate the macro.

The conditions that can be handled are:

  • The HALT condition, triggered when Ctrl+Break is pressed.

  • The FAILURE condition, triggered when a command yields a negative return code.

  • The ERROR condition, triggered when a command yields a positive return code, or when a command yields a negative return code and the FAILURE condition is not enabled. Note that the ERROR condition is not usually useful in KEXX macros, since several KEDIT commands (such as a DOWN command that reaches the End-of-File line) generate positive return codes in non-error situations.

  • The SYNTAX condition, triggered by a syntax error in your macro, or by invalid macro operations like division by zero or passing invalid arguments to a built-in function.

  • The NOVALUE condition, triggered by the use of an uninitialized variable in your macro. By default, user-specified condition handling is disabled and the above conditions are handled as follows: Ctrl+Break and syntax errors cause termination of your macro. Error and failure return codes are ignored. Use of uninitialized variables is ignored if SET NOVALUE OFF is in effect, and causes termination of your macro if SET NOVALUE ON is in effect. Condition handling is most often enabled via this form of the SIGNAL instruction:
    SIGNAL ON condition [NAME trapname]
    
    When SIGNAL ON has been executed for a condition and that condition occurs, control is transferred, as if SIGNALlabel had been executed, to the label specified by trapname or, if NAMEtrapname was omitted, to a label corresponding to the name of the condition. For example, with
    SIGNAL ON HALT
    
    KEXX will transfer control to the label HALT if Ctrl+Break is pressed while your macro is executing.
With
SIGNAL ON HALT NAME BREAKER
KEXX will transfer control to the label BREAKER if Ctrl+Break is pressed while your macro is executing.

You can use

SIGNAL OFF condition
to disable user-specified condition handling and restore the default behavior.

With SIGNAL ON, control is transferred to the appropriate label when a condition is raised, but there is no convenient way of resuming execution of your macro at the point that the condition was detected. An alternative is to use

CALL ON condition [NAME trapname]
which calls your condition handler as a subroutine and, if your subroutine returns, resumes execution immediately following the point where the condition was triggered.

You can use

CALL OFF condition
to disable this form of user-specified condition handling.

CALL ON condition can be used with the HALT, ERROR, and FAILURE conditions, but cannot be used with the SYNTAX and NOVALUE conditions.

Notes

  • When a condition with SIGNAL ON handling in effect occurs, and before control is transferred to the condition handler, SIGNAL OFF is put into effect for that condition, so that the default behavior will take place if the condition occurs again and user-specified condition handling has not been re-enabled.

  • When a condition with CALL ON handling in effect occurs, and before control is transferred to the condition handler, the condition is put into a delayed state, and will be re-enabled on return from your handler. You can also use SIGNAL or CALL instructions within your handler to enable or disable condition handling while your handler is active.

  • While your handler is active, you can use the CONDITION() function to get information about the current trapped condition.

  • For the ERROR and FAILURE conditions, the RC variable is set to the command return code involved before control is transferred to the condition handler. For the SYNTAX condition, the RC variable is set to the message number for the error involved; the text of the message can be retrieved via the ERRORTEXT() function.

  • The SIGL variable is set before control is transferred to your condition handler to the line number of the last clause executed.

KEXX and REXX

KEDIT's macro language, KEXX, contains a large subset of the REXX language. As of KEDIT for Windows 1.5, almost all of the features of REXX, as documented in The REXX Language: APractical Approach to Programming by Michael Cowlishaw (Second Edition, Prentice-Hall, 1990) are available in KEXX. Here are the primary differences between KEXX and REXX:

  • KEXX clauses and comments must fit completely on a single line, and cannot be continued on additional lines.

  • Lines of a KEXX macro are limited to 250 characters, and KEXX macros cannot be longer than 4000 lines.

  • KEXX comment lines that begin with an asterisk (``*'') are not valid in REXX programs. The other form of KEXX comment, delimited by slash-asterisk (``/*'') asterisk-slash (``*/'') pairs, are valid in REXX programs.

  • The maximum NUMERIC DIGITS value supported by KEXX is 50.

  • KEXX does not support the REXX ADDRESS, PUSH, or QUEUE instructions.

  • Control variables in KEXX DO loops must be simple symbols, and the values of the control variable and the expressions involved in DO loop control must be whole numbers with at most 9 digits.

  • TRACE + and TRACE -, used to turn interactive tracing on and off, are supported in KEXX but not in REXX, which supports only TRACE ?, which toggles the status of interactive tracing.

  • The STREAM() built-in function is not available in KEXX.

  • KEXX does not support the NOTREADY condition.

  • Labels in KEXX programs are only valid when they are the first token on a line.

  • KEXX's LINEIN(), LINEOUT(), LINES(), CHARIN(), CHAROUT(), and CHARS() functions require that their first operand be specified. REXX lets you do I/O to the console by omitting this argument.

  • The following REXX features are supported in KEXX, but are not documented here because they are rarely-used and not of interest to most KEDIT users: the second argument (``n'') of the C2D(), D2C(), and X2D() functions, the expp and expt arguments of the FORMAT() function, the NUMERIC FORM instruction, the FORM() function, SIGNAL VALUE, and TRACE VALUE. See the Cowlishaw book for details about these items.

  • For compatibility with older versions of KEDIT, KEXX accepts the characters ``@'', ``#'', and ``$'' as valid in symbols and lets you use ``^'' and ``~'' to indicate negation. These characters are not included in the latest REXX language definition and are considered invalid by some REXX implementations.

KEDIT Home Page
KEDIT Overview | Download Libraries | Maintenance Releases
Ordering/Licensing | Demo Version | Technical Support | What's New
KEDIT for Windows 1.6.1 Upgrade | KEDIT Mailing List

Copyright © 1996-2012 Mansfield Software Group, Inc.