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>