1132451Sroberto/* Create and destroy argument vectors (argv's)
2132451Sroberto   Copyright (C) 1992, 2001, 2010 Free Software Foundation, Inc.
3132451Sroberto   Written by Fred Fish @ Cygnus Support
4132451Sroberto
5132451SrobertoThis file is part of the libiberty library.
6132451SrobertoLibiberty is free software; you can redistribute it and/or
7132451Srobertomodify it under the terms of the GNU Library General Public
8132451SrobertoLicense as published by the Free Software Foundation; either
9132451Srobertoversion 2 of the License, or (at your option) any later version.
10132451Sroberto
11132451SrobertoLibiberty is distributed in the hope that it will be useful,
12132451Srobertobut WITHOUT ANY WARRANTY; without even the implied warranty of
13132451SrobertoMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14132451SrobertoLibrary General Public License for more details.
15132451Sroberto
16132451SrobertoYou should have received a copy of the GNU Library General Public
17132451SrobertoLicense along with libiberty; see the file COPYING.LIB.  If
18132451Srobertonot, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
19132451SrobertoBoston, MA 02110-1301, USA.  */
20132451Sroberto
21132451Sroberto
22132451Sroberto/*  Create and destroy argument vectors.  An argument vector is simply an
23132451Sroberto    array of string pointers, terminated by a NULL pointer. */
24132451Sroberto
25132451Sroberto#ifdef HAVE_CONFIG_H
26132451Sroberto#include "config.h"
27132451Sroberto#endif
28132451Sroberto#include "ansidecl.h"
29132451Sroberto#include "libiberty.h"
30132451Sroberto#include "safe-ctype.h"
31132451Sroberto
32132451Sroberto/*  Routines imported from standard C runtime libraries. */
33132451Sroberto
34132451Sroberto#include <stddef.h>
35132451Sroberto#include <string.h>
36132451Sroberto#include <stdlib.h>
37132451Sroberto#include <stdio.h>
38132451Sroberto
39132451Sroberto#ifndef NULL
40132451Sroberto#define NULL 0
41132451Sroberto#endif
42132451Sroberto
43132451Sroberto#ifndef EOS
44132451Sroberto#define EOS '\0'
45132451Sroberto#endif
46132451Sroberto
47132451Sroberto#define INITIAL_MAXARGC 8	/* Number of args + NULL in initial argv */
48132451Sroberto
49132451Sroberto
50132451Sroberto/*
51132451Sroberto
52132451Sroberto@deftypefn Extension char** dupargv (char **@var{vector})
53132451Sroberto
54132451SrobertoDuplicate an argument vector.  Simply scans through @var{vector},
55132451Srobertoduplicating each argument until the terminating @code{NULL} is found.
56132451SrobertoReturns a pointer to the argument vector if successful.  Returns
57132451Sroberto@code{NULL} if there is insufficient memory to complete building the
58132451Srobertoargument vector.
59132451Sroberto
60132451Sroberto@end deftypefn
61132451Sroberto
62132451Sroberto*/
63132451Sroberto
64132451Srobertochar **
65132451Srobertodupargv (char **argv)
66132451Sroberto{
67132451Sroberto  int argc;
68132451Sroberto  char **copy;
69132451Sroberto
70132451Sroberto  if (argv == NULL)
71132451Sroberto    return NULL;
72132451Sroberto
73132451Sroberto  /* the vector */
74132451Sroberto  for (argc = 0; argv[argc] != NULL; argc++);
75132451Sroberto  copy = (char **) malloc ((argc + 1) * sizeof (char *));
76132451Sroberto  if (copy == NULL)
77132451Sroberto    return NULL;
78132451Sroberto
79132451Sroberto  /* the strings */
80132451Sroberto  for (argc = 0; argv[argc] != NULL; argc++)
81132451Sroberto    {
82132451Sroberto      int len = strlen (argv[argc]);
83132451Sroberto      copy[argc] = (char *) malloc (len + 1);
84132451Sroberto      if (copy[argc] == NULL)
85132451Sroberto	{
86132451Sroberto	  freeargv (copy);
87132451Sroberto	  return NULL;
88132451Sroberto	}
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
99Free an argument vector that was built using @code{buildargv}.  Simply
100scans through @var{vector}, freeing the memory for each argument until
101the terminating @code{NULL} is found, and then frees @var{vector}
102itself.
103
104@end deftypefn
105
106*/
107
108void 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
122static void
123consume_whitespace (const char **input)
124{
125  while (ISSPACE (**input))
126    {
127      (*input)++;
128    }
129}
130
131static int
132only_whitespace (const char* input)
133{
134  while (*input != EOS && ISSPACE (*input))
135    input++;
136
137  return (*input == EOS);
138}
139
140/*
141
142@deftypefn Extension char** buildargv (char *@var{sp})
143
144Given a pointer to a string, parse the string extracting fields
145separated by whitespace and optionally enclosed within either single
146or double quotes (which are stripped off), and build a vector of
147pointers to copies of the string for each field.  The input string
148remains unchanged.  The last element of the vector is followed by a
149@code{NULL} element.
150
151All of the memory for the pointer array and copies of the string
152is obtained from @code{malloc}.  All of the memory can be returned to the
153system with the single function call @code{freeargv}, which takes the
154returned result of @code{buildargv}, as it's argument.
155
156Returns a pointer to the argument vector if successful.  Returns
157@code{NULL} if @var{sp} is @code{NULL} or if there is insufficient
158memory to complete building the argument vector.
159
160If the input is a null string (as opposed to a @code{NULL} pointer),
161then buildarg returns an argument vector that has one arg, a null
162string.
163
164@end deftypefn
165
166The memory for the argv array is dynamically expanded as necessary.
167
168In order to provide a working buffer for extracting arguments into,
169with appropriate stripping of quotes and translation of backslash
170sequences, we allocate a working buffer at least as long as the input
171string.  This ensures that we always have enough space in which to
172work, since the extracted arg is never larger than the input string.
173
174The argument vector is always kept terminated with a @code{NULL} arg
175pointer, so it can be passed to @code{freeargv} at any time, or
176returned, as appropriate.
177
178*/
179
180char **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] */
200	  consume_whitespace (&input);
201
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
297	  consume_whitespace (&input);
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
308Write each member of ARGV, handling all necessary quoting, to the file
309named by FILE, separated by whitespace.  Return 0 on success, non-zero
310if an error occurred while writing to FILE.
311
312@end deftypefn
313
314*/
315
316int
317writeargv (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
363The @var{argcp} and @code{argvp} arguments are pointers to the usual
364@code{argc} and @code{argv} arguments to @code{main}.  This function
365looks for arguments that begin with the character @samp{@@}.  Any such
366arguments are interpreted as ``response files''.  The contents of the
367response file are interpreted as additional command line options.  In
368particular, the file is separated into whitespace-separated strings;
369each such string is taken as a command-line option.  The new options
370are 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
373been 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
376operating system to free the memory when the program exits.
377
378@end deftypefn
379
380*/
381
382void
383expandargv (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;
389  /* Limit the number of response files that we parse in order
390     to prevent infinite recursion.  */
391  unsigned int iteration_limit = 2000;
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;
418      /* If we have iterated too many times then stop.  */
419      if (-- iteration_limit == 0)
420	{
421	  fprintf (stderr, "%s: error: too many @-files encountered\n", (*argvp)[0]);
422	  xexit (1);
423	}
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';
445      /* If the file is empty or contains only whitespace, buildargv would
446	 return a single empty argument.  In this context we want no arguments,
447	 instead.  */
448      if (only_whitespace (buffer))
449	{
450	  file_argv = (char **) xmalloc (sizeof (char *));
451	  file_argv[0] = NULL;
452	}
453      else
454	/* Parse the string.  */
455	file_argv = buildargv (buffer);
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;
468      while (file_argv[file_argc])
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
499static 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
516int
517main (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 */
545