In the examples below, @samp{_} stands in for a space to make the
results visible.
+@c Keep these examples in sync with the test for !BLANKS in
+@c tests/language/control/define.at:
@example
!BLANKS(0) @expansion{} @r{empty}
!BLANKS(1) @expansion{} _
concatenation, each quoted string argument is unquoted, as if
@code{!UNQUOTE} were applied.
+@c Keep these examples in sync with the test for !CONCAT in
+@c tests/language/control/define.at:
@example
!CONCAT(x, y) @expansion{} xy
!CONCAT('x', 'y') @expansion{} xy
@node Macro Settings
@subsection Macro Settings
-MPRINT
-MEXPAND
-MNEST
+Some macro behavior is controlled through the SET command
+(@pxref{SET}). This section describes these settings.
+
+Any SET command that changes these settings within a macro body only
+takes effect following the macro. This is because PSPP expands a
+macro's entire body at once, so that the SET command inside the body
+only executes afterwards.
+
+The MEXPAND setting (@pxref{SET MEXPAND}) controls whether macros will
+be expanded at all. By default, macro expansion is on. To avoid
+expansion of macros called within a macro body, use @code{!OFFEXPAND}
+and @code{!ONEXPAND} (@pxref{Controlling Macro Expansion}).
+
+When MPRINT (@pxref{SET MPRINT}) is turned on, PSPP logs an expansion
+of each macro in the input. This feature can be useful for debugging
+macro definitions.
+
+MNEST (@pxref{SET MNEST}) limits the depth of expansion of macro
+calls, that is, the nesting level of macro expansion.
+
MITERATE
PRESERVE...RESTORE
Controls whether macros are expanded. The default is ON.
@item MPRINT
+@anchor{SET MPRINT}
Controls whether the expansion of macros is included in output. This
is separate from whether command syntax in general is included in
output. The default is OFF.
@item MITERATE
+@anchor{SET MITERATE}
Limits the number of iterations executed in @code{!DO} loops within
macros. This does not affect other language constructs such as
@cmd{LOOP}. This must be set to a positive integer. The default is
1000.
@item MNEST
-Limits the number of levels of nested macro expansion. This must be
+@anchor{SET MNEST}
+Limits the number of levels of nested macro expansions. This must be
set to a positive integer. The default is 50.
@end table
else if (parse_macro_function (ctx, &args, ss_cstr ("!concat"), 1, INT_MAX,
input_consumed))
{
- struct string s;
- bool all_strings = true;
+ struct string s = DS_EMPTY_INITIALIZER;
for (size_t i = 0; i < args.n; i++)
{
if (args.mts[i].token.type == T_STRING)
ds_put_substring (&s, args.mts[i].token.string);
else
- {
- all_strings = false;
- ds_put_substring (&s, args.mts[i].representation);
- }
+ ds_put_substring (&s, args.mts[i].representation);
}
- if (all_strings)
- {
- *output = (struct macro_token) {
- .token = { .type = T_STRING, .string = s.ss },
- };
- output->representation = ss_cstr (token_to_string (&output->token));
- }
- else
- {
- *output = (struct macro_token) {
- .token = { .type = T_MACRO_ID /*XXX*/, .string = s.ss },
- };
- ss_alloc_substring (&output->representation, s.ss);
- }
+ *output = (struct macro_token) {
+ .token = { .type = T_MACRO_ID /*XXX*/, .string = s.ss },
+ };
+ ss_alloc_substring (&output->representation, s.ss);
}
else if (parse_macro_function (ctx, &args, ss_cstr ("!quote"), 1, 1,
input_consumed))
else
macro_token_copy (output, &args.mts[0]);
}
+ else if (ctx->n_input > 0
+ && ctx->input[0].token.type == T_MACRO_ID
+ && ss_equals_case (ctx->input[0].token.string, ss_cstr ("!null")))
+ {
+ *input_consumed = 1;
+ *output = (struct macro_token) {
+ .token = { .type = T_MACRO_ID /* XXX*/ },
+ };
+ ss_alloc_substring (&output->token.string, ss_cstr (""));
+ return true;
+ }
else
return false;
m4_define([PSPP_CHECK_MACRO_EXPANSION],
[AT_SETUP([macro expansion - $1])
+ AT_KEYWORDS([m4_bpatsubst([$1], [!], [])])
AT_DATA([define.sps], [$2
DEBUG EXPAND.
$3
])
+ AT_CAPTURE_FILE([define.sps])
AT_DATA([expout], [$4
])
AT_CHECK([pspp --testing-mode define.sps | sed '/^$/d'], [$6], [expout])
[!k arg1=x.
!k],
[k(x)
-k(a b c)])
\ No newline at end of file
+k(a b c)])
+
+dnl Keep this test in sync with the examples for !BLANKS in the manual.
+PSPP_CHECK_MACRO_EXPANSION([!BLANKS],
+ [DEFINE !b()
+!BLANKS(0).
+!QUOTE(!BLANKS(0)).
+!BLANKS(1).
+!QUOTE(!BLANKS(1)).
+!BLANKS(2).
+!QUOTE(!BLANKS(2)).
+!BLANKS(5).
+!QUOTE(!BLANKS(5)).
+!ENDDEFINE],
+ [!b.],
+ [.
+''.
+ .
+' '.
+ .
+' '.
+ .
+' '.])
+
+dnl Keep this test in sync with the examples for !CONCAT in the manual.
+PSPP_CHECK_MACRO_EXPANSION([!CONCAT],
+ [DEFINE !c()
+!CONCAT(x, y).
+!CONCAT('x', 'y').
+!CONCAT(12, 34).
+!CONCAT(!NULL, 123).
+!ENDDEFINE],
+ [!c.],
+ [xy.
+xy.
+1234.
+123.])