summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Watts <Robin.Watts@artifex.com>2022-09-09 15:59:22 +0100
committerChris Liddell <chris.liddell@artifex.com>2022-09-19 16:47:45 +0100
commitc9897b8c857e5252524f97e5668428b8563e6a1b (patch)
tree33fb215bbcfa7963cfe907fd6094635bfdbdb59a
parente208b3c5a6634fbfe1dc74a171ba47970947eb44 (diff)
downloadghostpdl-c9897b8c857e5252524f97e5668428b8563e6a1b.tar.gz
Tweak @file quote handling.
The change for bug 703694 in commit 0f38f27a7b3a1eb meant that we no longer accepted -sFoo="Bar Baz" in an @file, and instead read that as: -sFoo="Bar This seems counterintuitive. Here we tweak the code so that " is accepted to mean the start of a quotation after an = sign too. We also tweak the handling of '\' so that special case handling only happens in @ files, not from the command line. And we allow '\"' to mean literal '"'. '\' at the end of the line remains meaning "continue parsing past the newline". All other cases of '\' continue to mean literal '\'.
-rw-r--r--base/gsargs.c43
1 files changed, 31 insertions, 12 deletions
diff --git a/base/gsargs.c b/base/gsargs.c
index a2023d5e3..a17998f95 100644
--- a/base/gsargs.c
+++ b/base/gsargs.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -214,6 +214,7 @@ arg_next(arg_list * pal, const char **argstr, const gs_memory_t *errmem)
int c;
int i;
bool in_quote, eol;
+ int prev_c_was_equals = 0;
*argstr = NULL;
@@ -304,9 +305,10 @@ arg_next(arg_list * pal, const char **argstr, const gs_memory_t *errmem)
c = get_codepoint(pal, pas);
if (c == '\n')
c = get_codepoint(pal, pas);
+ prev_c_was_equals = 0;
continue; /* Next char */
}
- if (c == '\\') {
+ if (c == '\\' && pal->depth > 0) {
/* Check for \ followed by newline. */
c = get_codepoint(pal, pas);
if (is_eol(c)) {
@@ -315,18 +317,33 @@ arg_next(arg_list * pal, const char **argstr, const gs_memory_t *errmem)
if (c == '\n')
c = get_codepoint(pal, pas);
eol = true;
+ prev_c_was_equals = 0;
continue; /* Next char */
}
- /* \ anywhere else is treated as a printing character. */
- /* This is different from the Unix shells. */
- if (i >= arg_str_max - 1) {
- cstr[i] = 0;
- errprintf(errmem, "Command too long: %s\n", cstr);
- return_error(gs_error_Fatal);
+ {
+ char what;
+
+ if (c == '"') {
+ /* currently \" is treated as literal ". No other literals yet.
+ * We may expand this in future. */
+ what = c;
+ c = get_codepoint(pal, pas);
+ } else {
+ /* \ anywhere else is treated as a printing character. */
+ /* This is different from the Unix shells. */
+ what = '\\';
+ }
+
+ if (i >= arg_str_max - 1) {
+ cstr[i] = 0;
+ errprintf(errmem, "Command too long: %s\n", cstr);
+ return_error(gs_error_Fatal);
+ }
+ cstr[i++] = what;
+ eol = false;
+ prev_c_was_equals = 0;
+ continue; /* Next char */
}
- cstr[i++] = '\\';
- eol = false;
- continue; /* Next char */
}
/* c will become part of the argument */
if (i >= arg_str_max - 1) {
@@ -341,7 +358,7 @@ arg_next(arg_list * pal, const char **argstr, const gs_memory_t *errmem)
* have to have carefully quoted double-quotes to make them survive the
* shell anyway! */
if (c == '"' && pal->depth > 0) {
- if (i == 0 && !in_quote)
+ if ((i == 0 || prev_c_was_equals) && !in_quote)
in_quote = true;
else if (in_quote) {
/* Need to check the next char to see if we're closing at the end */
@@ -355,6 +372,7 @@ arg_next(arg_list * pal, const char **argstr, const gs_memory_t *errmem)
/* Not a close quote, just a literal quote. */
i += codepoint_to_utf8(&cstr[i], '"');
eol = false;
+ prev_c_was_equals = 0;
continue; /* Jump to the start of the loop without reading another char. */
} else
i += codepoint_to_utf8(&cstr[i], c);
@@ -362,6 +380,7 @@ arg_next(arg_list * pal, const char **argstr, const gs_memory_t *errmem)
else
i += codepoint_to_utf8(&cstr[i], c);
eol = is_eol(c);
+ prev_c_was_equals = (c == '=');
c = get_codepoint(pal, pas);
}
cstr[i] = 0;