From 340f224bd085965d5ff724afdafa04759f8a040f Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Wed, 1 Sep 2021 10:02:26 -0700 Subject: [PATCH] macro: Fix crash for !QUOTE of a quoted string. This revealed that the tests didn't include anything for !QUOTE and !UNQUOTE, even though the manual had lots of examples. I added a test for these and for !NULL, which had also been forgotten. Thanks to Frans Houweling for reporting the bug. --- doc/flow-control.texi | 4 ++ src/language/lexer/macro.c | 3 +- tests/language/control/define.at | 66 ++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 1 deletion(-) diff --git a/doc/flow-control.texi b/doc/flow-control.texi index d3235612b9..23539bcfb6 100644 --- a/doc/flow-control.texi +++ b/doc/flow-control.texi @@ -578,6 +578,8 @@ Expands to a number token representing the number of characters in @deffn {Macro Function} !NULL Expands to an empty character sequence. +@c Keep these examples in sync with the test for !NULL in +@c tests/language/control/define.at: @example !NULL @expansion{} @r{empty} !QUOTE(!NULL) @expansion{} '' @@ -596,6 +598,8 @@ 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, @code{!UNQUOTE} expands to the argument unchanged. +@c Keep these examples in sync with the test for !QUOTE and !UNQUOTE in +@c tests/language/control/define.at: @example !QUOTE(123.0) @expansion{} '123.0' !QUOTE( 123 ) @expansion{} '123' diff --git a/src/language/lexer/macro.c b/src/language/lexer/macro.c index 742b8771ac..814740bfac 100644 --- a/src/language/lexer/macro.c +++ b/src/language/lexer/macro.c @@ -1038,7 +1038,8 @@ unquote_string (const char *s, enum segmenter_mode segmenter_mode, return false; } - ds_put_substring (content, token1.string); + if (content) + ds_put_substring (content, token1.string); token_uninit (&token1); return true; } diff --git a/tests/language/control/define.at b/tests/language/control/define.at index 9a7594b81b..204ed2efd3 100644 --- a/tests/language/control/define.at +++ b/tests/language/control/define.at @@ -880,6 +880,72 @@ AT_CHECK([pspp --testing-mode define.sps], [0], [dnl ]) AT_CLEANUP +dnl Keep this test in sync with the examples for !NULL in the manual. +AT_SETUP([macro expansion - !NULL]) +AT_KEYWORDS([NULL]) +AT_DATA([define.sps], [dnl +DEFINE !n() +!NULL. +!QUOTE(!NULL). +!ENDDEFINE. +DEBUG EXPAND. +!n. +]) +AT_CAPTURE_FILE([define.sps]) +AT_CHECK([pspp --testing-mode define.sps], [0], [dnl +. +''. +]) +AT_CLEANUP + +dnl Keep this test in sync with the examples for !QUOTE and !UNQUOTE in the manual. +AT_SETUP([macro expansion - !QUOTE and !UNQUOTE]) +AT_KEYWORDS([QUOTE UNQUOTE]) +AT_DATA([define.sps], [dnl +DEFINE !q(!POS !CMDEND) +!QUOTE(123.0). +!QUOTE( 123 ). +!QUOTE('a b c'). +!QUOTE("a b c"). +!QUOTE(!1). + +!UNQUOTE(123.0). +!UNQUOTE( 123 ). +!UNQUOTE('a b c'). +!UNQUOTE("a b c"). +!UNQUOTE(!1). + +!QUOTE(!UNQUOTE(123.0)). +!QUOTE(!UNQUOTE( 123 )). +!QUOTE(!UNQUOTE('a b c')). +!QUOTE(!UNQUOTE("a b c")). +!QUOTE(!UNQUOTE(!1)). +!ENDDEFINE. +DEBUG EXPAND. +!q a 'b' c. +]) +AT_CAPTURE_FILE([define.sps]) +AT_CHECK([pspp --testing-mode define.sps], [0], [dnl +'123.0'. +'123'. +'a b c'. +"a b c". +'a ''b'' c'. + +123.0. +123. +a b c. +a b c. +a 'b' c. + +'123.0'. +'123'. +'a b c'. +'a b c'. +'a ''b'' c'. +]) +AT_CLEANUP + dnl Keep this test in sync with the examples for !SUBSTR in the manual. AT_SETUP([macro expansion - !SUBSTR]) AT_KEYWORDS([SUBSTR]) -- 2.30.2