14.2.6 Macro Functions

Macro bodies may manipulate syntax using macro functions. Macro functions accept tokens as arguments and expand to sequences of characters.

The arguments to macro functions have a restricted form. They may only be a single token (such as an identifier or a string), a macro argument, or a call to a macro function. Thus, the following are valid macro arguments:

x    5.0    x    !1    "5 + 6"    !CONCAT(x,y)

and the following are not:

x y    5+6

Macro functions expand to sequences of characters. When these character strings are processed further as character strings, e.g. with !LENGTH, any character string is valid. When they are interpreted as PSPP syntax, e.g. when the expansion becomes part of a command, they need to be valid for that purpose. For example, !UNQUOTE("It's") will yield an error if the expansion It's becomes part of a PSPP command, because it contains unbalanced single quotes, but !LENGTH(!UNQUOTE("It's")) expands to 4.

The following macro functions are available. Each function’s documentation includes examples in the form callexpansion.

Macro Function: !BLANKS (count)

Expands to count unquoted spaces, where count is a nonnegative integer. Outside quotes, any positive number of spaces are equivalent; for a quoted string of spaces, use !QUOTE(!BLANKS(count)).

In the examples below, ‘_’ stands in for a space to make the results visible.

!BLANKS(0)                  → empty
!BLANKS(1)                  → _
!BLANKS(2)                  → __
!QUOTE(!BLANKS(5))          → '_____'
Macro Function: !CONCAT (arg…)

Expands to the concatenation of all of the arguments. Before concatenation, each quoted string argument is unquoted, as if !UNQUOTE were applied. This allows for “token pasting”, combining two (or more) tokens into a single one:

!CONCAT(x, y)                → xy
!CONCAT('x', 'y')            → xy
!CONCAT(12, 34)              → 1234
!CONCAT(!NULL, 123)          → 123

!CONCAT is often used for constructing a series of similar variable names from a prefix followed by a number and perhaps a suffix. For example:

!CONCAT(x, 0)                → x0
!CONCAT(x, 0, y)             → x0y

An identifier token must begin with a letter (or ‘#’ or ‘@’), which means that attempting to use a number as the first part of an identifier will produce a pair of distinct tokens rather than a single one. For example:

!CONCAT(0, x)                → 0 x
!CONCAT(0, x, y)             → 0 xy
Macro Function: !EVAL (arg)

Expands macro calls in arg. This is especially useful if arg is the name of a macro or a macro argument that expands to one, because arguments to macro functions are not expanded by default (see Controlling Macro Expansion).

The following examples assume that !vars is a macro that expands to a b c:

!vars                        → a b c
!QUOTE(!vars)                → '!vars'
!EVAL(!vars)                 → a b c
!QUOTE(!EVAL(!vars))         → 'a b c'

These examples additionally assume that argument !1 has value !vars:

!1                           → a b c
!QUOTE(!1)                   → '!vars'
!EVAL(!1)                    → a b c
!QUOTE(!EVAL(!1))            → 'a b c'
Macro Function: !HEAD (arg)
Macro Function: !TAIL (arg)

!HEAD expands to just the first token in an unquoted version of arg, and !TAIL to all the tokens after the first.

!HEAD('a b c')               → a
!HEAD('a')                   → a
!HEAD(!NULL)                 → empty
!HEAD('')                    → empty

!TAIL('a b c')               → b c
!TAIL('a')                   → empty
!TAIL(!NULL)                 → empty
!TAIL('')                    → empty
Macro Function: !INDEX (haystack, needle)

Looks for needle in haystack. If it is present, expands to the 1-based index of its first occurrence; if not, expands to 0.

!INDEX(banana, an)           → 2
!INDEX(banana, nan)          → 3
!INDEX(banana, apple)        → 0
!INDEX("banana", nan)        → 4
!INDEX("banana", "nan")      → 0
!INDEX(!UNQUOTE("banana"), !UNQUOTE("nan")) → 3
Macro Function: !LENGTH (arg)

Expands to a number token representing the number of characters in arg.

!LENGTH(123)                 → 3
!LENGTH(123.00)              → 6
!LENGTH( 123 )               → 3
!LENGTH("123")               → 5
!LENGTH(xyzzy)               → 5
!LENGTH("xyzzy")             → 7
!LENGTH("xy""zzy")           → 9
!LENGTH(!UNQUOTE("xyzzy"))   → 5
!LENGTH(!UNQUOTE("xy""zzy")) → 6
!LENGTH(!1)                  → 5 if !1 is a b c
!LENGTH(!1)                  → 0 if !1 is empty
!LENGTH(!NULL)               → 0
Macro Function: !NULL

Expands to an empty character sequence.

!NULL                        → empty
!QUOTE(!NULL)                → ''
Macro Function: !QUOTE (arg)
Macro Function: !UNQUOTE (arg)

The !QUOTE function expands to its argument surrounded by apostrophes, doubling any apostrophes inside the argument to make sure that it is valid PSPP syntax for a string. If the argument was already a quoted string, !QUOTE expands to it unchanged.

Given a quoted string argument, the !UNQUOTED function expands to the string’s contents, with the quotes removed and any doubled quote marks reduced to singletons. If the argument was not a quoted string, !UNQUOTE expands to the argument unchanged.

!QUOTE(123.0)                → '123.0'
!QUOTE( 123 )                → '123'
!QUOTE('a b c')              → 'a b c'
!QUOTE("a b c")              → "a b c"
!QUOTE(!1)                   → 'a ''b'' c' if !1 is a 'b' c

!UNQUOTE(123.0)              → 123.0
!UNQUOTE( 123 )              → 123
!UNQUOTE('a b c')            → a b c
!UNQUOTE("a b c")            → a b c
!UNQUOTE(!1)                 → a 'b' c if !1 is a 'b' c

!QUOTE(!UNQUOTE(123.0))      → '123.0'
!QUOTE(!UNQUOTE( 123 ))      → '123'
!QUOTE(!UNQUOTE('a b c'))    → 'a b c'
!QUOTE(!UNQUOTE("a b c"))    → 'a b c'
!QUOTE(!UNQUOTE(!1))         → 'a ''b'' c' if !1 is a 'b' c
Macro Function: !SUBSTR (arg, start[, count])

Expands to a substring of arg starting from 1-based position start. If count is given, it limits the number of characters in the expansion; if it is omitted, then the expansion extends to the end of arg.

!SUBSTR(banana, 3)           → nana
!SUBSTR(banana, 3, 3)        → nan
!SUBSTR("banana", 1, 3)         → error ("ba is not a valid token)
!SUBSTR(!UNQUOTE("banana"), 3) → nana
!SUBSTR("banana", 3, 3)      → ana

!SUBSTR(banana, 3, 0)        → empty
!SUBSTR(banana, 3, 10)       → nana
!SUBSTR(banana, 10, 3)       → empty
Macro Function: !UPCASE (arg)

Expands to an unquoted version of arg with all letters converted to uppercase.

!UPCASE(freckle)             → FRECKLE
!UPCASE('freckle')           → FRECKLE
!UPCASE('a b c')             → A B C
!UPCASE('A B C')             → A B C