Mercurial > hg > CbC > CbC_gcc
comparison libiberty/argv.c @ 0:a06113de4d67
first commit
author | kent <kent@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 17 Jul 2009 14:47:48 +0900 |
parents | |
children | 77e2b8dfacca |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a06113de4d67 |
---|---|
1 /* Create and destroy argument vectors (argv's) | |
2 Copyright (C) 1992, 2001 Free Software Foundation, Inc. | |
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 | |
122 /* | |
123 | |
124 @deftypefn Extension char** buildargv (char *@var{sp}) | |
125 | |
126 Given a pointer to a string, parse the string extracting fields | |
127 separated by whitespace and optionally enclosed within either single | |
128 or double quotes (which are stripped off), and build a vector of | |
129 pointers to copies of the string for each field. The input string | |
130 remains unchanged. The last element of the vector is followed by a | |
131 @code{NULL} element. | |
132 | |
133 All of the memory for the pointer array and copies of the string | |
134 is obtained from @code{malloc}. All of the memory can be returned to the | |
135 system with the single function call @code{freeargv}, which takes the | |
136 returned result of @code{buildargv}, as it's argument. | |
137 | |
138 Returns a pointer to the argument vector if successful. Returns | |
139 @code{NULL} if @var{sp} is @code{NULL} or if there is insufficient | |
140 memory to complete building the argument vector. | |
141 | |
142 If the input is a null string (as opposed to a @code{NULL} pointer), | |
143 then buildarg returns an argument vector that has one arg, a null | |
144 string. | |
145 | |
146 @end deftypefn | |
147 | |
148 The memory for the argv array is dynamically expanded as necessary. | |
149 | |
150 In order to provide a working buffer for extracting arguments into, | |
151 with appropriate stripping of quotes and translation of backslash | |
152 sequences, we allocate a working buffer at least as long as the input | |
153 string. This ensures that we always have enough space in which to | |
154 work, since the extracted arg is never larger than the input string. | |
155 | |
156 The argument vector is always kept terminated with a @code{NULL} arg | |
157 pointer, so it can be passed to @code{freeargv} at any time, or | |
158 returned, as appropriate. | |
159 | |
160 */ | |
161 | |
162 char **buildargv (const char *input) | |
163 { | |
164 char *arg; | |
165 char *copybuf; | |
166 int squote = 0; | |
167 int dquote = 0; | |
168 int bsquote = 0; | |
169 int argc = 0; | |
170 int maxargc = 0; | |
171 char **argv = NULL; | |
172 char **nargv; | |
173 | |
174 if (input != NULL) | |
175 { | |
176 copybuf = (char *) alloca (strlen (input) + 1); | |
177 /* Is a do{}while to always execute the loop once. Always return an | |
178 argv, even for null strings. See NOTES above, test case below. */ | |
179 do | |
180 { | |
181 /* Pick off argv[argc] */ | |
182 while (ISBLANK (*input)) | |
183 { | |
184 input++; | |
185 } | |
186 if ((maxargc == 0) || (argc >= (maxargc - 1))) | |
187 { | |
188 /* argv needs initialization, or expansion */ | |
189 if (argv == NULL) | |
190 { | |
191 maxargc = INITIAL_MAXARGC; | |
192 nargv = (char **) malloc (maxargc * sizeof (char *)); | |
193 } | |
194 else | |
195 { | |
196 maxargc *= 2; | |
197 nargv = (char **) realloc (argv, maxargc * sizeof (char *)); | |
198 } | |
199 if (nargv == NULL) | |
200 { | |
201 if (argv != NULL) | |
202 { | |
203 freeargv (argv); | |
204 argv = NULL; | |
205 } | |
206 break; | |
207 } | |
208 argv = nargv; | |
209 argv[argc] = NULL; | |
210 } | |
211 /* Begin scanning arg */ | |
212 arg = copybuf; | |
213 while (*input != EOS) | |
214 { | |
215 if (ISSPACE (*input) && !squote && !dquote && !bsquote) | |
216 { | |
217 break; | |
218 } | |
219 else | |
220 { | |
221 if (bsquote) | |
222 { | |
223 bsquote = 0; | |
224 *arg++ = *input; | |
225 } | |
226 else if (*input == '\\') | |
227 { | |
228 bsquote = 1; | |
229 } | |
230 else if (squote) | |
231 { | |
232 if (*input == '\'') | |
233 { | |
234 squote = 0; | |
235 } | |
236 else | |
237 { | |
238 *arg++ = *input; | |
239 } | |
240 } | |
241 else if (dquote) | |
242 { | |
243 if (*input == '"') | |
244 { | |
245 dquote = 0; | |
246 } | |
247 else | |
248 { | |
249 *arg++ = *input; | |
250 } | |
251 } | |
252 else | |
253 { | |
254 if (*input == '\'') | |
255 { | |
256 squote = 1; | |
257 } | |
258 else if (*input == '"') | |
259 { | |
260 dquote = 1; | |
261 } | |
262 else | |
263 { | |
264 *arg++ = *input; | |
265 } | |
266 } | |
267 input++; | |
268 } | |
269 } | |
270 *arg = EOS; | |
271 argv[argc] = strdup (copybuf); | |
272 if (argv[argc] == NULL) | |
273 { | |
274 freeargv (argv); | |
275 argv = NULL; | |
276 break; | |
277 } | |
278 argc++; | |
279 argv[argc] = NULL; | |
280 | |
281 while (ISSPACE (*input)) | |
282 { | |
283 input++; | |
284 } | |
285 } | |
286 while (*input != EOS); | |
287 } | |
288 return (argv); | |
289 } | |
290 | |
291 /* | |
292 | |
293 @deftypefn Extension int writeargv (const char **@var{argv}, FILE *@var{file}) | |
294 | |
295 Write each member of ARGV, handling all necessary quoting, to the file | |
296 named by FILE, separated by whitespace. Return 0 on success, non-zero | |
297 if an error occurred while writing to FILE. | |
298 | |
299 @end deftypefn | |
300 | |
301 */ | |
302 | |
303 int | |
304 writeargv (char **argv, FILE *f) | |
305 { | |
306 int status = 0; | |
307 | |
308 if (f == NULL) | |
309 return 1; | |
310 | |
311 while (*argv != NULL) | |
312 { | |
313 const char *arg = *argv; | |
314 | |
315 while (*arg != EOS) | |
316 { | |
317 char c = *arg; | |
318 | |
319 if (ISSPACE(c) || c == '\\' || c == '\'' || c == '"') | |
320 if (EOF == fputc ('\\', f)) | |
321 { | |
322 status = 1; | |
323 goto done; | |
324 } | |
325 | |
326 if (EOF == fputc (c, f)) | |
327 { | |
328 status = 1; | |
329 goto done; | |
330 } | |
331 arg++; | |
332 } | |
333 | |
334 if (EOF == fputc ('\n', f)) | |
335 { | |
336 status = 1; | |
337 goto done; | |
338 } | |
339 argv++; | |
340 } | |
341 | |
342 done: | |
343 return status; | |
344 } | |
345 | |
346 /* | |
347 | |
348 @deftypefn Extension void expandargv (int *@var{argcp}, char ***@var{argvp}) | |
349 | |
350 The @var{argcp} and @code{argvp} arguments are pointers to the usual | |
351 @code{argc} and @code{argv} arguments to @code{main}. This function | |
352 looks for arguments that begin with the character @samp{@@}. Any such | |
353 arguments are interpreted as ``response files''. The contents of the | |
354 response file are interpreted as additional command line options. In | |
355 particular, the file is separated into whitespace-separated strings; | |
356 each such string is taken as a command-line option. The new options | |
357 are inserted in place of the option naming the response file, and | |
358 @code{*argcp} and @code{*argvp} will be updated. If the value of | |
359 @code{*argvp} is modified by this function, then the new value has | |
360 been dynamically allocated and can be deallocated by the caller with | |
361 @code{freeargv}. However, most callers will simply call | |
362 @code{expandargv} near the beginning of @code{main} and allow the | |
363 operating system to free the memory when the program exits. | |
364 | |
365 @end deftypefn | |
366 | |
367 */ | |
368 | |
369 void | |
370 expandargv (int *argcp, char ***argvp) | |
371 { | |
372 /* The argument we are currently processing. */ | |
373 int i = 0; | |
374 /* Non-zero if ***argvp has been dynamically allocated. */ | |
375 int argv_dynamic = 0; | |
376 /* Loop over the arguments, handling response files. We always skip | |
377 ARGVP[0], as that is the name of the program being run. */ | |
378 while (++i < *argcp) | |
379 { | |
380 /* The name of the response file. */ | |
381 const char *filename; | |
382 /* The response file. */ | |
383 FILE *f; | |
384 /* An upper bound on the number of characters in the response | |
385 file. */ | |
386 long pos; | |
387 /* The number of characters in the response file, when actually | |
388 read. */ | |
389 size_t len; | |
390 /* A dynamically allocated buffer used to hold options read from a | |
391 response file. */ | |
392 char *buffer; | |
393 /* Dynamically allocated storage for the options read from the | |
394 response file. */ | |
395 char **file_argv; | |
396 /* The number of options read from the response file, if any. */ | |
397 size_t file_argc; | |
398 /* We are only interested in options of the form "@file". */ | |
399 filename = (*argvp)[i]; | |
400 if (filename[0] != '@') | |
401 continue; | |
402 /* Read the contents of the file. */ | |
403 f = fopen (++filename, "r"); | |
404 if (!f) | |
405 continue; | |
406 if (fseek (f, 0L, SEEK_END) == -1) | |
407 goto error; | |
408 pos = ftell (f); | |
409 if (pos == -1) | |
410 goto error; | |
411 if (fseek (f, 0L, SEEK_SET) == -1) | |
412 goto error; | |
413 buffer = (char *) xmalloc (pos * sizeof (char) + 1); | |
414 len = fread (buffer, sizeof (char), pos, f); | |
415 if (len != (size_t) pos | |
416 /* On Windows, fread may return a value smaller than POS, | |
417 due to CR/LF->CR translation when reading text files. | |
418 That does not in-and-of itself indicate failure. */ | |
419 && ferror (f)) | |
420 goto error; | |
421 /* Add a NUL terminator. */ | |
422 buffer[len] = '\0'; | |
423 /* Parse the string. */ | |
424 file_argv = buildargv (buffer); | |
425 /* If *ARGVP is not already dynamically allocated, copy it. */ | |
426 if (!argv_dynamic) | |
427 { | |
428 *argvp = dupargv (*argvp); | |
429 if (!*argvp) | |
430 { | |
431 fputs ("\nout of memory\n", stderr); | |
432 xexit (1); | |
433 } | |
434 } | |
435 /* Count the number of arguments. */ | |
436 file_argc = 0; | |
437 while (file_argv[file_argc] && *file_argv[file_argc]) | |
438 ++file_argc; | |
439 /* Now, insert FILE_ARGV into ARGV. The "+1" below handles the | |
440 NULL terminator at the end of ARGV. */ | |
441 *argvp = ((char **) | |
442 xrealloc (*argvp, | |
443 (*argcp + file_argc + 1) * sizeof (char *))); | |
444 memmove (*argvp + i + file_argc, *argvp + i + 1, | |
445 (*argcp - i) * sizeof (char *)); | |
446 memcpy (*argvp + i, file_argv, file_argc * sizeof (char *)); | |
447 /* The original option has been replaced by all the new | |
448 options. */ | |
449 *argcp += file_argc - 1; | |
450 /* Free up memory allocated to process the response file. We do | |
451 not use freeargv because the individual options in FILE_ARGV | |
452 are now in the main ARGV. */ | |
453 free (file_argv); | |
454 free (buffer); | |
455 /* Rescan all of the arguments just read to support response | |
456 files that include other response files. */ | |
457 --i; | |
458 error: | |
459 /* We're all done with the file now. */ | |
460 fclose (f); | |
461 } | |
462 } | |
463 | |
464 #ifdef MAIN | |
465 | |
466 /* Simple little test driver. */ | |
467 | |
468 static const char *const tests[] = | |
469 { | |
470 "a simple command line", | |
471 "arg 'foo' is single quoted", | |
472 "arg \"bar\" is double quoted", | |
473 "arg \"foo bar\" has embedded whitespace", | |
474 "arg 'Jack said \\'hi\\'' has single quotes", | |
475 "arg 'Jack said \\\"hi\\\"' has double quotes", | |
476 "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", | |
477 | |
478 /* This should be expanded into only one argument. */ | |
479 "trailing-whitespace ", | |
480 | |
481 "", | |
482 NULL | |
483 }; | |
484 | |
485 int | |
486 main (void) | |
487 { | |
488 char **argv; | |
489 const char *const *test; | |
490 char **targs; | |
491 | |
492 for (test = tests; *test != NULL; test++) | |
493 { | |
494 printf ("buildargv(\"%s\")\n", *test); | |
495 if ((argv = buildargv (*test)) == NULL) | |
496 { | |
497 printf ("failed!\n\n"); | |
498 } | |
499 else | |
500 { | |
501 for (targs = argv; *targs != NULL; targs++) | |
502 { | |
503 printf ("\t\"%s\"\n", *targs); | |
504 } | |
505 printf ("\n"); | |
506 } | |
507 freeargv (argv); | |
508 } | |
509 | |
510 return 0; | |
511 } | |
512 | |
513 #endif /* MAIN */ |