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
5This file is part of the libiberty library.
6Libiberty is free software; you can redistribute it and/or
7modify it under the terms of the GNU Library General Public
8License as published by the Free Software Foundation; either
9version 2 of the License, or (at your option) any later version.
10
11Libiberty is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14Library General Public License for more details.
15
16You should have received a copy of the GNU Library General Public
17License along with libiberty; see the file COPYING.LIB.  If
18not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
19Boston, 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
54Duplicate an argument vector.  Simply scans through @var{vector},
55duplicating each argument until the terminating @code{NULL} is found.
56Returns a pointer to the argument vector if successful.  Returns
57@code{NULL} if there is insufficient memory to complete building the
58argument vector.
59
60@end deftypefn
61
62*/
63
64char **
65dupargv (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
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
122/*
123
124@deftypefn Extension char** buildargv (char *@var{sp})
125
126Given a pointer to a string, parse the string extracting fields
127separated by whitespace and optionally enclosed within either single
128or double quotes (which are stripped off), and build a vector of
129pointers to copies of the string for each field.  The input string
130remains unchanged.  The last element of the vector is followed by a
131@code{NULL} element.
132
133All of the memory for the pointer array and copies of the string
134is obtained from @code{malloc}.  All of the memory can be returned to the
135system with the single function call @code{freeargv}, which takes the
136returned result of @code{buildargv}, as it's argument.
137
138Returns a pointer to the argument vector if successful.  Returns
139@code{NULL} if @var{sp} is @code{NULL} or if there is insufficient
140memory to complete building the argument vector.
141
142If the input is a null string (as opposed to a @code{NULL} pointer),
143then buildarg returns an argument vector that has one arg, a null
144string.
145
146@end deftypefn
147
148The memory for the argv array is dynamically expanded as necessary.
149
150In order to provide a working buffer for extracting arguments into,
151with appropriate stripping of quotes and translation of backslash
152sequences, we allocate a working buffer at least as long as the input
153string.  This ensures that we always have enough space in which to
154work, since the extracted arg is never larger than the input string.
155
156The argument vector is always kept terminated with a @code{NULL} arg
157pointer, so it can be passed to @code{freeargv} at any time, or
158returned, as appropriate.
159
160*/
161
162char **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 *@{file})
294
295Write each member of ARGV, handling all necessary quoting, to the file
296named by FILE, separated by whitespace.  Return 0 on success, non-zero
297if an error occurred while writing to FILE.
298
299@end deftypefn
300
301*/
302
303int
304writeargv (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
350The @var{argcp} and @code{argvp} arguments are pointers to the usual
351@code{argc} and @code{argv} arguments to @code{main}.  This function
352looks for arguments that begin with the character @samp{@@}.  Any such
353arguments are interpreted as ``response files''.  The contents of the
354response file are interpreted as additional command line options.  In
355particular, the file is separated into whitespace-separated strings;
356each such string is taken as a command-line option.  The new options
357are 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
360been 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
363operating system to free the memory when the program exits.
364
365@end deftypefn
366
367*/
368
369void
370expandargv (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
468static 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
485int
486main (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 */
514