[gs-devel] Re: [gs-cvs] rev 7133 - trunk/gs/src
SaGS
sags5495 at hotmail.com
Tue Oct 31 08:43:19 PST 2006
----- Original Message -----
From: Stefan Kemper
To: SaGS
Cc: gs-devel ; Miles Jones ; Henry Stiles
Sent: Tuesday, 31 October 2006 16:32
Subject: Re: [gs-devel] Re: [gs-cvs] rev 7133 - trunk/gs/src
> Dear SaGS,
>
> Please send me your patch, and the command line arguments that you
> used to test it.
> ...
Dear Stefan,
As I understand the bug is already fixed in your working copy, I'll
post the requested details and attach a diff here, not on Bugzilla.
(1) In GS_OPTIONS, quotes are treated as regular characters,
and not used for quoting spaces.
gs\BIN>set GS_OPTIONS=-sDEVICE=nullpage <-/
-sTEST="HAVE -c TEST == SPACES"
gs\BIN>gswin32c
AFPL Ghostscript SVN PRE-RELEASE 8.55 (2006-05-20)
Copyright (C) 2006 artofcode LLC, Benicia, CA. All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
("HAVE)
Error: /undefined in SPACES"
...
Expected behaviour:
- use nullpage as initial device;
Note: not related to this bug, but otherwise GS tries to install
an initial device and fails. Don't know why; in (2) below
it doesn't.
- set /TEST to <(HAVE -c TEST == SPACES)> (I'm using "<>" for
citing, to avoid confusion with quotes in cited text);
- display the GS prompt (allows to examine /TEST).
Actual behaviour:
- use nullpage as initial device;
- set /TEST to <"HAVE> (note: with a leading quote);
- find <-c> and execute <TEST>, <==>, then <SPACES"> (note: last one
has a trailing quote). The <-c> inside the string is only to show
what /TEST has been set to, and is not connected to (2) below.
(2) Quoting ineffective for 1st switch following <-c>.
gs\BIN>gswin32c -c 1 pop -sTEST="HAVE -c TEST == SPACES"
AFPL Ghostscript SVN PRE-RELEASE 8.55 (2006-05-20)
Copyright (C) 2006 artofcode LLC, Benicia, CA. All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
(HAVE)
Error: /undefined in SPACES
...
Expected behaviour:
- execute <1>, then <pop>;
- define /TEST as <(HAVE -c TEST == SPACES)>;
- display the GS prompt (allows to examine /TEST).
Actual behaviour:
- execute <1>, then <pop>;
- define /TEST as <(HAVE)>;
- find <-c> and execute <TEST>, <==>, then <SPACES>.
Differs from (1) above: text is parsed twice. 1st pass finds and removes
the quotes; during the 2nd parsing quotes aren't there anymore, and
spaces that were previously protected are treated as delimiters.
(3) Quoting ineffective for GhostPCL's (1.41) input filenames.
Note: Does not affect Ghostscript.
Any input file with spaces in the name or path (as typed on the
command line, not after converting to a full path), even properly
enclosed in <"">, fails as if the <""> were not there.
My [short] explanation of the cause:
In the situations above, some text gets "pushed back" into the
arguments list. But:
(a) Sometimes this text represents a single [already parsed] argument,
retrieved by a previous call to arg_next(). In this case, quotes
were already found and removed, spaces are part of the argument
itself and not a delimiter. When this text is encountered again
it should be taken as-is.
(b) Other times (GS_OPTIONS) this text is an [unparsed] list of
arguments; [only the] unquoted spaces are delimiters. When
arg_next() reaches the string it has to parse it normally.
(c) Currently arg_next() cannot know if it's case (a) or (b). It does
the parsing from the <spaces are delimiters> point of view, but
does not do the parsing from the <quotes are for quoting> point of
view. IMHO, the <&& f != NULL> (hunk <@@ -172,9 +189,9 @@> in the
attached diff) was an [incorrect and partial] attempt to
handle (a). Taking <"> as a regular character in GS_OPTIONS is a
direct consequence of this. I see absolutely no reason for
accepting spaces as delimiters without allowing <"> to quote them.
Sincerely yours,
Gh. Savulescu
-------------- next part --------------
Index: src/gsargs.h
===================================================================
--- src/gsargs.h (revision 7138)
+++ src/gsargs.h (working copy)
@@ -29,6 +29,7 @@
bool is_file;
union _u {
struct _su {
+ bool parsed; /* true for "pushed-back" argument, not to be parsed again */
char *chars; /* original string */
gs_memory_t *memory; /* if non-0, free chars when done with it */
const char *str; /* string being read */
@@ -57,13 +58,11 @@
* This may also be used (once) to "unread" the last argument.
* If mem != 0, it is used to free the string when we are done with it.
* Return 0 on success, non-zero on failure
- * NB: pushing args has the side effect of changing the parsing algoritm to
- * space delimited instead of argument string delimited.
*/
-int arg_push_memory_string(arg_list * pal, char *str, gs_memory_t * mem);
+int arg_push_memory_string(arg_list * pal, char *str, bool parsed, gs_memory_t * mem);
-#define arg_push_string(pal, str)\
- arg_push_memory_string(pal, str, (gs_memory_t *)0);
+#define arg_push_string(pal, str, parsed)\
+ arg_push_memory_string(pal, str, parsed, (gs_memory_t *)0);
/* Clean up an arg list before exiting. */
void arg_finit(arg_list * pal);
Index: src/imainarg.c
===================================================================
--- src/imainarg.c (revision 7138)
+++ src/imainarg.c (working copy)
@@ -194,7 +194,7 @@
(char *)gs_alloc_bytes(minst->heap, len, "GS_OPTIONS");
gp_getenv(GS_OPTIONS, opts, &len); /* can't fail */
- if (arg_push_memory_string(&args, opts, minst->heap))
+ if (arg_push_memory_string(&args, opts, false, minst->heap))
return e_Fatal;
}
}
@@ -366,7 +366,7 @@
char *p = arg_copy(arg, minst->heap);
if (p == NULL)
return e_Fatal;
- arg_push_string(pal, p);
+ arg_push_string(pal, p, true);
}
pal->expand_ats = ats;
break;
Index: src/gsargs.c
===================================================================
--- src/gsargs.c (revision 7138)
+++ src/gsargs.c (working copy)
@@ -37,7 +37,7 @@
/* Push a string onto an arg list. */
int
-arg_push_memory_string(arg_list * pal, char *str, gs_memory_t * mem)
+arg_push_memory_string(arg_list * pal, char *str, bool parsed, gs_memory_t * mem)
{
arg_source *pas;
@@ -47,6 +47,7 @@
}
pas = &pal->sources[pal->depth];
pas->is_file = false;
+ pas->u.s.parsed = parsed;
pas->u.s.chars = str;
pas->u.s.memory = mem;
pas->u.s.str = str;
@@ -92,6 +93,22 @@
}
if (pas->is_file)
f = pas->u.file, endc = EOF;
+ else if (pas->u.s.parsed)
+ /* this string is a "pushed-back" argument */
+ /* (retrieved by a precedeing arg_next(), but not processed) */
+ if (strlen(pas->u.s.str) >= arg_str_max) {
+ errprintf("Command too long: %s\n", pas->u.s.str);
+ *code = gs_error_Fatal;
+ return NULL;
+ } else {
+ strcpy(pal->cstr, pas->u.s.str);
+ result = pal->cstr;
+ if (pas->u.s.memory)
+ gs_free_object(pas->u.s.memory, pas->u.s.chars, "arg_next");
+ pal->depth--;
+ pas--;
+ goto at;
+ }
else
astr = pas->u.s.str, f = NULL, endc = 0;
result = cstr = pal->cstr;
@@ -172,9 +189,9 @@
*code = gs_error_Fatal;
return NULL;
}
- /* If input is coming from an @-file, allow quotes */
- /* to protect whitespace. */
- if (c == '"' && f != NULL)
+ /* Allow quotes to protect whitespace. */
+ /* (special cases have already been handled and don't reach this point) */
+ if (c == '"')
in_quote = !in_quote;
else
cstr[i++] = c;
More information about the gs-devel
mailing list