100bf4279Sespie /* Create and destroy argument vectors (argv's)
237c53322Sespie Copyright (C) 1992, 2001 Free Software Foundation, Inc.
300bf4279Sespie Written by Fred Fish @ Cygnus Support
400bf4279Sespie
500bf4279Sespie This file is part of the libiberty library.
600bf4279Sespie Libiberty is free software; you can redistribute it and/or
700bf4279Sespie modify it under the terms of the GNU Library General Public
800bf4279Sespie License as published by the Free Software Foundation; either
900bf4279Sespie version 2 of the License, or (at your option) any later version.
1000bf4279Sespie
1100bf4279Sespie Libiberty is distributed in the hope that it will be useful,
1200bf4279Sespie but WITHOUT ANY WARRANTY; without even the implied warranty of
1300bf4279Sespie MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1400bf4279Sespie Library General Public License for more details.
1500bf4279Sespie
1600bf4279Sespie You should have received a copy of the GNU Library General Public
1700bf4279Sespie License along with libiberty; see the file COPYING.LIB. If
18150b7e42Smiod not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
19150b7e42Smiod Boston, MA 02110-1301, USA. */
2000bf4279Sespie
2100bf4279Sespie
2200bf4279Sespie /* Create and destroy argument vectors. An argument vector is simply an
2300bf4279Sespie array of string pointers, terminated by a NULL pointer. */
2400bf4279Sespie
25150b7e42Smiod #ifdef HAVE_CONFIG_H
26150b7e42Smiod #include "config.h"
27150b7e42Smiod #endif
2800bf4279Sespie #include "ansidecl.h"
2900bf4279Sespie #include "libiberty.h"
30150b7e42Smiod #include "safe-ctype.h"
3100bf4279Sespie
3200bf4279Sespie /* Routines imported from standard C runtime libraries. */
3300bf4279Sespie
3400bf4279Sespie #include <stddef.h>
3500bf4279Sespie #include <string.h>
3600bf4279Sespie #include <stdlib.h>
37150b7e42Smiod #include <stdio.h>
3800bf4279Sespie
3900bf4279Sespie #ifndef NULL
4000bf4279Sespie #define NULL 0
4100bf4279Sespie #endif
4200bf4279Sespie
4300bf4279Sespie #ifndef EOS
4400bf4279Sespie #define EOS '\0'
4500bf4279Sespie #endif
4600bf4279Sespie
4700bf4279Sespie #define INITIAL_MAXARGC 8 /* Number of args + NULL in initial argv */
4800bf4279Sespie
4900bf4279Sespie
5000bf4279Sespie /*
5100bf4279Sespie
5237c53322Sespie @deftypefn Extension char** dupargv (char **@var{vector})
5300bf4279Sespie
5437c53322Sespie Duplicate an argument vector. Simply scans through @var{vector},
5537c53322Sespie duplicating each argument until the terminating @code{NULL} is found.
5637c53322Sespie Returns a pointer to the argument vector if successful. Returns
5737c53322Sespie @code{NULL} if there is insufficient memory to complete building the
5837c53322Sespie argument vector.
5900bf4279Sespie
6037c53322Sespie @end deftypefn
6100bf4279Sespie
6200bf4279Sespie */
6300bf4279Sespie
6400bf4279Sespie char **
dupargv(char ** argv)65150b7e42Smiod dupargv (char **argv)
6600bf4279Sespie {
6700bf4279Sespie int argc;
6800bf4279Sespie char **copy;
6900bf4279Sespie
7000bf4279Sespie if (argv == NULL)
7100bf4279Sespie return NULL;
7200bf4279Sespie
7300bf4279Sespie /* the vector */
7400bf4279Sespie for (argc = 0; argv[argc] != NULL; argc++);
7500bf4279Sespie copy = (char **) malloc ((argc + 1) * sizeof (char *));
7600bf4279Sespie if (copy == NULL)
7700bf4279Sespie return NULL;
7800bf4279Sespie
7900bf4279Sespie /* the strings */
8000bf4279Sespie for (argc = 0; argv[argc] != NULL; argc++)
8100bf4279Sespie {
82*781be6a6Smiod copy[argc] = strdup (argv[argc]);
8300bf4279Sespie if (copy[argc] == NULL)
8400bf4279Sespie {
8500bf4279Sespie freeargv (copy);
8600bf4279Sespie return NULL;
8700bf4279Sespie }
8800bf4279Sespie }
8900bf4279Sespie copy[argc] = NULL;
9000bf4279Sespie return copy;
9100bf4279Sespie }
9200bf4279Sespie
9300bf4279Sespie /*
9400bf4279Sespie
9537c53322Sespie @deftypefn Extension void freeargv (char **@var{vector})
9600bf4279Sespie
9737c53322Sespie Free an argument vector that was built using @code{buildargv}. Simply
9837c53322Sespie scans through @var{vector}, freeing the memory for each argument until
9937c53322Sespie the terminating @code{NULL} is found, and then frees @var{vector}
10037c53322Sespie itself.
10100bf4279Sespie
10237c53322Sespie @end deftypefn
10300bf4279Sespie
10400bf4279Sespie */
10500bf4279Sespie
freeargv(char ** vector)106150b7e42Smiod void freeargv (char **vector)
10700bf4279Sespie {
10800bf4279Sespie register char **scan;
10900bf4279Sespie
11000bf4279Sespie if (vector != NULL)
11100bf4279Sespie {
11200bf4279Sespie for (scan = vector; *scan != NULL; scan++)
11300bf4279Sespie {
11400bf4279Sespie free (*scan);
11500bf4279Sespie }
11600bf4279Sespie free (vector);
11700bf4279Sespie }
11800bf4279Sespie }
11900bf4279Sespie
12000bf4279Sespie /*
12100bf4279Sespie
12237c53322Sespie @deftypefn Extension char** buildargv (char *@var{sp})
12300bf4279Sespie
12400bf4279Sespie Given a pointer to a string, parse the string extracting fields
12500bf4279Sespie separated by whitespace and optionally enclosed within either single
12600bf4279Sespie or double quotes (which are stripped off), and build a vector of
12700bf4279Sespie pointers to copies of the string for each field. The input string
12837c53322Sespie remains unchanged. The last element of the vector is followed by a
12937c53322Sespie @code{NULL} element.
13000bf4279Sespie
13100bf4279Sespie All of the memory for the pointer array and copies of the string
13237c53322Sespie is obtained from @code{malloc}. All of the memory can be returned to the
13337c53322Sespie system with the single function call @code{freeargv}, which takes the
13437c53322Sespie returned result of @code{buildargv}, as it's argument.
13500bf4279Sespie
13637c53322Sespie Returns a pointer to the argument vector if successful. Returns
13737c53322Sespie @code{NULL} if @var{sp} is @code{NULL} or if there is insufficient
13800bf4279Sespie memory to complete building the argument vector.
13900bf4279Sespie
14037c53322Sespie If the input is a null string (as opposed to a @code{NULL} pointer),
14137c53322Sespie then buildarg returns an argument vector that has one arg, a null
14237c53322Sespie string.
14337c53322Sespie
14437c53322Sespie @end deftypefn
14537c53322Sespie
14637c53322Sespie The memory for the argv array is dynamically expanded as necessary.
14700bf4279Sespie
14800bf4279Sespie In order to provide a working buffer for extracting arguments into,
14900bf4279Sespie with appropriate stripping of quotes and translation of backslash
15000bf4279Sespie sequences, we allocate a working buffer at least as long as the input
15100bf4279Sespie string. This ensures that we always have enough space in which to
15200bf4279Sespie work, since the extracted arg is never larger than the input string.
15300bf4279Sespie
15437c53322Sespie The argument vector is always kept terminated with a @code{NULL} arg
15537c53322Sespie pointer, so it can be passed to @code{freeargv} at any time, or
15637c53322Sespie returned, as appropriate.
15700bf4279Sespie
15800bf4279Sespie */
15900bf4279Sespie
buildargv(const char * input)160150b7e42Smiod char **buildargv (const char *input)
16100bf4279Sespie {
16200bf4279Sespie char *arg;
16300bf4279Sespie char *copybuf;
16400bf4279Sespie int squote = 0;
16500bf4279Sespie int dquote = 0;
16600bf4279Sespie int bsquote = 0;
16700bf4279Sespie int argc = 0;
16800bf4279Sespie int maxargc = 0;
16900bf4279Sespie char **argv = NULL;
17000bf4279Sespie char **nargv;
17100bf4279Sespie
17200bf4279Sespie if (input != NULL)
17300bf4279Sespie {
17400bf4279Sespie copybuf = (char *) alloca (strlen (input) + 1);
17500bf4279Sespie /* Is a do{}while to always execute the loop once. Always return an
17600bf4279Sespie argv, even for null strings. See NOTES above, test case below. */
17700bf4279Sespie do
17800bf4279Sespie {
17900bf4279Sespie /* Pick off argv[argc] */
180f5dd06f4Sespie while (ISBLANK (*input))
18100bf4279Sespie {
18200bf4279Sespie input++;
18300bf4279Sespie }
18400bf4279Sespie if ((maxargc == 0) || (argc >= (maxargc - 1)))
18500bf4279Sespie {
18600bf4279Sespie /* argv needs initialization, or expansion */
18700bf4279Sespie if (argv == NULL)
18800bf4279Sespie {
18900bf4279Sespie maxargc = INITIAL_MAXARGC;
19000bf4279Sespie nargv = (char **) malloc (maxargc * sizeof (char *));
19100bf4279Sespie }
19200bf4279Sespie else
19300bf4279Sespie {
19400bf4279Sespie maxargc *= 2;
19500bf4279Sespie nargv = (char **) realloc (argv, maxargc * sizeof (char *));
19600bf4279Sespie }
19700bf4279Sespie if (nargv == NULL)
19800bf4279Sespie {
19900bf4279Sespie if (argv != NULL)
20000bf4279Sespie {
20100bf4279Sespie freeargv (argv);
20200bf4279Sespie argv = NULL;
20300bf4279Sespie }
20400bf4279Sespie break;
20500bf4279Sespie }
20600bf4279Sespie argv = nargv;
20700bf4279Sespie argv[argc] = NULL;
20800bf4279Sespie }
20900bf4279Sespie /* Begin scanning arg */
21000bf4279Sespie arg = copybuf;
21100bf4279Sespie while (*input != EOS)
21200bf4279Sespie {
213150b7e42Smiod if (ISSPACE (*input) && !squote && !dquote && !bsquote)
21400bf4279Sespie {
21500bf4279Sespie break;
21600bf4279Sespie }
21700bf4279Sespie else
21800bf4279Sespie {
21900bf4279Sespie if (bsquote)
22000bf4279Sespie {
22100bf4279Sespie bsquote = 0;
22200bf4279Sespie *arg++ = *input;
22300bf4279Sespie }
22400bf4279Sespie else if (*input == '\\')
22500bf4279Sespie {
22600bf4279Sespie bsquote = 1;
22700bf4279Sespie }
22800bf4279Sespie else if (squote)
22900bf4279Sespie {
23000bf4279Sespie if (*input == '\'')
23100bf4279Sespie {
23200bf4279Sespie squote = 0;
23300bf4279Sespie }
23400bf4279Sespie else
23500bf4279Sespie {
23600bf4279Sespie *arg++ = *input;
23700bf4279Sespie }
23800bf4279Sespie }
23900bf4279Sespie else if (dquote)
24000bf4279Sespie {
24100bf4279Sespie if (*input == '"')
24200bf4279Sespie {
24300bf4279Sespie dquote = 0;
24400bf4279Sespie }
24500bf4279Sespie else
24600bf4279Sespie {
24700bf4279Sespie *arg++ = *input;
24800bf4279Sespie }
24900bf4279Sespie }
25000bf4279Sespie else
25100bf4279Sespie {
25200bf4279Sespie if (*input == '\'')
25300bf4279Sespie {
25400bf4279Sespie squote = 1;
25500bf4279Sespie }
25600bf4279Sespie else if (*input == '"')
25700bf4279Sespie {
25800bf4279Sespie dquote = 1;
25900bf4279Sespie }
26000bf4279Sespie else
26100bf4279Sespie {
26200bf4279Sespie *arg++ = *input;
26300bf4279Sespie }
26400bf4279Sespie }
26500bf4279Sespie input++;
26600bf4279Sespie }
26700bf4279Sespie }
26800bf4279Sespie *arg = EOS;
26900bf4279Sespie argv[argc] = strdup (copybuf);
27000bf4279Sespie if (argv[argc] == NULL)
27100bf4279Sespie {
27200bf4279Sespie freeargv (argv);
27300bf4279Sespie argv = NULL;
27400bf4279Sespie break;
27500bf4279Sespie }
27600bf4279Sespie argc++;
27700bf4279Sespie argv[argc] = NULL;
27800bf4279Sespie
279150b7e42Smiod while (ISSPACE (*input))
28000bf4279Sespie {
28100bf4279Sespie input++;
28200bf4279Sespie }
28300bf4279Sespie }
28400bf4279Sespie while (*input != EOS);
28500bf4279Sespie }
28600bf4279Sespie return (argv);
28700bf4279Sespie }
28800bf4279Sespie
289150b7e42Smiod /*
290150b7e42Smiod
291150b7e42Smiod @deftypefn Extension void expandargv (int *@var{argcp}, char ***@var{argvp})
292150b7e42Smiod
293150b7e42Smiod The @var{argcp} and @code{argvp} arguments are pointers to the usual
294150b7e42Smiod @code{argc} and @code{argv} arguments to @code{main}. This function
295150b7e42Smiod looks for arguments that begin with the character @samp{@@}. Any such
296150b7e42Smiod arguments are interpreted as ``response files''. The contents of the
297150b7e42Smiod response file are interpreted as additional command line options. In
298150b7e42Smiod particular, the file is separated into whitespace-separated strings;
299150b7e42Smiod each such string is taken as a command-line option. The new options
300150b7e42Smiod are inserted in place of the option naming the response file, and
301150b7e42Smiod @code{*argcp} and @code{*argvp} will be updated. If the value of
302150b7e42Smiod @code{*argvp} is modified by this function, then the new value has
303150b7e42Smiod been dynamically allocated and can be deallocated by the caller with
304150b7e42Smiod @code{freeargv}. However, most callers will simply call
305150b7e42Smiod @code{expandargv} near the beginning of @code{main} and allow the
306150b7e42Smiod operating system to free the memory when the program exits.
307150b7e42Smiod
308150b7e42Smiod @end deftypefn
309150b7e42Smiod
310150b7e42Smiod */
311150b7e42Smiod
312150b7e42Smiod void
expandargv(argcp,argvp)313150b7e42Smiod expandargv (argcp, argvp)
314150b7e42Smiod int *argcp;
315150b7e42Smiod char ***argvp;
316150b7e42Smiod {
317150b7e42Smiod /* The argument we are currently processing. */
318150b7e42Smiod int i = 0;
319150b7e42Smiod /* Non-zero if ***argvp has been dynamically allocated. */
320150b7e42Smiod int argv_dynamic = 0;
321150b7e42Smiod /* Loop over the arguments, handling response files. We always skip
322150b7e42Smiod ARGVP[0], as that is the name of the program being run. */
323150b7e42Smiod while (++i < *argcp)
324150b7e42Smiod {
325150b7e42Smiod /* The name of the response file. */
326150b7e42Smiod const char *filename;
327150b7e42Smiod /* The response file. */
328150b7e42Smiod FILE *f;
329150b7e42Smiod /* An upper bound on the number of characters in the response
330150b7e42Smiod file. */
331*781be6a6Smiod off_t pos;
332150b7e42Smiod /* The number of characters in the response file, when actually
333150b7e42Smiod read. */
334150b7e42Smiod size_t len;
335150b7e42Smiod /* A dynamically allocated buffer used to hold options read from a
336150b7e42Smiod response file. */
337150b7e42Smiod char *buffer;
338150b7e42Smiod /* Dynamically allocated storage for the options read from the
339150b7e42Smiod response file. */
340150b7e42Smiod char **file_argv;
341150b7e42Smiod /* The number of options read from the response file, if any. */
342150b7e42Smiod size_t file_argc;
343150b7e42Smiod /* We are only interested in options of the form "@file". */
344150b7e42Smiod filename = (*argvp)[i];
345150b7e42Smiod if (filename[0] != '@')
346150b7e42Smiod continue;
347150b7e42Smiod /* Read the contents of the file. */
348150b7e42Smiod f = fopen (++filename, "r");
349150b7e42Smiod if (!f)
350150b7e42Smiod continue;
351150b7e42Smiod if (fseek (f, 0L, SEEK_END) == -1)
352150b7e42Smiod goto error;
353*781be6a6Smiod pos = ftello (f);
354150b7e42Smiod if (pos == -1)
355150b7e42Smiod goto error;
356150b7e42Smiod if (fseek (f, 0L, SEEK_SET) == -1)
357150b7e42Smiod goto error;
358150b7e42Smiod buffer = (char *) xmalloc (pos * sizeof (char) + 1);
359150b7e42Smiod len = fread (buffer, sizeof (char), pos, f);
360150b7e42Smiod if (len != (size_t) pos
361150b7e42Smiod /* On Windows, fread may return a value smaller than POS,
362150b7e42Smiod due to CR/LF->CR translation when reading text files.
363150b7e42Smiod That does not in-and-of itself indicate failure. */
364150b7e42Smiod && ferror (f))
365150b7e42Smiod goto error;
366150b7e42Smiod /* Add a NUL terminator. */
367150b7e42Smiod buffer[len] = '\0';
368150b7e42Smiod /* Parse the string. */
369150b7e42Smiod file_argv = buildargv (buffer);
370150b7e42Smiod /* If *ARGVP is not already dynamically allocated, copy it. */
371150b7e42Smiod if (!argv_dynamic)
372150b7e42Smiod {
373150b7e42Smiod *argvp = dupargv (*argvp);
374150b7e42Smiod if (!*argvp)
375150b7e42Smiod {
376150b7e42Smiod fputs ("\nout of memory\n", stderr);
377150b7e42Smiod xexit (1);
378150b7e42Smiod }
379150b7e42Smiod }
380150b7e42Smiod /* Count the number of arguments. */
381150b7e42Smiod file_argc = 0;
382150b7e42Smiod while (file_argv[file_argc] && *file_argv[file_argc])
383150b7e42Smiod ++file_argc;
384150b7e42Smiod /* Now, insert FILE_ARGV into ARGV. The "+1" below handles the
385150b7e42Smiod NULL terminator at the end of ARGV. */
386150b7e42Smiod *argvp = ((char **)
387150b7e42Smiod xrealloc (*argvp,
388150b7e42Smiod (*argcp + file_argc + 1) * sizeof (char *)));
389150b7e42Smiod memmove (*argvp + i + file_argc, *argvp + i + 1,
390150b7e42Smiod (*argcp - i) * sizeof (char *));
391150b7e42Smiod memcpy (*argvp + i, file_argv, file_argc * sizeof (char *));
392150b7e42Smiod /* The original option has been replaced by all the new
393150b7e42Smiod options. */
394150b7e42Smiod *argcp += file_argc - 1;
395150b7e42Smiod /* Free up memory allocated to process the response file. We do
396150b7e42Smiod not use freeargv because the individual options in FILE_ARGV
397150b7e42Smiod are now in the main ARGV. */
398150b7e42Smiod free (file_argv);
399150b7e42Smiod free (buffer);
400150b7e42Smiod /* Rescan all of the arguments just read to support response
401150b7e42Smiod files that include other response files. */
402150b7e42Smiod --i;
403150b7e42Smiod error:
404150b7e42Smiod /* We're all done with the file now. */
405150b7e42Smiod fclose (f);
406150b7e42Smiod }
407150b7e42Smiod }
408150b7e42Smiod
40900bf4279Sespie #ifdef MAIN
41000bf4279Sespie
41100bf4279Sespie /* Simple little test driver. */
41200bf4279Sespie
41337c53322Sespie static const char *const tests[] =
41400bf4279Sespie {
41500bf4279Sespie "a simple command line",
41600bf4279Sespie "arg 'foo' is single quoted",
41700bf4279Sespie "arg \"bar\" is double quoted",
41800bf4279Sespie "arg \"foo bar\" has embedded whitespace",
41900bf4279Sespie "arg 'Jack said \\'hi\\'' has single quotes",
42000bf4279Sespie "arg 'Jack said \\\"hi\\\"' has double quotes",
42100bf4279Sespie "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",
42200bf4279Sespie
42300bf4279Sespie /* This should be expanded into only one argument. */
42400bf4279Sespie "trailing-whitespace ",
42500bf4279Sespie
42600bf4279Sespie "",
42700bf4279Sespie NULL
42800bf4279Sespie };
42900bf4279Sespie
430150b7e42Smiod int
main(void)431150b7e42Smiod main (void)
43200bf4279Sespie {
43300bf4279Sespie char **argv;
43437c53322Sespie const char *const *test;
43500bf4279Sespie char **targs;
43600bf4279Sespie
43700bf4279Sespie for (test = tests; *test != NULL; test++)
43800bf4279Sespie {
43900bf4279Sespie printf ("buildargv(\"%s\")\n", *test);
44000bf4279Sespie if ((argv = buildargv (*test)) == NULL)
44100bf4279Sespie {
44200bf4279Sespie printf ("failed!\n\n");
44300bf4279Sespie }
44400bf4279Sespie else
44500bf4279Sespie {
44600bf4279Sespie for (targs = argv; *targs != NULL; targs++)
44700bf4279Sespie {
44800bf4279Sespie printf ("\t\"%s\"\n", *targs);
44900bf4279Sespie }
45000bf4279Sespie printf ("\n");
45100bf4279Sespie }
45200bf4279Sespie freeargv (argv);
45300bf4279Sespie }
45400bf4279Sespie
45537c53322Sespie return 0;
45600bf4279Sespie }
45700bf4279Sespie
45800bf4279Sespie #endif /* MAIN */
459