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