From 5a3cab3cef8c98bc8de55b29e0d28b20d0baf293 Mon Sep 17 00:00:00 2001 From: Christophe CURIS Date: Wed, 14 Nov 2012 22:05:35 +0100 Subject: [PATCH] Changed handling of quoted strings in the menu parser for consistency MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit As reported by Amadeusz Sławiński, the support for (d)quoted string in the menu file was not exactly the same as in previous versions of WindowMaker, so we had a regression which is not acceptable. This patch propose a consistent handling for (d)quoted text instead of the previous on-the-title-only code; now all (d)quoted strings are still kept as-is (as expected) but the (d)quotes are always removed. As a side note, it also improve the support for \escaped character to work correctly as mentioned in the example of the default menu. Note: This reverts b2e7620868aa18cebb8f6d1e653f8c46dc959a34 which was an incomplete solution to the problem. --- WINGs/menuparser.c | 112 +++++++++++++++++++++++----------------------- WINGs/menuparser.h | 3 +- WINGs/menuparser_macros.c | 14 +++--- 3 files changed, 67 insertions(+), 62 deletions(-) diff --git a/WINGs/menuparser.c b/WINGs/menuparser.c index c18f9b98..e812ba37 100644 --- a/WINGs/menuparser.c +++ b/WINGs/menuparser.c @@ -228,24 +228,6 @@ read_next_line: } } - if (title != NULL) { - char eot, *src, *dst; - - src = *title; - eot = *src++; - if ((eot == '"') || (eot == '\'')) { - dst = *title; - - while (*src != '\0') - *dst++ = *src++; - - if ((dst > *title) && (dst[-1] == eot)) - dst--; - - *dst = '\0'; - } - } - if (params != NULL) { lineparam[sizeof(lineparam) - 1] = '\0'; *parameter = wstrdup(lineparam); @@ -319,10 +301,12 @@ found_end_of_comment: * the result is wmalloc's, so it needs to be free'd */ static char *menu_parser_isolate_token(WMenuParser parser, WParserMacro *list_macros) { - char *start, *token; + char buffer_token[sizeof(parser->line_buffer)]; + char *token; int limit = MAX_NESTED_MACROS; - start = parser->rd; + token = buffer_token; + restart_token_split: while (*parser->rd != '\0') @@ -333,48 +317,64 @@ restart_token_split: ((parser->rd[1] == '*') || (parser->rd[1] == '/'))) { break; - } else if ((parser->rd[0] == '\\') && (parser->rd[1] == '\n')) { - break; + } else if (parser->rd[0] == '\\') { + if ((parser->rd[1] == '\n') || (parser->rd[1] == '\0')) + break; - } else if ((*parser->rd == '"' ) || (*parser->rd == '\'')) { - char eot = *parser->rd++; + parser->rd++; + *token++ = *parser->rd++; + + } else if (*parser->rd == '"' ) { + char ch; - while ((*parser->rd != '\0') && (*parser->rd != '\n')) - if (*parser->rd++ == eot) - goto found_end_quote; + /* Double-quoted string deserve special processing because macros are not expanded + inside. We also remove the double quotes. */ + parser->rd++; + while ((*parser->rd != '\0') && (*parser->rd != '\n')) { + ch = *parser->rd++; + if (ch == '\\') { + if ((*parser->rd == '\0') || (*parser->rd == '\n')) + break; + *token++ = *parser->rd++; + } else if (ch == '"') + goto found_end_dquote; + else + *token++ = ch; + } - WMenuParserError(parser, _("missing closing quote or double-quote before end-of-line") ); + WMenuParserError(parser, _("missing closing double-quote before end-of-line") ); -found_end_quote: +found_end_dquote: ; - } else if (isnamechr(*parser->rd)) { - WParserMacro *macro; - char *start_macro; - start_macro = parser->rd; - while (isnamechr(*parser->rd)) - parser->rd++; + } else if (*parser->rd == '\'') { + char ch; + + /* Simple-quoted string deserve special processing because we keep their content + as-is, including the quotes and the \-escaped text */ + *token++ = *parser->rd++; + while ((*parser->rd != '\0') && (*parser->rd != '\n')) { + ch = *parser->rd++; + *token++ = ch; + if (ch == '\'') + goto found_end_squote; + } - macro = menu_parser_find_macro(parser, start_macro); - if (macro != NULL) { - char *expand_there; + WMenuParserError(parser, _("missing closing simple-quote before end-of-line") ); - /* Copy the chars before the macro to the beginning of the buffer to - * leave as much room as possible for expansion */ - expand_there = parser->line_buffer; - if (start != parser->line_buffer) - while (start < start_macro) - *expand_there++ = *start++; +found_end_squote: + ; - start = parser->line_buffer; + } else if (isnamechr(*parser->rd)) { + WParserMacro *macro; - /* Macro expansion will take care to keep the rest of the line after - * the macro to the end of the line for future token extraction */ - menu_parser_expand_macro(parser, macro, expand_there, - sizeof(parser->line_buffer) - (start - parser->line_buffer) ); + macro = menu_parser_find_macro(parser, parser->rd); + if (macro != NULL) { + /* The expansion is done inside the parser's buffer + this is needed to allow sub macro calls */ + menu_parser_expand_macro(parser, macro); /* Restart parsing to allow expansion of sub macro calls */ - parser->rd = expand_there; if (limit-- > 0) goto restart_token_split; @@ -384,15 +384,17 @@ found_end_quote: parser->rd++; break; + } else { + while (isnamechr(*parser->rd)) + *token++ = *parser->rd++; } - /* else: the text was passed over so it will be counted in the token from 'start' */ } else { - parser->rd++; + *token++ = *parser->rd++; } - token = wmalloc(parser->rd - start + 1); - strncpy(token, start, parser->rd - start); - token[parser->rd - start] = '\0'; + *token++ = '\0'; + token = wmalloc(token - buffer_token); + strcpy(token, buffer_token); return token; } diff --git a/WINGs/menuparser.h b/WINGs/menuparser.h index 692ef69b..dbf78f99 100644 --- a/WINGs/menuparser.h +++ b/WINGs/menuparser.h @@ -79,8 +79,7 @@ void menu_parser_free_macros(WMenuParser parser); WParserMacro *menu_parser_find_macro(WMenuParser parser, const char *name); -void menu_parser_expand_macro(WMenuParser parser, WParserMacro *macro, - char *write_buf, int write_buf_size); +void menu_parser_expand_macro(WMenuParser parser, WParserMacro *macro); int isnamechr(char ch); // Check if char is valid character for a macro name diff --git a/WINGs/menuparser_macros.c b/WINGs/menuparser_macros.c index bada6203..511334fc 100644 --- a/WINGs/menuparser_macros.c +++ b/WINGs/menuparser_macros.c @@ -381,8 +381,7 @@ static Bool menu_parser_read_macro_def(WMenuParser parser, WParserMacro *macro, /* When a macro is being used in the file, this function will generate the expanded value for the macro in the parser's work line. It blindly supposes that the data generated in macro->value is valid */ -void menu_parser_expand_macro(WMenuParser parser, WParserMacro *macro, - char *write_buf, int write_buf_size) +void menu_parser_expand_macro(WMenuParser parser, WParserMacro *macro) { char save_buf[sizeof(parser->line_buffer)]; char arg_values_buf[MAXLINE]; @@ -390,7 +389,11 @@ void menu_parser_expand_macro(WMenuParser parser, WParserMacro *macro, char *src, *dst; unsigned char *rd; unsigned int size; - int space_left; + int i, space_left; + + /* Skip the name of the macro, this was not done by caller */ + for (i = 0; macro->name[i] != '\0'; i++) + parser->rd++; if (macro->arg_count >= 0) { menu_parser_skip_spaces_and_comments(parser); @@ -409,8 +412,9 @@ void menu_parser_expand_macro(WMenuParser parser, WParserMacro *macro, while ((*dst++ = *parser->rd++) != '\0') ; /* Generate expanded macro */ - dst = write_buf; - space_left = write_buf_size - 1; + dst = parser->line_buffer; + parser->rd = dst; + space_left = sizeof(parser->line_buffer) - 1; if (macro->function != NULL) { /* Parser's pre-defined macros actually proposes a function call to generate dynamic value for the expansion of the macro. In this case -- 2.11.4.GIT