1248
|
1 /* quotearg.c - quote arguments for output |
|
2 Copyright (C) 1998 Free Software Foundation, Inc. |
|
3 |
|
4 This program is free software; you can redistribute it and/or modify |
|
5 it under the terms of the GNU General Public License as published by |
|
6 the Free Software Foundation; either version 2, or (at your option) |
|
7 any later version. |
|
8 |
|
9 This program is distributed in the hope that it will be useful, |
|
10 but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 GNU General Public License for more details. |
|
13 |
|
14 You should have received a copy of the GNU General Public License |
|
15 along with this program; if not, write to the Free Software Foundation, |
|
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
|
17 |
|
18 /* Written by Paul Eggert <eggert@twinsun.com> */ |
|
19 |
|
20 #if HAVE_CONFIG_H |
|
21 # include <config.h> |
|
22 #endif |
|
23 |
|
24 #include <sys/types.h> |
|
25 #include <quotearg.h> |
|
26 #include <xalloc.h> |
|
27 |
|
28 #include <ctype.h> |
|
29 #if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII)) |
|
30 # define ISASCII(c) 1 |
|
31 #else |
|
32 # define ISASCII(c) isascii (c) |
|
33 #endif |
|
34 #ifdef isgraph |
|
35 # define ISGRAPH(c) (ISASCII (c) && isgraph (c)) |
|
36 #else |
|
37 # define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c)) |
|
38 #endif |
|
39 |
|
40 #if HAVE_LIMITS_H |
|
41 # include <limits.h> |
|
42 #endif |
|
43 #ifndef CHAR_BIT |
|
44 # define CHAR_BIT 8 |
|
45 #endif |
|
46 #ifndef UCHAR_MAX |
|
47 # define UCHAR_MAX ((unsigned char) -1) |
|
48 #endif |
|
49 |
|
50 #if HAVE_STDLIB_H |
|
51 # include <stdlib.h> |
|
52 #endif |
|
53 |
|
54 #if HAVE_STRING_H |
|
55 # include <string.h> |
|
56 #endif |
|
57 |
|
58 #define INT_BITS (sizeof (int) * CHAR_BIT) |
|
59 |
|
60 struct quoting_options |
|
61 { |
|
62 /* Basic quoting style. */ |
|
63 enum quoting_style style; |
|
64 |
|
65 /* Quote the chararacters indicated by this bit vector even if the |
|
66 quoting style would not normally require them to be quoted. */ |
|
67 int quote_these_too[((UCHAR_MAX + 1) / INT_BITS |
|
68 + ((UCHAR_MAX + 1) % INT_BITS != 0))]; |
|
69 }; |
|
70 |
|
71 /* Names of quoting styles. */ |
|
72 char const *const quoting_style_args[] = |
|
73 { |
|
74 "literal", "shell", "shell-always", "c", "escape", 0 |
|
75 }; |
|
76 |
1282
|
77 /* The default quoting options. */ |
|
78 static struct quoting_options default_quoting_options; |
|
79 |
1248
|
80 /* Allocate a new set of quoting options, with contents initially identical |
1282
|
81 to O if O is not null, or to the default if O is null. |
1248
|
82 It is the caller's responsibility to free the result. */ |
|
83 struct quoting_options * |
|
84 clone_quoting_options (struct quoting_options *o) |
|
85 { |
|
86 struct quoting_options *p |
|
87 = (struct quoting_options *) xmalloc (sizeof (struct quoting_options)); |
1282
|
88 *p = *(o ? o : &default_quoting_options); |
1248
|
89 return p; |
|
90 } |
|
91 |
1282
|
92 /* Get the value of O's quoting style. If O is null, use the default. */ |
1248
|
93 enum quoting_style |
|
94 get_quoting_style (struct quoting_options *o) |
|
95 { |
1282
|
96 return (o ? o : &default_quoting_options)->style; |
1248
|
97 } |
|
98 |
1282
|
99 /* In O (or in the default if O is null), |
|
100 set the value of the quoting style to S. */ |
1248
|
101 void |
|
102 set_quoting_style (struct quoting_options *o, enum quoting_style s) |
|
103 { |
1282
|
104 (o ? o : &default_quoting_options)->style = s; |
1248
|
105 } |
|
106 |
1282
|
107 /* In O (or in the default if O is null), |
|
108 set the value of the quoting options for character C to I. |
1248
|
109 Return the old value. Currently, the only values defined for I are |
|
110 0 (the default) and 1 (which means to quote the character even if |
|
111 it would not otherwise be quoted). */ |
|
112 int |
|
113 set_char_quoting (struct quoting_options *o, char c, int i) |
|
114 { |
|
115 unsigned char uc = c; |
1282
|
116 int *p = (o ? o : &default_quoting_options)->quote_these_too + uc / INT_BITS; |
1248
|
117 int shift = uc % INT_BITS; |
|
118 int r = (*p >> shift) & 1; |
|
119 *p ^= ((i & 1) ^ r) << shift; |
|
120 return r; |
|
121 } |
|
122 |
1282
|
123 /* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of |
1248
|
124 argument ARG (of size ARGSIZE), using O to control quoting. |
1282
|
125 If O is null, use the default. |
1248
|
126 Terminate the output with a null character, and return the written |
|
127 size of the output, not counting the terminating null. |
1282
|
128 If BUFFERSIZE is too small to store the output string, return the |
|
129 value that would have been returned had BUFFERSIZE been large enough. |
1248
|
130 If ARGSIZE is -1, use the string length of the argument for ARGSIZE. */ |
|
131 size_t |
1282
|
132 quotearg_buffer (char *buffer, size_t buffersize, |
1248
|
133 char const *arg, size_t argsize, |
|
134 struct quoting_options const *o) |
|
135 { |
|
136 unsigned char c; |
|
137 size_t i; |
|
138 size_t len; |
|
139 int quote_mark; |
1282
|
140 struct quoting_options const *p = o ? o : &default_quoting_options; |
|
141 enum quoting_style quoting_style = p->style; |
|
142 #define STORE(c) \ |
|
143 do \ |
|
144 { \ |
|
145 if (len < buffersize) \ |
|
146 buffer[len] = (c); \ |
|
147 len++; \ |
|
148 } \ |
|
149 while (0) |
1248
|
150 |
|
151 switch (quoting_style) |
|
152 { |
|
153 case shell_quoting_style: |
|
154 if (! (argsize == -1 ? arg[0] == '\0' : argsize == 0)) |
|
155 { |
|
156 switch (arg[0]) |
|
157 { |
|
158 case '#': case '~': |
|
159 break; |
|
160 |
|
161 default: |
|
162 len = 0; |
|
163 for (i = 0; ; i++) |
|
164 { |
|
165 if (argsize == -1 ? arg[i] == '\0' : i == argsize) |
|
166 goto done; |
|
167 |
|
168 c = arg[i]; |
|
169 |
|
170 switch (c) |
|
171 { |
|
172 case '\t': case '\n': case ' ': |
|
173 case '!': /* special in csh */ |
|
174 case '"': case '$': case '&': case '\'': |
|
175 case '(': case ')': case '*': case ';': |
|
176 case '<': case '>': case '?': case '[': case '\\': |
|
177 case '^': /* special in old /bin/sh, e.g. SunOS 4.1.4 */ |
|
178 case '`': case '|': |
|
179 goto needs_quoting; |
|
180 } |
|
181 |
1282
|
182 if (p->quote_these_too[c / INT_BITS] & (1 << (c % INT_BITS))) |
1248
|
183 goto needs_quoting; |
|
184 |
|
185 STORE (c); |
|
186 } |
|
187 |
|
188 needs_quoting:; |
|
189 break; |
|
190 } |
|
191 } |
|
192 /* Fall through. */ |
|
193 |
|
194 case shell_always_quoting_style: |
|
195 quote_mark = '\''; |
|
196 break; |
|
197 |
|
198 case c_quoting_style: |
|
199 quote_mark = '"'; |
|
200 break; |
|
201 |
|
202 default: |
|
203 quote_mark = 0; |
|
204 break; |
|
205 } |
|
206 |
|
207 len = 0; |
|
208 |
|
209 if (quote_mark) |
|
210 STORE (quote_mark); |
|
211 |
|
212 for (i = 0; ! (argsize == -1 ? arg[i] == '\0' : i == argsize); i++) |
|
213 { |
|
214 c = arg[i]; |
|
215 |
|
216 switch (quoting_style) |
|
217 { |
|
218 case literal_quoting_style: |
|
219 break; |
|
220 |
|
221 case shell_quoting_style: |
|
222 case shell_always_quoting_style: |
|
223 if (c == '\'') |
|
224 { |
|
225 STORE ('\''); |
|
226 STORE ('\\'); |
|
227 STORE ('\''); |
|
228 } |
|
229 break; |
|
230 |
|
231 case c_quoting_style: |
|
232 case escape_quoting_style: |
|
233 switch (c) |
|
234 { |
|
235 case '?': /* Do not generate trigraphs. */ |
|
236 case '\\': goto store_escape; |
|
237 /* Not all C compilers know what \a means. */ |
|
238 case 7 : c = 'a'; goto store_escape; |
|
239 case '\b': c = 'b'; goto store_escape; |
|
240 case '\f': c = 'f'; goto store_escape; |
|
241 case '\n': c = 'n'; goto store_escape; |
|
242 case '\r': c = 'r'; goto store_escape; |
|
243 case '\t': c = 't'; goto store_escape; |
|
244 case '\v': c = 'v'; goto store_escape; |
|
245 |
|
246 case ' ': |
|
247 if (quoting_style == escape_quoting_style) |
|
248 goto store_escape; |
|
249 break; |
|
250 |
|
251 case '"': |
|
252 if (quoting_style == c_quoting_style) |
|
253 goto store_escape; |
|
254 break; |
|
255 |
|
256 default: |
|
257 if (!ISGRAPH (c)) |
|
258 { |
|
259 STORE ('\\'); |
|
260 STORE ('0' + (c >> 6)); |
|
261 STORE ('0' + ((c >> 3) & 3)); |
|
262 c = '0' + (c & 3); |
|
263 goto store_c; |
|
264 } |
|
265 break; |
|
266 } |
|
267 |
1282
|
268 if (! (p->quote_these_too[c / INT_BITS] & (1 << (c % INT_BITS)))) |
1248
|
269 goto store_c; |
|
270 |
|
271 store_escape: |
|
272 STORE ('\\'); |
|
273 } |
|
274 |
|
275 store_c: |
|
276 STORE (c); |
|
277 } |
|
278 |
|
279 if (quote_mark) |
|
280 STORE (quote_mark); |
|
281 |
|
282 done: |
1282
|
283 if (len < buffersize) |
|
284 buffer[len] = '\0'; |
1248
|
285 return len; |
|
286 } |
|
287 |
|
288 /* Use storage slot N to return a quoted version of the string ARG. |
|
289 OPTIONS specifies the quoting options. |
|
290 The returned value points to static storage that can be |
|
291 reused by the next call to this function with the same value of N. |
|
292 N must be nonnegative. */ |
|
293 static char * |
|
294 quotearg_n_options (int n, char const *arg, struct quoting_options *options) |
|
295 { |
|
296 static unsigned nslots; |
|
297 static struct slotvec |
|
298 { |
|
299 size_t size; |
|
300 char *val; |
|
301 } *slotvec; |
|
302 |
|
303 if (nslots <= n) |
|
304 { |
|
305 int n1 = n + 1; |
|
306 size_t s = n1 * sizeof (struct slotvec); |
|
307 if (! (0 < n1 && n1 == s / sizeof (struct slotvec))) |
|
308 abort (); |
|
309 slotvec = (struct slotvec *) xrealloc (slotvec, s); |
|
310 memset (slotvec + nslots, 0, (n1 - nslots) * sizeof (struct slotvec)); |
|
311 nslots = n; |
|
312 } |
|
313 |
|
314 { |
|
315 size_t size = slotvec[n].size; |
|
316 char *val = slotvec[n].val; |
|
317 size_t qsize = quotearg_buffer (val, size, arg, (size_t) -1, options); |
|
318 |
|
319 if (size <= qsize) |
|
320 { |
|
321 slotvec[n].size = size = qsize + 1; |
|
322 slotvec[n].val = val = xrealloc (val, size); |
|
323 quotearg_buffer (val, size, arg, (size_t) -1, options); |
|
324 } |
|
325 |
|
326 return val; |
|
327 } |
|
328 } |
|
329 |
|
330 char * |
|
331 quotearg_n (int n, char const *arg) |
|
332 { |
1282
|
333 return quotearg_n_options (n, arg, &default_quoting_options); |
1248
|
334 } |
|
335 |
|
336 char * |
|
337 quotearg (char const *arg) |
|
338 { |
|
339 return quotearg_n (0, arg); |
|
340 } |
|
341 |
|
342 char * |
|
343 quotearg_char (char const *arg, char ch) |
|
344 { |
|
345 struct quoting_options options; |
1282
|
346 options = default_quoting_options; |
1248
|
347 set_char_quoting (&options, ch, 1); |
|
348 return quotearg_n_options (0, arg, &options); |
|
349 } |
|
350 |
|
351 char * |
|
352 quotearg_colon (char const *arg) |
|
353 { |
|
354 return quotearg_char (arg, ':'); |
|
355 } |