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