Document revision date: 19 July 1999 | |
Previous | Contents | Index |
By using macros, you can use a single line to insert a sequence of source lines into a program.
A macro definition contains the source lines of the macro. The macro definition can optionally have formal arguments. These formal arguments can be used throughout the sequence of source lines. Later, the formal arguments are replaced by the actual arguments in the macro call.
The macro call consists of the macro name optionally followed by actual arguments. The assembler replaces the line containing the macro call with the source lines in the macro definition. It replaces any occurrences of formal arguments in the macro definition with the actual arguments specified in the macro call. This process is called the macro expansion.
The macro directives (described in Chapter 6) provide facilities for performing eight categories of functions. Table 6-2 lists these categories and the directives that fall under them.
By default, macro expansions are not printed in the assembly listing. They are printed only when the .SHOW directive (see description in Chapter 6) or the /SHOW qualifier (described in the OpenVMS DCL Dictionary) specifies the EXPANSIONS argument. In the examples in this chapter, the macro expansions are listed as they would appear if .SHOW EXPANSIONS was specified in the source file or /SHOW=EXPANSIONS was specified in the MACRO command string.
The remainder of this chapter describes macro arguments, created local
labels, and the macro string operators.
4.1 Arguments in Macros
Macros have two types of arguments: actual and formal. Actual arguments are the strings given in the macro call after the name of the macro. Formal arguments are specified by name in the macro definition; that is, after the macro name in the .MACRO directive. Actual arguments in macro calls and formal arguments in macro definitions can be separated by commas (,), tabs, or spaces.
The number of actual arguments in the macro call can be less than or equal to the number of formal arguments in the macro definition. If the number of actual arguments is greater than the number of formal arguments, the assembler displays an error message.
Formal and actual arguments normally maintain a strict positional relationship. That is, the first actual argument in a macro call replaces all occurrences of the first formal argument in the macro definition. This strict positional relationship can be overridden by the use of keyword arguments (see Section 4.3).
An example of a macro definition using formal arguments follows:
.MACRO STORE ARG1,ARG2,ARG3 .LONG ARG1 ; ARG1 is first argument .WORD ARG3 ; ARG3 is third argument .BYTE ARG2 ; ARG2 is second argument .ENDM STORE |
The following two examples show possible calls and expansions of the macro defined previously:
STORE 3,2,1 ; Macro call .LONG 3 ; 3 is first argument .WORD 1 ; 1 is third argument .BYTE 2 ; 2 is second argument STORE X,X-Y,Z ; Macro call #.LONG X ; X is first argument #.WORD Z ; Z is third argument #.BYTE X-Y ; X-Y is second argument |
Default values are values that are defined in the macro definition. They are used when no value for a formal argument is specified in the macro call.
Default values are specified in the .MACRO directive as follows:
formal-argument-name = default-value |
An example of a macro definition specifying default values follows:
.MACRO STORE ARG1=12,ARG2=0,ARG3=1000 .LONG ARG1 .WORD ARG3 .BYTE ARG2 .ENDM STORE |
The following three examples show possible calls and expansions of the macro defined previously:
STORE ; No arguments supplied .LONG 12 .WORD 1000 .BYTE 0 STORE ,5,X ; Last two arguments supplied .LONG 12 .WORD X .BYTE 5 STORE 1 ; First argument supplied .LONG 1 .WORD 1000 .BYTE 0 |
Keyword arguments allow a macro call to specify the arguments in any order. The macro call must specify the same formal argument names that appear in the macro definition. Keyword arguments are useful when a macro definition has more formal arguments than need to be specified in the call.
In any one macro call, the arguments should be either all positional arguments or all keyword arguments. When positional and keyword arguments are combined in a macro, only the positional arguments correspond by position to the formal arguments; the keyword arguments are not used. If a formal argument corresponds to both a positional argument and a keyword argument, the argument that appears last in the macro call overrides any other argument definition for the same argument.
For example, the following macro definition specifies three arguments:
.MACRO STORE ARG1,ARG2,ARG3 .LONG ARG1 .WORD ARG3 .BYTE ARG2 .ENDM STORE |
The following macro call specifies keyword arguments:
STORE ARG3=27+5/4,ARG2=5,ARG1=SYMBL .LONG SYMBL .WORD 27+5/4 .BYTE 5 |
Because the keywords are specified in the macro call, the arguments in
the macro call need not be given in the order they were listed in the
macro definition.
4.4 String Arguments
If an actual argument is a string containing characters that the assembler interprets as separators (such as a tab, space, or comma), the string must be enclosed by delimiters. String delimiters are usually paired angle brackets (<>).
The assembler also interprets any character after an initial circumflex (^) as a delimiter. To pass an angle bracket as part of a string, you can use the circumflex form of the delimiter.
The following are examples of delimited macro arguments:
<HAVE THE SUPPLIES RUN OUT?> <LAST NAME, FIRST NAME> <LAB: CLRL R4> ^%ARGUMENT IS <LAST,FIRST> FOR CALL% ^?EXPRESSION IS <5+3>*<4+2>? |
In the last two examples, the initial circumflex indicates that the percent sign (%) and question mark (?) are the delimiters. Note that only the left-hand delimiter is preceded by a circumflex.
The assembler interprets a string argument enclosed by delimiters as one actual argument and associates it with one formal argument. If a string argument that contains separator characters is not enclosed by delimiters, the assembler interprets it as successive actual arguments and associates it with successive formal arguments.
For example, the following macro call has one formal argument:
.MACRO REPEAT STRNG .ASCII /STRNG/ .ASCII /STRNG/ .ENDM REPEAT |
The following two macro calls demonstrate actual arguments with and without delimiters:
REPEAT <A B C D E> .ASCII /A B C D E/ .ASCII /A B C D E/ REPEAT A B C D E %MACRO-E-TOOMNYARGS, Too many arguments in macro call |
Note that the assembler interpreted the second macro call as having five actual arguments instead of one actual argument with spaces.
When a macro is called, the assembler removes any delimiters around a string before associating it with the formal arguments.
If a string contains a semicolon (;), the string must be enclosed by delimiters, or the semicolon will mark the start of the comment field.
Strings enclosed by delimiters cannot be continued on a new line.
To pass a number containing a radix or unary operator (for example, ^XF19), the entire argument must be enclosed by delimiters, or the assembler will interpret the radix operator as a delimiter.
The following are macro arguments that are enclosed in delimiters because they contain radix operators:
<^XF19> <^B01100011> <^F1.5> |
Macros can be nested; that is, a macro definition can contain a call to another macro. If, within a macro definition, another macro is called and is passed a string argument, you must delimit the argument so that the entire string is passed to the second macro as one argument.
The following macro definition contains a call to the REPEAT macro defined in an earlier example:
.MACRO CNTRPT LAB1,LAB2,STR_ARG LAB1: .BYTE LAB2-LAB1-1 ; Length of 2*string REPEAT <STR_ARG> ; Call REPEAT macro LAB2: .ENDM CNTRPT |
Note that the argument in the call to REPEAT is enclosed in angle brackets even though it does not contain any separator characters. The argument is thus delimited because it is a formal argument in the definition of the macro CNTRPT and will be replaced with an actual argument that may contain separator characters.
The following example calls the macro CNTRPT, which in turn calls the macro REPEAT:
CNTRPT ST,FIN,<LEARN YOUR ABC'S> ST: .BYTE FIN-ST-1 ; Length of 2*string REPEAT <LEARN YOUR ABC'S> ; Call REPEAT macro .ASCII /LEARN YOUR ABC'S/ .ASCII /LEARN YOUR ABC'S/ FIN: |
An alternative method to pass string arguments in nested macros is to enclose the macro argument in nested delimiters. Do not use delimiters around the macro calls in the macro definitions. Each time you use the delimited argument in a macro call, the assembler removes the outermost pair of delimiters before associating it with the formal argument. This method is not recommended because it requires that you know how deeply a macro is nested.
The following macro definition also contains a call to the REPEAT macro:
.MACRO CNTRPT2 LAB1,LAB2,STR_ARG LAB1: .BYTE LAB2-LAB1-1 ; Length of 2*string REPEAT STR_ARG ; Call REPEAT macro LAB2: .ENDM CNTRPT2 |
Note that the argument in the call to REPEAT is not enclosed in angle brackets.
The following example calls the macro CNTRPT2:
CNTRPT2 BEG,TERM,<<MIND YOUR P'S AND Q'S>> BEG: .BYTE TERM-BEG-1 ; Length of 2*string REPEAT <MIND YOUR P'S AND Q'S> ; Call REPEAT macro .ASCII /MIND YOUR P'S AND Q'S/ .ASCII /MIND YOUR P'S AND Q'S/ TERM: |
Note that even though the call to REPEAT in the macro definition is not
enclosed in delimiters, the call in the expansion is enclosed because
the call to CNTRPT2 contains nested delimiters around the string
argument.
4.5 Argument Concatenation
The argument concatenation operator, the apostrophe ('), concatenates a macro argument with some constant text. Apostrophes can either precede or follow a formal argument name in the macro source.
If an apostrophe precedes the argument name, the text before the apostrophe is concatenated with the actual argument when the macro is expanded. For example, if ARG1 is a formal argument associated with the actual argument TEST, ABCDE'ARG1 is expanded to ABCDETEST.
If an apostrophe follows the formal argument name, the actual argument is concatenated with the text that follows the apostrophe when the macro is expanded. For example, if ARG2 is a formal argument associated with the actual argument MOV, ARG2'L is expanded to MOVL.
Note that the apostrophe itself does not appear in the macro expansion.
To concatenate two arguments, separate the two formal arguments with two successive apostrophes. Two apostrophes are needed because each concatenation operation discards an apostrophe from the expansion.
An example of a macro definition that uses concatenation follows:
.MACRO CONCAT INST,SIZE,NUM TEST'NUM': INST''SIZE R0,R'NUM TEST'NUM'X: .ENDM CONCAT |
Note that two successive apostrophes are used when concatenating the two formal arguments INST and SIZE.
An example of a macro call and expansion follows:
CONCAT MOV,L,5 TEST5: MOVL R0,R5 TEST5X: |
When a symbol is specified as an actual argument, the name of the symbol, not the numeric value of the symbol, is passed to the macro. The value of the symbol can be passed by inserting a backslash (\) before the symbol in the macro call. The assembler passes the characters representing the decimal value of the symbol to the macro. For example, if the symbol COUNT has a value of 2 and the actual argument specified is \COUNT, the assembler passes the string "2" to the macro; it does not pass the name of the symbol, "COUNT".
Passing numeric values of symbols is especially useful with the apostrophe (') concatenation operator for creating new symbols.
An example of a macro definition for passing numeric values of symbols follows:
.MACRO TESTDEF,TESTNO,ENTRYMASK=^?^M<>? .ENTRY TEST'TESTNO,ENTRYMASK ; Uses arg concatenation .ENDM TESTDEF |
The following example shows a possible call and expansion of the macro defined previously:
COUNT = 2 TESTDEF \COUNT .ENTRY TEST2,^M<> ; Uses arg concatenation COUNT = COUNT + 1 TESTDEF \COUNT,^?^M<R3,R4>? .ENTRY TEST3,^M<R3,R4> ; Uses arg concatenation |
Local labels are often very useful in macros. Although you can create a macro definition that specifies local labels within it, these local labels might be duplicated elsewhere in the local label block possibly causing errors. However, the assembler can create local labels in the macro expansion that will not conflict with other local labels. These labels are called created local labels.
Created local labels range from 30000$ to 65535$. Each time the assembler creates a new local label, it increments the numeric part of the label name by 1. Consequently, no user-defined local labels should be in the range of 30000$ to 65535$.
A created local label is specified by a question mark (?) in front of the formal argument name. When the macro is expanded, the assembler creates a new local label if the corresponding actual argument is blank. If the corresponding actual argument is specified, the assembler substitutes the actual argument for the formal argument. Created local symbols can be used only in the first 31 formal arguments specified in the .MACRO directive.
Created local labels can be associated only with positional actual arguments; created local labels cannot be associated with keyword actual arguments.
The following example is a macro definition specifying a created local label:
.MACRO POSITIVE ARG1,?L1 TSTL ARG1 BGEQ L1 MNEGL ARG1,ARG1 L1: .ENDM POSITIVE |
The following three calls and expansions of the macro defined previously show both created local labels and a user-defined local label:
POSITIVE R0 TSTL R0 BGEQ 30000$ MNEGL R0,R0 30000$: POSITIVE COUNT TSTL COUNT BGEQ 30001$ MNEGL COUNT,COUNT 30001$: POSITIVE VALUE,10$ TSTL VALUE BGEQ 10$ MNEGL VALUE,VALUE 10$: |
Following are the three macro string operators:
These operators perform string manipulations on macro arguments and
ASCII strings. They can be used only in macros and repeat blocks. The
following sections describe these operators and give their formats and
examples of their use.
4.8.1 %LENGTH Operator
%LENGTH(string) |
Description The %LENGTH operator returns the length of a string. For example, the value of %LENGTH(<ABCDE>) is 5. Examplesstring
A macro argument or a delimited string. The string can be delimited by angle brackets or a character preceded by a circumflex (see Section 4.4).
The macro definition is as follows:
#1 |
---|
.MACRO CHK_SIZE ARG1 ; Macro checks if ARG1 .IF GREATER_EQUAL %LENGTH(ARG1)-3 ; is between 3 and .IF LESS_THAN 6-%LENGTH(ARG1) ; 6 characters long .ERROR ; Argument ARG1 is greater than 6 characters .ENDC ; If more than 6 .IF_FALSE ; If less than 3 .ERROR ; Argument ARG1 is less than 3 characters .ENDC ; Otherwise do nothing .ENDM CHK_SIZE |
The macro calls and expansions of the macro defined previously are as follows:
#2 |
---|
CHK_SIZE A ; Macro checks if A .IF GREATER_EQUAL 1-3 ; is between 3 and .IF LESS_THAN 6-1 ; 6 characters long. ; Should be too short. .ERROR ; Argument A is greater than 6 characters .ENDC ; If more than 6 .IF_FALSE ; If less than 3 %MACRO-E-GENERR, Generated ERROR: Argument A is less than 3 characters .ENDC ; Otherwise do nothing |
#3 |
---|
CHK_SIZE ABC ; Macro checks if ABC .IF GREATER_EQUAL 3-3 ; is between 3 and .IF LESS_THAN 6-3 ; 6 characters long. ; Should be ok. .ERROR ; Argument ABC is greater than 6 characters .ENDC ; If more than 6 .IF_FALSE ; If less than 3 .ERROR ; Argument ABC is less than 3 characters .ENDC ; Otherwise do nothing |
%LOCATE(string1,string2 [,symbol]) |
Description The %LOCATE operator locates a substring within a string. If %LOCATE finds a match of the substring, it returns the character position of the first character of the match in the string. For example, the value of %LOCATE(<D>,<ABCDEF>) is 3. Note that the first character position of a string is zero. If %LOCATE does not find a match, it returns a value equal to the length of the string. For example, the value of %LOCATE(<Z>,<ABCDEF>) is 6.string1
A substring. The substring can be written either as a macro argument or as a delimited string. The delimiters can be either angle brackets or a character preceded by a circumflex.string2
The string to be searched for the substring. The string can be written either as a macro argument or as a delimited string. The delimiters can be either angle brackets or a character preceded by a circumflex.symbol
An optional symbol or decimal number that specifies the position in string2 at which the assembler should start the search. If this argument is omitted, the assembler starts the search at position zero (the beginning of the string). The symbol must be an absolute symbol that has been previously defined; the number must be an unsigned decimal number. Expressions and radix operators are not allowed.
The %LOCATE operator returns a numeric value that can be used in any expression.
Examples
The macro definition is as follows:
#1 |
---|
.MACRO BIT_NAME ARG1 ; Checks if ARG1 is in list .IF EQUAL %LOCATE(ARG1,<DELDFWDLTDMOESC>)-15 ; If it is not, print error .ERROR ; ARG1 is an invalid bit name .ENDC ; If it is, do nothing .ENDM BIT_NAME |
The macro calls and expansions of the macro defined previously are as follows:
#2 |
---|
BIT_NAME ESC ; Is ESC in list .IF EQUAL 12-15 ; If it is not, print error .ERROR ; ESC is an invalid bit name .ENDC ; If it is, do nothing BIT_NAME FOO ; Not in list .IF EQUAL 15-15 ; If it is not, print error %MACRO-E-GENERR, Generated ERROR: FOO is an invalid bit name .ENDC ; If it is, do nothing |
If the optional symbol is specified, the search begins at the character position of string2 specified by the symbol. For example, the value of %LOCATE(<ACE>,<SPACE_HOLDER>,5) is 12 because there is no match after the fifth character position. |
Previous | Next | Contents | Index |
privacy and legal statement | ||
4515PRO_003.HTML |