From d84f361c8b9c567f08eeaf2497a88bdab312ed36 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Thu, 10 Jun 2021 22:34:12 -0700 Subject: [PATCH] !UPCASE --- src/language/lexer/macro.c | 31 +++++++++++++++++++++++-------- tests/language/control/define.at | 14 ++++++++++++++ 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/src/language/lexer/macro.c b/src/language/lexer/macro.c index b17d467faa..95d86a6e96 100644 --- a/src/language/lexer/macro.c +++ b/src/language/lexer/macro.c @@ -854,6 +854,13 @@ unquote_string (const char *s, struct string *content) return true; } +static const char * +unquote_string_in_place (const char *s, struct string *tmp) +{ + ds_init_empty (tmp); + return unquote_string (s, tmp) ? ds_cstr (tmp) : s; +} + static bool parse_integer (const char *s, int *np) { @@ -899,16 +906,15 @@ expand_macro_function (struct parse_macro_function_ctx *ctx, else if (parse_macro_function (ctx, &args, ss_cstr ("!head"), 1, 1, input_consumed)) { - struct string content = DS_EMPTY_INITIALIZER; - const char *s = (unquote_string (args.strings[0], &content) - ? ds_cstr (&content) : args.strings[0]); + struct string tmp; + const char *s = unquote_string_in_place (args.strings[0], &tmp); struct macro_tokens mts = { .n = 0 }; macro_tokens_from_string (&mts, ss_cstr (s), SEG_MODE_INTERACTIVE /* XXX */); if (mts.n > 0) ds_put_substring (output, mts.mts[0].representation); macro_tokens_uninit (&mts); - ds_destroy (&content); + ds_destroy (&tmp); } else if (parse_macro_function (ctx, &args, ss_cstr ("!index"), 2, 2, input_consumed)) @@ -960,9 +966,8 @@ expand_macro_function (struct parse_macro_function_ctx *ctx, else if (parse_macro_function (ctx, &args, ss_cstr ("!tail"), 1, 1, input_consumed)) { - struct string content = DS_EMPTY_INITIALIZER; - const char *s = (unquote_string (args.strings[0], &content) - ? ds_cstr (&content) : args.strings[0]); + struct string tmp; + const char *s = unquote_string_in_place (args.strings[0], &tmp); struct macro_tokens mts = { .n = 0 }; macro_tokens_from_string (&mts, ss_cstr (s), SEG_MODE_INTERACTIVE /* XXX */); @@ -972,7 +977,7 @@ expand_macro_function (struct parse_macro_function_ctx *ctx, macro_tokens_to_representation (&tail, output); } macro_tokens_uninit (&mts); - ds_destroy (&content); + ds_destroy (&tmp); } else if (parse_macro_function (ctx, &args, ss_cstr ("!unquote"), 1, 1, input_consumed)) @@ -980,6 +985,16 @@ expand_macro_function (struct parse_macro_function_ctx *ctx, if (!unquote_string (args.strings[0], output)) ds_put_cstr (output, args.strings[0]); } + else if (parse_macro_function (ctx, &args, ss_cstr ("!upcase"), 1, 1, + input_consumed)) + { + struct string tmp; + const char *s = unquote_string_in_place (args.strings[0], &tmp); + char *upper = utf8_to_upper (s); + ds_put_cstr (output, upper); + free (upper); + ds_destroy (&tmp); + } 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"))) diff --git a/tests/language/control/define.at b/tests/language/control/define.at index 9a13ea45cd..fce0e3f832 100644 --- a/tests/language/control/define.at +++ b/tests/language/control/define.at @@ -491,3 +491,17 @@ ana. nana. .]) +dnl Keep this test in sync with the examples for !UPCASE in the manual. +PSPP_CHECK_MACRO_EXPANSION([!UPCASE], + [DEFINE !u() +!UPCASE(freckle). +!UPCASE('freckle'). +!UPCASE('a b c'). +!UPCASE('A B C'). +!ENDDEFINE.], + [!u.], + [FRECKLE. +FRECKLE. +A B C. +A B C.]) + -- 2.30.2