Mercurial > hg > CbC > CbC_gcc
annotate libiberty/argv.c @ 109:78d3881f2882
add CbC-example/rectype
author | Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Thu, 14 Jun 2012 20:43:12 +0900 |
parents | f6334be47118 |
children | 04ced10e8804 |
rev | line source |
---|---|
0 | 1 /* Create and destroy argument vectors (argv's) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2 Copyright (C) 1992, 2001, 2010 Free Software Foundation, Inc. |
0 | 3 Written by Fred Fish @ Cygnus Support |
4 | |
5 This file is part of the libiberty library. | |
6 Libiberty is free software; you can redistribute it and/or | |
7 modify it under the terms of the GNU Library General Public | |
8 License as published by the Free Software Foundation; either | |
9 version 2 of the License, or (at your option) any later version. | |
10 | |
11 Libiberty is distributed in the hope that it will be useful, | |
12 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 Library General Public License for more details. | |
15 | |
16 You should have received a copy of the GNU Library General Public | |
17 License along with libiberty; see the file COPYING.LIB. If | |
18 not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, | |
19 Boston, MA 02110-1301, USA. */ | |
20 | |
21 | |
22 /* Create and destroy argument vectors. An argument vector is simply an | |
23 array of string pointers, terminated by a NULL pointer. */ | |
24 | |
25 #ifdef HAVE_CONFIG_H | |
26 #include "config.h" | |
27 #endif | |
28 #include "ansidecl.h" | |
29 #include "libiberty.h" | |
30 #include "safe-ctype.h" | |
31 | |
32 /* Routines imported from standard C runtime libraries. */ | |
33 | |
34 #include <stddef.h> | |
35 #include <string.h> | |
36 #include <stdlib.h> | |
37 #include <stdio.h> | |
38 | |
39 #ifndef NULL | |
40 #define NULL 0 | |
41 #endif | |
42 | |
43 #ifndef EOS | |
44 #define EOS '\0' | |
45 #endif | |
46 | |
47 #define INITIAL_MAXARGC 8 /* Number of args + NULL in initial argv */ | |
48 | |
49 | |
50 /* | |
51 | |
52 @deftypefn Extension char** dupargv (char **@var{vector}) | |
53 | |
54 Duplicate an argument vector. Simply scans through @var{vector}, | |
55 duplicating each argument until the terminating @code{NULL} is found. | |
56 Returns a pointer to the argument vector if successful. Returns | |
57 @code{NULL} if there is insufficient memory to complete building the | |
58 argument vector. | |
59 | |
60 @end deftypefn | |
61 | |
62 */ | |
63 | |
64 char ** | |
65 dupargv (char **argv) | |
66 { | |
67 int argc; | |
68 char **copy; | |
69 | |
70 if (argv == NULL) | |
71 return NULL; | |
72 | |
73 /* the vector */ | |
74 for (argc = 0; argv[argc] != NULL; argc++); | |
75 copy = (char **) malloc ((argc + 1) * sizeof (char *)); | |
76 if (copy == NULL) | |
77 return NULL; | |
78 | |
79 /* the strings */ | |
80 for (argc = 0; argv[argc] != NULL; argc++) | |
81 { | |
82 int len = strlen (argv[argc]); | |
83 copy[argc] = (char *) malloc (len + 1); | |
84 if (copy[argc] == NULL) | |
85 { | |
86 freeargv (copy); | |
87 return NULL; | |
88 } | |
89 strcpy (copy[argc], argv[argc]); | |
90 } | |
91 copy[argc] = NULL; | |
92 return copy; | |
93 } | |
94 | |
95 /* | |
96 | |
97 @deftypefn Extension void freeargv (char **@var{vector}) | |
98 | |
99 Free an argument vector that was built using @code{buildargv}. Simply | |
100 scans through @var{vector}, freeing the memory for each argument until | |
101 the terminating @code{NULL} is found, and then frees @var{vector} | |
102 itself. | |
103 | |
104 @end deftypefn | |
105 | |
106 */ | |
107 | |
108 void freeargv (char **vector) | |
109 { | |
110 register char **scan; | |
111 | |
112 if (vector != NULL) | |
113 { | |
114 for (scan = vector; *scan != NULL; scan++) | |
115 { | |
116 free (*scan); | |
117 } | |
118 free (vector); | |
119 } | |
120 } | |
121 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
122 static void |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
123 consume_whitespace (const char **input) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
124 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
125 while (ISSPACE (**input)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
126 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
127 (*input)++; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
128 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
129 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
130 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
131 static int |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
132 only_whitespace (const char* input) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
133 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
134 while (*input != EOS && ISSPACE (*input)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
135 input++; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
136 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
137 return (*input == EOS); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
138 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
139 |
0 | 140 /* |
141 | |
142 @deftypefn Extension char** buildargv (char *@var{sp}) | |
143 | |
144 Given a pointer to a string, parse the string extracting fields | |
145 separated by whitespace and optionally enclosed within either single | |
146 or double quotes (which are stripped off), and build a vector of | |
147 pointers to copies of the string for each field. The input string | |
148 remains unchanged. The last element of the vector is followed by a | |
149 @code{NULL} element. | |
150 | |
151 All of the memory for the pointer array and copies of the string | |
152 is obtained from @code{malloc}. All of the memory can be returned to the | |
153 system with the single function call @code{freeargv}, which takes the | |
154 returned result of @code{buildargv}, as it's argument. | |
155 | |
156 Returns a pointer to the argument vector if successful. Returns | |
157 @code{NULL} if @var{sp} is @code{NULL} or if there is insufficient | |
158 memory to complete building the argument vector. | |
159 | |
160 If the input is a null string (as opposed to a @code{NULL} pointer), | |
161 then buildarg returns an argument vector that has one arg, a null | |
162 string. | |
163 | |
164 @end deftypefn | |
165 | |
166 The memory for the argv array is dynamically expanded as necessary. | |
167 | |
168 In order to provide a working buffer for extracting arguments into, | |
169 with appropriate stripping of quotes and translation of backslash | |
170 sequences, we allocate a working buffer at least as long as the input | |
171 string. This ensures that we always have enough space in which to | |
172 work, since the extracted arg is never larger than the input string. | |
173 | |
174 The argument vector is always kept terminated with a @code{NULL} arg | |
175 pointer, so it can be passed to @code{freeargv} at any time, or | |
176 returned, as appropriate. | |
177 | |
178 */ | |
179 | |
180 char **buildargv (const char *input) | |
181 { | |
182 char *arg; | |
183 char *copybuf; | |
184 int squote = 0; | |
185 int dquote = 0; | |
186 int bsquote = 0; | |
187 int argc = 0; | |
188 int maxargc = 0; | |
189 char **argv = NULL; | |
190 char **nargv; | |
191 | |
192 if (input != NULL) | |
193 { | |
194 copybuf = (char *) alloca (strlen (input) + 1); | |
195 /* Is a do{}while to always execute the loop once. Always return an | |
196 argv, even for null strings. See NOTES above, test case below. */ | |
197 do | |
198 { | |
199 /* Pick off argv[argc] */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
200 consume_whitespace (&input); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
201 |
0 | 202 if ((maxargc == 0) || (argc >= (maxargc - 1))) |
203 { | |
204 /* argv needs initialization, or expansion */ | |
205 if (argv == NULL) | |
206 { | |
207 maxargc = INITIAL_MAXARGC; | |
208 nargv = (char **) malloc (maxargc * sizeof (char *)); | |
209 } | |
210 else | |
211 { | |
212 maxargc *= 2; | |
213 nargv = (char **) realloc (argv, maxargc * sizeof (char *)); | |
214 } | |
215 if (nargv == NULL) | |
216 { | |
217 if (argv != NULL) | |
218 { | |
219 freeargv (argv); | |
220 argv = NULL; | |
221 } | |
222 break; | |
223 } | |
224 argv = nargv; | |
225 argv[argc] = NULL; | |
226 } | |
227 /* Begin scanning arg */ | |
228 arg = copybuf; | |
229 while (*input != EOS) | |
230 { | |
231 if (ISSPACE (*input) && !squote && !dquote && !bsquote) | |
232 { | |
233 break; | |
234 } | |
235 else | |
236 { | |
237 if (bsquote) | |
238 { | |
239 bsquote = 0; | |
240 *arg++ = *input; | |
241 } | |
242 else if (*input == '\\') | |
243 { | |
244 bsquote = 1; | |
245 } | |
246 else if (squote) | |
247 { | |
248 if (*input == '\'') | |
249 { | |
250 squote = 0; | |
251 } | |
252 else | |
253 { | |
254 *arg++ = *input; | |
255 } | |
256 } | |
257 else if (dquote) | |
258 { | |
259 if (*input == '"') | |
260 { | |
261 dquote = 0; | |
262 } | |
263 else | |
264 { | |
265 *arg++ = *input; | |
266 } | |
267 } | |
268 else | |
269 { | |
270 if (*input == '\'') | |
271 { | |
272 squote = 1; | |
273 } | |
274 else if (*input == '"') | |
275 { | |
276 dquote = 1; | |
277 } | |
278 else | |
279 { | |
280 *arg++ = *input; | |
281 } | |
282 } | |
283 input++; | |
284 } | |
285 } | |
286 *arg = EOS; | |
287 argv[argc] = strdup (copybuf); | |
288 if (argv[argc] == NULL) | |
289 { | |
290 freeargv (argv); | |
291 argv = NULL; | |
292 break; | |
293 } | |
294 argc++; | |
295 argv[argc] = NULL; | |
296 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
297 consume_whitespace (&input); |
0 | 298 } |
299 while (*input != EOS); | |
300 } | |
301 return (argv); | |
302 } | |
303 | |
304 /* | |
305 | |
306 @deftypefn Extension int writeargv (const char **@var{argv}, FILE *@var{file}) | |
307 | |
308 Write each member of ARGV, handling all necessary quoting, to the file | |
309 named by FILE, separated by whitespace. Return 0 on success, non-zero | |
310 if an error occurred while writing to FILE. | |
311 | |
312 @end deftypefn | |
313 | |
314 */ | |
315 | |
316 int | |
317 writeargv (char **argv, FILE *f) | |
318 { | |
319 int status = 0; | |
320 | |
321 if (f == NULL) | |
322 return 1; | |
323 | |
324 while (*argv != NULL) | |
325 { | |
326 const char *arg = *argv; | |
327 | |
328 while (*arg != EOS) | |
329 { | |
330 char c = *arg; | |
331 | |
332 if (ISSPACE(c) || c == '\\' || c == '\'' || c == '"') | |
333 if (EOF == fputc ('\\', f)) | |
334 { | |
335 status = 1; | |
336 goto done; | |
337 } | |
338 | |
339 if (EOF == fputc (c, f)) | |
340 { | |
341 status = 1; | |
342 goto done; | |
343 } | |
344 arg++; | |
345 } | |
346 | |
347 if (EOF == fputc ('\n', f)) | |
348 { | |
349 status = 1; | |
350 goto done; | |
351 } | |
352 argv++; | |
353 } | |
354 | |
355 done: | |
356 return status; | |
357 } | |
358 | |
359 /* | |
360 | |
361 @deftypefn Extension void expandargv (int *@var{argcp}, char ***@var{argvp}) | |
362 | |
363 The @var{argcp} and @code{argvp} arguments are pointers to the usual | |
364 @code{argc} and @code{argv} arguments to @code{main}. This function | |
365 looks for arguments that begin with the character @samp{@@}. Any such | |
366 arguments are interpreted as ``response files''. The contents of the | |
367 response file are interpreted as additional command line options. In | |
368 particular, the file is separated into whitespace-separated strings; | |
369 each such string is taken as a command-line option. The new options | |
370 are inserted in place of the option naming the response file, and | |
371 @code{*argcp} and @code{*argvp} will be updated. If the value of | |
372 @code{*argvp} is modified by this function, then the new value has | |
373 been dynamically allocated and can be deallocated by the caller with | |
374 @code{freeargv}. However, most callers will simply call | |
375 @code{expandargv} near the beginning of @code{main} and allow the | |
376 operating system to free the memory when the program exits. | |
377 | |
378 @end deftypefn | |
379 | |
380 */ | |
381 | |
382 void | |
383 expandargv (int *argcp, char ***argvp) | |
384 { | |
385 /* The argument we are currently processing. */ | |
386 int i = 0; | |
387 /* Non-zero if ***argvp has been dynamically allocated. */ | |
388 int argv_dynamic = 0; | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
389 /* Limit the number of response files that we parse in order |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
390 to prevent infinite recursion. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
391 unsigned int iteration_limit = 2000; |
0 | 392 /* Loop over the arguments, handling response files. We always skip |
393 ARGVP[0], as that is the name of the program being run. */ | |
394 while (++i < *argcp) | |
395 { | |
396 /* The name of the response file. */ | |
397 const char *filename; | |
398 /* The response file. */ | |
399 FILE *f; | |
400 /* An upper bound on the number of characters in the response | |
401 file. */ | |
402 long pos; | |
403 /* The number of characters in the response file, when actually | |
404 read. */ | |
405 size_t len; | |
406 /* A dynamically allocated buffer used to hold options read from a | |
407 response file. */ | |
408 char *buffer; | |
409 /* Dynamically allocated storage for the options read from the | |
410 response file. */ | |
411 char **file_argv; | |
412 /* The number of options read from the response file, if any. */ | |
413 size_t file_argc; | |
414 /* We are only interested in options of the form "@file". */ | |
415 filename = (*argvp)[i]; | |
416 if (filename[0] != '@') | |
417 continue; | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
418 /* If we have iterated too many times then stop. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
419 if (-- iteration_limit == 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
420 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
421 fprintf (stderr, "%s: error: too many @-files encountered\n", (*argvp)[0]); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
422 xexit (1); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
423 } |
0 | 424 /* Read the contents of the file. */ |
425 f = fopen (++filename, "r"); | |
426 if (!f) | |
427 continue; | |
428 if (fseek (f, 0L, SEEK_END) == -1) | |
429 goto error; | |
430 pos = ftell (f); | |
431 if (pos == -1) | |
432 goto error; | |
433 if (fseek (f, 0L, SEEK_SET) == -1) | |
434 goto error; | |
435 buffer = (char *) xmalloc (pos * sizeof (char) + 1); | |
436 len = fread (buffer, sizeof (char), pos, f); | |
437 if (len != (size_t) pos | |
438 /* On Windows, fread may return a value smaller than POS, | |
439 due to CR/LF->CR translation when reading text files. | |
440 That does not in-and-of itself indicate failure. */ | |
441 && ferror (f)) | |
442 goto error; | |
443 /* Add a NUL terminator. */ | |
444 buffer[len] = '\0'; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
445 /* If the file is empty or contains only whitespace, buildargv would |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
446 return a single empty argument. In this context we want no arguments, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
447 instead. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
448 if (only_whitespace (buffer)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
449 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
450 file_argv = (char **) xmalloc (sizeof (char *)); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
451 file_argv[0] = NULL; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
452 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
453 else |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
454 /* Parse the string. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
455 file_argv = buildargv (buffer); |
0 | 456 /* If *ARGVP is not already dynamically allocated, copy it. */ |
457 if (!argv_dynamic) | |
458 { | |
459 *argvp = dupargv (*argvp); | |
460 if (!*argvp) | |
461 { | |
462 fputs ("\nout of memory\n", stderr); | |
463 xexit (1); | |
464 } | |
465 } | |
466 /* Count the number of arguments. */ | |
467 file_argc = 0; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
468 while (file_argv[file_argc]) |
0 | 469 ++file_argc; |
470 /* Now, insert FILE_ARGV into ARGV. The "+1" below handles the | |
471 NULL terminator at the end of ARGV. */ | |
472 *argvp = ((char **) | |
473 xrealloc (*argvp, | |
474 (*argcp + file_argc + 1) * sizeof (char *))); | |
475 memmove (*argvp + i + file_argc, *argvp + i + 1, | |
476 (*argcp - i) * sizeof (char *)); | |
477 memcpy (*argvp + i, file_argv, file_argc * sizeof (char *)); | |
478 /* The original option has been replaced by all the new | |
479 options. */ | |
480 *argcp += file_argc - 1; | |
481 /* Free up memory allocated to process the response file. We do | |
482 not use freeargv because the individual options in FILE_ARGV | |
483 are now in the main ARGV. */ | |
484 free (file_argv); | |
485 free (buffer); | |
486 /* Rescan all of the arguments just read to support response | |
487 files that include other response files. */ | |
488 --i; | |
489 error: | |
490 /* We're all done with the file now. */ | |
491 fclose (f); | |
492 } | |
493 } | |
494 | |
495 #ifdef MAIN | |
496 | |
497 /* Simple little test driver. */ | |
498 | |
499 static const char *const tests[] = | |
500 { | |
501 "a simple command line", | |
502 "arg 'foo' is single quoted", | |
503 "arg \"bar\" is double quoted", | |
504 "arg \"foo bar\" has embedded whitespace", | |
505 "arg 'Jack said \\'hi\\'' has single quotes", | |
506 "arg 'Jack said \\\"hi\\\"' has double quotes", | |
507 "a b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9", | |
508 | |
509 /* This should be expanded into only one argument. */ | |
510 "trailing-whitespace ", | |
511 | |
512 "", | |
513 NULL | |
514 }; | |
515 | |
516 int | |
517 main (void) | |
518 { | |
519 char **argv; | |
520 const char *const *test; | |
521 char **targs; | |
522 | |
523 for (test = tests; *test != NULL; test++) | |
524 { | |
525 printf ("buildargv(\"%s\")\n", *test); | |
526 if ((argv = buildargv (*test)) == NULL) | |
527 { | |
528 printf ("failed!\n\n"); | |
529 } | |
530 else | |
531 { | |
532 for (targs = argv; *targs != NULL; targs++) | |
533 { | |
534 printf ("\t\"%s\"\n", *targs); | |
535 } | |
536 printf ("\n"); | |
537 } | |
538 freeargv (argv); | |
539 } | |
540 | |
541 return 0; | |
542 } | |
543 | |
544 #endif /* MAIN */ |