1 – Processing with Lexical Operators
Lexical operator processing is performed on all source lines and macro expansion lines before any other assembler processing. Thus, macro invocations, assembler directives, and instructions are subject to lexical operator processing before normal assembler processing. Lexical operators are recognized and processed within string literals. Lexical operator processing is suppressed during macro registration in order that lexical operator evaluation may occur during macro expansion. Lexical operator evaluation is also suppressed for a range of text that is conditionally excluded with one of the .IF directives. In addition, lexical operator processing is not performed within a comment.
2 – Syntax
You invoke a lexical string operator with a percent sign followed by the lexical operator name, a left parentheses, a list of arguments separated by commas, and a right parentheses. The following example shows the lexical operator syntax: .print "%EDIT(<Fred>,<upcase>)" Spaces are allowed between syntax elements in the general lexical operator syntax. For example, the following syntax, including spaces, is allowed: .print "%EDIT ( <Fred> , <upcase> )" Spaces are also allowed between the opening and closing percent signs in a lexical substitution operator. .print "% lexical_symbol_name %" Spaces are not allowed between the pair of percent signs indicating a lexical escape operator. You can specify lexical operator arguments in the same way as macro arguments: o A numeric symbol name preceded by a backslash (\). This construct results in the decimal value of the numeric symbol, as shown in the following example: \N o Any string of characters surrounded by left- and right-angle brackets, as shown in the following example: <Foo bar thud> You can nest angle brackets (<>). For example: <<X+7>*17> o Any string of characters surrounded by a delimiter specified after a caret character (^). You cannot nest delimiters. For example: ^%Foo bar thud% o Any undelimited string of characters not separated by a space, tab, form feed, comma, equal sign, semicolon, or end of line. For example: A+B+C In addition to the formats allowed for a macro argument, you can also specify lexical operator arguments as follows: o An undelimited string of characters may also contain a string of characters enclosed within left and right parentheses. The characters between the left and right parentheses may contain space, tab, or comma delimiters. For example: 16( R27 ) o You can use a lexical operator as an argument to another lexical operator. For example: %EXTRACT( %LOCATE($,X), %LENGTH(X) - %LOCATE($,X) ,X) Except for the %TYPE lexical operator, a string symbol name supplied as a lexical operator argument is replaced with the value of the string symbol. Each lexical operator accepts a given number of arguments and each argument has a specific type. There are three different types of arguments-string, integer, and name: o A string argument can be any arbitrary sequence of characters. o An integer argument must be an absolute or relocatable expression that can be resolved at that point in the assembly. A relocatable expression represents a psect and an offset within that psect. If you specify a relocatable expression for an integer argument, the assembler uses only the value of the offset within the psect. The offset value is determined before optimization and code alignment, but after data alignment. o The name argument type is used only by the %TYPE lexical operator. The %TYPE lexical operator accepts the name of a numeric symbol, string symbol, label, psect, or a permanent symbol as its argument. Unlike the other lexical operators, if a string symbol name is specified as an argument to %TYPE, the value of the string symbol is not substituted for its name. Instead, information about the name is returned. If you omit a string argument, the default is the empty string. An empty string is a string with no characters. If you omit an integer argument or specify an illegal expression, the default value is 0. The assembler does not issue diagnostic messages for illegal expressions used as arguments to lexical operators. If you omit the name argument or specify an illegal name to the %TYPE lexical operator, %TYPE returns a 0 value.
3 – Numeric Symbols and Lexical String Symbols
Lexical string symbols are similar in concept and syntax to numeric symbols. MACRO-64 supports numeric symbols using the following syntax: numeric_symbol_name = numeric_expression MACRO-64 supports lexical string symbols using the following syntax: string_symbol_name = "any string of characters" The assembler differentiates between numeric symbol assignment and lexical string symbol assignment as follows: o In a lexical string symbol assignment, a quoted string literal must appear after the equal sign. o A lexical string symbol value is specified by the quoted string literal. The quotes are not included in the value of the lexical string symbol. You cannot use the same name for a lexical string symbol, numeric symbol, or label. Like numeric symbols, lexical string symbols are assembly time variables. After you assign a string value to a lexical string symbol, you can reassign a different value to that symbol later in the assembly. You can use lexical string symbols as arguments to lexical operators. In particular, you can use a lexical string symbol as an argument to the lexical substitution operator (%) or the %STRING lexical operator to substitute the value of the lexical string symbol at any point in the text of your program.
4 – Lexical Substitution Operator
You can use the lexical substitution operator at any point in your program to cause the assembler to substitute the value of a lexical string symbol for the name of the symbol. The lexical substitution operator is the percent sign (%). Place the lexical substitution operator to the left and right of the name of the lexical string symbol that you wish to subsitute, as follows: %lexsym_name% For example: HORSES = "All the king's horses" MEN = "all the king's men" .print "%HORSES% and %MEN%" This example defines two lexical string symbols: HORSES and MEN. The third statement displays a message at assembly time. The text of the message specifies that the value of the HORSES and MEN lexical string symbols be substituted as indicated. After lexical processing, the third statement appears as: .print "All the king's horses and all the king's men"
5 – Lexical Escape Operator
It is possible to defer the processing of a lexical string operator by using the lexical escape operator, which is the percent sign (%). Since all lexical string operators begin with a percent sign, the effect of placing two percent signs before the name of the lexical string operator defers the evaluation of the lexical string operator. If you want to defer processing of a lexical substitution operator, place two percent signs to the left and two percent signs to the right of the lexical string symbol name. This can be useful when you want the evaluation of a lexical string operator that you have used in a default macro argument to occur during macro expansion, rather than during macro definition. Lexical operator processing is suppressed during macro registration. Therefore, lexical operator processing is automatically deferred within the body of a macro. However, the .MACRO directive line that begins the macro definition is subject to normal lexical operator processing. Sometimes you may need to use the value of a lexical string symbol as the default for a macro argument, but you need to use the value of the lexical string symbol that is current when the macro expands, not when the macro is defined. Lexical Processing Without the Escape Operator shows an example of this, but it does not use an escape operator. Example 1 Lexical Processing Without the Escape Operator CODE_PSECT_NAME = "CODE1" .MACRO CODE_PSECT PSECT_NAME=%string(CODE_PSECT_NAME) .PSECT PSECT_NAME .ENDM CODE_PSECT CODE_PSECT CODE_PSECT_NAME = "CODE2" CODE_PSECT Lexical Processing Without the Escape Operator does not process correctly for the following reasons: o The lexical operator in the .MACRO directive line is processed when the macro is defined, not when the macro expands. o The CODE_PSECT macro always defaults to setting the psect to the CODE1 psect because the default for the PSECT_NAME argument will be set to CODE1, not %string(CODE_PSECT_NAME). This is because %string(CODE_PSECT_NAME) is evaluated when the CODE_PSECT macro is defined, not when it expands. Lexical Processing with Escape Operator is similar to Lexical Processing Without the Escape Operator except it uses the lexical escape operator. Example 2 Lexical Processing with Escape Operator CODE_PSECT_NAME = "CODE1" .macro CODE_PSECT PSECT_NAME=%%string(CODE_PSECT_NAME) .psect PSECT_NAME .endm CODE_PSECT CODE_PSECT CODE_PSECT_NAME = "CODE2" CODE_PSECT Lexical Processing with Escape Operator processes correctly for the following reasons: o Lexical operator processing of %%string(CODE_PSECT_NAME) is deferred when the CODE_PSECT macro is defined. The default value for the PSECT_NAME argument is stored as %string(CODE_PSECT_NAME). o During macro expansion, %string(CODE_PSECT_NAME) is evaluated, which results in the current value of the CODE_PSECT_NAME lexical string symbol as desired.
6 – %EDIT
Lexical operator for editing text strings. Format %EDIT (string1,string2)
6.1 – Arguments
string1 The first argument, of type string, specifies the string to be edited. string2 The second argument, of type string, specifies a list of edits to perform, which are separated by commas.
6.2 – Description
%EDIT is modeled after the OpenVMS DCL lexical function F$EDIT. It is used to perform one or more edits on a specified string. %EDIT processes the string of arguments from left to right. %EDIT gives precedence to the last argument. %EDIT gives precedence to uppercase over lowercase. The list of edits may contain any combination of the following elements: Element Function COLLAPSE Removes all tabs and spaces. COMPRESS Replaces multiple, consecutive tabs or spaces with a single space. LOWERCASE Changes uppercase characters to lowercase. TRIM Removes leading and trailing spaces and tabs. UPCASE Changes lowercase characters to uppercase.
6.3 – Examples
Example 1 .PRINT "%EDIT(< Fred Smith >, <TRIM,COLLAPSE,UPCASE>)" After lexical processing, the statement apears as the following: .PRINT "FREDSMITH" Example 2 .PRINT "%EDIT(<AbCdEfG>,<upcase,lowercase>) .PRINT "%EDIT(<AbCdEfG>,<lowercase,upcase>) The first source statement produces the string "abcdefg" and the second source statement produces the string "ABCDEFG". Each of the edits in the edit list is performed in sequence, from left to right.
7 – %ELEMENT
Lexical operator for extracting elements from a list of elements. Format %ELEMENT (integer,string1,string2)
7.1 – Arguments
integer The first argument, of type integer, is the element number to extract. The first element is number 0. string1 The second argument, of type string, is the delimiter or delimiters that separate elements. string2 The third argument, of type string, is the list of elements.
7.2 – Description
%ELEMENT is modeled after the OpenVMS DCL lexical function F$ELEMENT. It is used to extract one element from a string of elements. Note that unlike F$ELEMENT, you may specify multiple delimiters. The result is the specified string element. If the specified element number is greater than the number of elements in the list, the delimiter argument is returned.
7.3 – Example
.PRINT "%ELEMENT (2, <+-*/>, JOE+FRED-TOM*BILL/ERIC)" After lexical processing, the statement appears as: .PRINT "TOM"
8 – %EXTRACT
Lexical operator for extracting a range of characters from a string of characters. Format %EXTRACT (integer1,integer2,string)
8.1 – Arguments
integer1 The first argument, of type integer, is the offset at which to begin the extraction. The first character is at offset 0. integer2 The second argument, of type integer, is the number of characters to extract. string The third argument, of type string, is the string from which to extract the characters.
8.2 – Description
%EXTRACT is modeled after VAX MACRO's %EXTRACT macro string operator and the OpenVMS DCL lexical function F$EXTRACT. %EXTRACT is used to extract a specified range of characters from a string.
8.3 – Example
.PRINT "%EXTRACT(3,4,ABCDEFGHIJKLMNOP)" After lexical processing, the statement appears as: .PRINT "DEFG"
9 – %FREG
Lexical operator for obtaining the floating-point register number associated with a symbol. Format %FREG (symbol)
9.1 – Argument
symbol The single argument, of type string, specifies a symbol that may or may not be currently defined as a floating-point register symbol.
9.2 – Description
%FREG returns the decimal number of the floating-point register when the specified symbol is defined as a floating-point register symbol. Otherwise, %FREG returns 32.
9.3 – Example
; Is TARG_REG the same as F31? .IF EQ, <%FREG(TARG_REG)>, <%FREG(31)> If TARG_REG has been defined as floating-point register F5, the statements appear as follows after lexical processing: ; Is TARG_REG the same as F31? .IF EQ, <5>, <31>
10 – %INTEGER
Lexical operator for converting the value of an expression to a decimal value. Format %INTEGER (integer)
10.1 – Argument
integer The single argument, of type integer, is the expression to be converted.
10.2 – Description
%INTEGER is modeled after the OpenVMS DCL lexical function F$INTEGER. It is used to convert the value of an expression to a decimal value. The result is its decimal value. You can also use %INTEGER to convert a relocatable expression to an absolute value.
10.3 – Example
.PRINT "%INTEGER (<<X+7>*17>)" After lexical processing, if X has the value 3, the statement will appear as: .PRINT "170"
11 – %IREG
Lexical operator for obtaining the integer register number associated with a symbol. Format %IREG (symbol)
11.1 – Argument
symbol The single argument, of type string, specifies a symbol that may or may not be currently defined as an integer register symbol.
11.2 – Description
%IREG returns the decimal number of the integer register when the specified symbol is defined as an integer register symbol. Otherwise, %IREG returns 32.
11.3 – Example
; Is SRC_REG the same as SP? .IF EQ, <%IREG(SRC_REG)>, <%IREG(SP)> If SRC_REG has been defined as integer register R16, the statements appear as follows after lexical processing: ; Is SRC_REG the same as SP? .IF EQ, <16>, <30>
12 – %LENGTH
Lexical operator for determining the length of a string. Format %LENGTH (string)
12.1 – Argument
string The single argument, of type string, is the string from which the length is to be computed.
12.2 – Description
%LENGTH is modeled after VAX MACRO's %LENGTH macro string operator and the OpenVMS DCL lexical function F$LENGTH. %LENGTH is used to determine the length of a string. The result is the length of the string expressed as a decimal number.
12.3 – Example
.PRINT "%LENGTH(<The quick brown fox>)" After lexical processing, the statement appears as: .PRINT "19"
13 – %LOCATE
Lexical operator for locating a string of text within another string of text. Format %LOCATE (string1,string2)
13.1 – Arguments
string1 The first argument, of type string, is the string for which %LOCATE searches. string2 The second argument, of type string, is the string in which the search is performed.
13.2 – Description
%LOCATE is modeled after VAX MACRO's %LOCATE macro string operator and the OpenVMS DCL lexical function F$LOCATE. %LOCATE is used to locate one string within another. The value returned is the decimal offset to the first occurrence of the first string within the second string. The offset to the first character is 0. If the first string cannot be found within the second string, the length of the second string is returned.
13.3 – Example
.PRINT "%LOCATE (DEF,ABCDEFGHIJKLMNOP)" After lexical processing, the statement appears as: .PRINT "3"
14 – %REPEAT
Lexical operator for repeating a specified string a specified number of times. Format %REPEAT (integer,string)
14.1 – Arguments
integer The first argument, of type integer, is the number of times to repeat the string. If you specify a negative value, the string is repeated 0 times. string The second argument, of type string, is the string to be repeated.
14.2 – Description
%REPEAT is used to repeat the specified string a specified number of times.
14.3 – Example
.PRINT "Never, %REPEAT (3, <ever, >)touch that button!" After lexical processing, the statement appears as: .PRINT "Never, ever, ever, ever, touch that button!"
15 – %STRING
Lexical operator for obtaining the value of a lexical string symbol. Format %STRING (string)
15.1 – Argument
string The single argument is of type string. If the argument is the name of the lexical string symbol, the value of the lexical string symbol is returned. Otherwise, the argument is returned unchanged.
15.2 – Description
%STRING is modeled after the OpenVMS DCL lexical function F$STRING. %STRING is generally used to obtain the value of a lexical string symbol, but you can use it with any string argument.
15.3 – Example
FOO = "All the king's horses" .PRINT "%STRING(FOO)" After lexical processing, the statement appears as: .PRINT "All the king's horses"
16 – %TIME
Lexical operator for obtaining the date and time of the assembly unit. Format %TIME ()
16.1 – Description
%TIME is modeled after the OpenVMS DCL lexical function F$TIME. %TIME is used to obtain the time and date of the assembly unit. There are no arguments. The result is a string specifying the date and time of the assembly unit.
16.2 – Example
.PRINT "%TIME()" After lexical processing, the statement appears as: .PRINT " 8-OCT-1991 13:17:57"
17 – %TYPE
Lexical operator for obtaining information about a name. Format %TYPE (name)
17.1 – Argument
name The single argument is of type name. Information is returned about the name specified in the argument.
17.2 – Description
%TYPE is modeled after the OpenVMS DCL lexical function F$TYPE. %TYPE is used to obtain information about a name. The value returned is a numeric value with certain bit positions, either 0 or 1, depending on whether the specified name has the corresponding attribute. As described elsewhere, the decimal digits of the numeric value are substituted for the %TYPE lexical operator. %TYPE Attributes shows the symbolic names that are predefined for each attribute. Table 5 %TYPE Attributes Symbolic Name Attribute MACRO64$TYPE_SYMBOL Name is a numeric symbol name. MACRO64$TYPE_PROC_ Name is a procedure descriptor name. DESC MACRO64$TYPE_LABEL Name is a label. MACRO64$TYPE_EXTERN Name is an external name. MACRO64$TYPE_WEAK Name is a weak name. MACRO64$TYPE_PSECT Name is a psect. MACRO64$TYPE_MACRO Name is a macro name. MACRO64$TYPE_STRING Name is a lexical string symbol name. MACRO64$TYPE_OPCODE Name is an opcode. MACRO64$TYPE_DIR Name is a directive. MACRO64$TYPE_GENREG Name is a general register. MACRO64$TYPE_FLTREG Name is a floating register. A given name may have zero, one, or several attributes.
17.3 – Example
.macro IS_GR ARG .IF equal, %TYPE(ARG) & <MACRO64$TYPE_GENREG> .PRINT "ARG is not a general register" .ENDC .endm IS_GR IS_GR F11 Initially, the first line of the IS_GR macro expands as the following: .IF equal, <%TYPE(F11) & MACRO64$TYPE_GENREG> After lexical processing, the statement appears as: .IF equal, <8192 & MACRO64$TYPE_GENREG> In this example, 8192 is the attribute value for a floating- point register. This value could change in subsequent releases. Use only the predefined attribute masks described in %TYPE Attributes. Since the attribute for a general register MACRO64$TYPE_GENREG is 4096, the expression evaluates as 0. <8192 & MACRO64$TYPE_GENREG>