2 Free Software Foundation, Inc.
3 Written by: Jeff Conrad (jeff_conrad@msn.com)
4 and Keith Marshall (keith.d.marshall@ntlworld.com)
6 This file is part of groff.
8 groff is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
13 groff is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License along
19 with groff; see the file COPYING. If not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
28 /* Define the default mechanism, and messages, for error reporting
29 * (user may substitute a preferred alternative, by defining his own
30 * implementation of the macros REPORT_ERROR, QUOTE_ARG_MALLOC_FAILED
31 * and QUOTE_ARG_REALLOC_FAILED, in the header file `nonposix.h').
37 # define REPORT_ERROR(WHY) fprintf(stderr, "%s:%s\n", program_name, WHY)
39 #ifndef QUOTE_ARG_MALLOC_ERROR
40 # define QUOTE_ARG_MALLOC_ERROR "malloc: Buffer allocation failed"
42 #ifndef QUOTE_ARG_REALLOC_ERROR
43 # define QUOTE_ARG_REALLOC_ERROR "realloc: Buffer resize failed"
46 extern char *program_name
; /* main program must define this */
54 needs_quoting(const char *string
)
56 /* Scan `string' to see whether it needs quoting for MSVC `spawn'/`exec'
57 * (i.e., whether it contains whitespace or embedded quotes).
60 if (string
== NULL
) /* ignore NULL strings */
63 if (*string
== '\0') /* explicit arguments of zero length */
64 return TRUE
; /* need quoting, so they aren't discarded */
67 /* Scan non-NULL strings, up to '\0' terminator,
68 * returning 'TRUE' if quote or white space found.
71 if (*string
== '"' || isspace(*string
))
74 /* otherwise, continue scanning to end of string */
79 /* Fall through, if no quotes or white space found,
80 * in which case, return `FALSE'.
87 quote_arg(char *string
)
89 /* Enclose arguments in double quotes so that the parsing done in the
90 * MSVC runtime startup code doesn't split them at whitespace. Escape
91 * embedded double quotes so that they emerge intact from the parsing.
97 if (needs_quoting(string
)) {
98 /* Need to create a quoted copy of `string';
99 * maximum buffer space needed is twice the original length,
100 * plus two enclosing quotes and one `\0' terminator.
103 if ((quoted
= (char *)malloc(2 * strlen(string
) + 3)) == NULL
) {
104 /* Couldn't get a buffer for the quoted string,
105 * so complain, and bail out gracefully.
108 REPORT_ERROR(QUOTE_ARG_MALLOC_ERROR
);
113 * insert the opening quote, then copy the source string,
114 * adding escapes as required.
118 for (backslashes
= 0, p
= string
, q
= quoted
; *p
; p
++) {
120 /* Just count backslashes when we find them.
121 * We will copy them out later, when we know if the count
122 * needs to be adjusted, to escape an embedded quote.
127 else if (*p
== '"') {
128 /* This embedded quote character must be escaped,
129 * but first double up any immediately preceding backslashes,
130 * with one extra, as the escape character.
133 for (backslashes
+= backslashes
+ 1; backslashes
; backslashes
--)
136 /* and now, add the quote character itself */
141 /* Any other character is simply copied,
142 * but first, if we have any pending backslashes,
143 * we must now insert them, without any count adjustment.
146 while (backslashes
) {
151 /* and then, copy the current character */
157 /* At end of argument:
158 * If any backslashes remain to be copied out, append them now,
159 * doubling the actual count to protect against reduction by MSVC,
160 * as a consequence of the immediately following closing quote.
163 for (backslashes
+= backslashes
; backslashes
; backslashes
--)
167 * add the closing quote, terminate the quoted string,
168 * and adjust its size to what was actually required,
174 if ((string
= (char *)realloc(quoted
, strlen(quoted
) + 1)) == NULL
) {
175 /* but bail out gracefully, on error */
177 REPORT_ERROR(QUOTE_ARG_REALLOC_ERROR
);
182 /* `string' now refers to the argument,
183 * quoted and escaped, as required.
190 purge_quoted_args(char **argv
)
192 /* To avoid memory leaks,
193 * free all memory previously allocated by `quoted_arg()',
194 * within the scope of the referring argument vector, `argv'.
199 /* Any argument beginning with a double quote
200 * SHOULD have been allocated by `quoted_arg()'.
204 free( *argv
); /* so free its allocation */
205 ++argv
; /* and continue to the next argument */
209 /* quotearg.c: end of file */