xref: /dflybsd-src/contrib/gdb-7/libiberty/argv.c (revision de8e141f24382815c10a4012d209bbbf7abf1112)
15796c8dcSSimon Schubert /* Create and destroy argument vectors (argv's)
2*ef5ccd6cSJohn Marino    Copyright (C) 1992, 2001, 2010, 2012 Free Software Foundation, Inc.
35796c8dcSSimon Schubert    Written by Fred Fish @ Cygnus Support
45796c8dcSSimon Schubert 
55796c8dcSSimon Schubert This file is part of the libiberty library.
65796c8dcSSimon Schubert Libiberty is free software; you can redistribute it and/or
75796c8dcSSimon Schubert modify it under the terms of the GNU Library General Public
85796c8dcSSimon Schubert License as published by the Free Software Foundation; either
95796c8dcSSimon Schubert version 2 of the License, or (at your option) any later version.
105796c8dcSSimon Schubert 
115796c8dcSSimon Schubert Libiberty is distributed in the hope that it will be useful,
125796c8dcSSimon Schubert but WITHOUT ANY WARRANTY; without even the implied warranty of
135796c8dcSSimon Schubert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
145796c8dcSSimon Schubert Library General Public License for more details.
155796c8dcSSimon Schubert 
165796c8dcSSimon Schubert You should have received a copy of the GNU Library General Public
175796c8dcSSimon Schubert License along with libiberty; see the file COPYING.LIB.  If
185796c8dcSSimon Schubert not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
195796c8dcSSimon Schubert Boston, MA 02110-1301, USA.  */
205796c8dcSSimon Schubert 
215796c8dcSSimon Schubert 
225796c8dcSSimon Schubert /*  Create and destroy argument vectors.  An argument vector is simply an
235796c8dcSSimon Schubert     array of string pointers, terminated by a NULL pointer. */
245796c8dcSSimon Schubert 
255796c8dcSSimon Schubert #ifdef HAVE_CONFIG_H
265796c8dcSSimon Schubert #include "config.h"
275796c8dcSSimon Schubert #endif
285796c8dcSSimon Schubert #include "ansidecl.h"
295796c8dcSSimon Schubert #include "libiberty.h"
305796c8dcSSimon Schubert #include "safe-ctype.h"
315796c8dcSSimon Schubert 
325796c8dcSSimon Schubert /*  Routines imported from standard C runtime libraries. */
335796c8dcSSimon Schubert 
345796c8dcSSimon Schubert #include <stddef.h>
355796c8dcSSimon Schubert #include <string.h>
365796c8dcSSimon Schubert #include <stdlib.h>
375796c8dcSSimon Schubert #include <stdio.h>
385796c8dcSSimon Schubert 
395796c8dcSSimon Schubert #ifndef NULL
405796c8dcSSimon Schubert #define NULL 0
415796c8dcSSimon Schubert #endif
425796c8dcSSimon Schubert 
435796c8dcSSimon Schubert #ifndef EOS
445796c8dcSSimon Schubert #define EOS '\0'
455796c8dcSSimon Schubert #endif
465796c8dcSSimon Schubert 
475796c8dcSSimon Schubert #define INITIAL_MAXARGC 8	/* Number of args + NULL in initial argv */
485796c8dcSSimon Schubert 
495796c8dcSSimon Schubert 
505796c8dcSSimon Schubert /*
515796c8dcSSimon Schubert 
525796c8dcSSimon Schubert @deftypefn Extension char** dupargv (char **@var{vector})
535796c8dcSSimon Schubert 
545796c8dcSSimon Schubert Duplicate an argument vector.  Simply scans through @var{vector},
555796c8dcSSimon Schubert duplicating each argument until the terminating @code{NULL} is found.
565796c8dcSSimon Schubert Returns a pointer to the argument vector if successful.  Returns
575796c8dcSSimon Schubert @code{NULL} if there is insufficient memory to complete building the
585796c8dcSSimon Schubert argument vector.
595796c8dcSSimon Schubert 
605796c8dcSSimon Schubert @end deftypefn
615796c8dcSSimon Schubert 
625796c8dcSSimon Schubert */
635796c8dcSSimon Schubert 
645796c8dcSSimon Schubert char **
dupargv(char ** argv)655796c8dcSSimon Schubert dupargv (char **argv)
665796c8dcSSimon Schubert {
675796c8dcSSimon Schubert   int argc;
685796c8dcSSimon Schubert   char **copy;
695796c8dcSSimon Schubert 
705796c8dcSSimon Schubert   if (argv == NULL)
715796c8dcSSimon Schubert     return NULL;
725796c8dcSSimon Schubert 
735796c8dcSSimon Schubert   /* the vector */
745796c8dcSSimon Schubert   for (argc = 0; argv[argc] != NULL; argc++);
75*ef5ccd6cSJohn Marino   copy = (char **) xmalloc ((argc + 1) * sizeof (char *));
765796c8dcSSimon Schubert 
775796c8dcSSimon Schubert   /* the strings */
785796c8dcSSimon Schubert   for (argc = 0; argv[argc] != NULL; argc++)
795796c8dcSSimon Schubert     {
805796c8dcSSimon Schubert       int len = strlen (argv[argc]);
81*ef5ccd6cSJohn Marino       copy[argc] = (char *) xmalloc (len + 1);
825796c8dcSSimon Schubert       strcpy (copy[argc], argv[argc]);
835796c8dcSSimon Schubert     }
845796c8dcSSimon Schubert   copy[argc] = NULL;
855796c8dcSSimon Schubert   return copy;
865796c8dcSSimon Schubert }
875796c8dcSSimon Schubert 
885796c8dcSSimon Schubert /*
895796c8dcSSimon Schubert 
905796c8dcSSimon Schubert @deftypefn Extension void freeargv (char **@var{vector})
915796c8dcSSimon Schubert 
925796c8dcSSimon Schubert Free an argument vector that was built using @code{buildargv}.  Simply
935796c8dcSSimon Schubert scans through @var{vector}, freeing the memory for each argument until
945796c8dcSSimon Schubert the terminating @code{NULL} is found, and then frees @var{vector}
955796c8dcSSimon Schubert itself.
965796c8dcSSimon Schubert 
975796c8dcSSimon Schubert @end deftypefn
985796c8dcSSimon Schubert 
995796c8dcSSimon Schubert */
1005796c8dcSSimon Schubert 
freeargv(char ** vector)1015796c8dcSSimon Schubert void freeargv (char **vector)
1025796c8dcSSimon Schubert {
1035796c8dcSSimon Schubert   register char **scan;
1045796c8dcSSimon Schubert 
1055796c8dcSSimon Schubert   if (vector != NULL)
1065796c8dcSSimon Schubert     {
1075796c8dcSSimon Schubert       for (scan = vector; *scan != NULL; scan++)
1085796c8dcSSimon Schubert 	{
1095796c8dcSSimon Schubert 	  free (*scan);
1105796c8dcSSimon Schubert 	}
1115796c8dcSSimon Schubert       free (vector);
1125796c8dcSSimon Schubert     }
1135796c8dcSSimon Schubert }
1145796c8dcSSimon Schubert 
115cf7f2e2dSJohn Marino static void
consume_whitespace(const char ** input)116cf7f2e2dSJohn Marino consume_whitespace (const char **input)
117cf7f2e2dSJohn Marino {
118cf7f2e2dSJohn Marino   while (ISSPACE (**input))
119cf7f2e2dSJohn Marino     {
120cf7f2e2dSJohn Marino       (*input)++;
121cf7f2e2dSJohn Marino     }
122cf7f2e2dSJohn Marino }
123cf7f2e2dSJohn Marino 
124cf7f2e2dSJohn Marino static int
only_whitespace(const char * input)125cf7f2e2dSJohn Marino only_whitespace (const char* input)
126cf7f2e2dSJohn Marino {
127cf7f2e2dSJohn Marino   while (*input != EOS && ISSPACE (*input))
128cf7f2e2dSJohn Marino     input++;
129cf7f2e2dSJohn Marino 
130cf7f2e2dSJohn Marino   return (*input == EOS);
131cf7f2e2dSJohn Marino }
132cf7f2e2dSJohn Marino 
1335796c8dcSSimon Schubert /*
1345796c8dcSSimon Schubert 
1355796c8dcSSimon Schubert @deftypefn Extension char** buildargv (char *@var{sp})
1365796c8dcSSimon Schubert 
1375796c8dcSSimon Schubert Given a pointer to a string, parse the string extracting fields
1385796c8dcSSimon Schubert separated by whitespace and optionally enclosed within either single
1395796c8dcSSimon Schubert or double quotes (which are stripped off), and build a vector of
1405796c8dcSSimon Schubert pointers to copies of the string for each field.  The input string
1415796c8dcSSimon Schubert remains unchanged.  The last element of the vector is followed by a
1425796c8dcSSimon Schubert @code{NULL} element.
1435796c8dcSSimon Schubert 
1445796c8dcSSimon Schubert All of the memory for the pointer array and copies of the string
145*ef5ccd6cSJohn Marino is obtained from @code{xmalloc}.  All of the memory can be returned to the
1465796c8dcSSimon Schubert system with the single function call @code{freeargv}, which takes the
1475796c8dcSSimon Schubert returned result of @code{buildargv}, as it's argument.
1485796c8dcSSimon Schubert 
1495796c8dcSSimon Schubert Returns a pointer to the argument vector if successful.  Returns
1505796c8dcSSimon Schubert @code{NULL} if @var{sp} is @code{NULL} or if there is insufficient
1515796c8dcSSimon Schubert memory to complete building the argument vector.
1525796c8dcSSimon Schubert 
1535796c8dcSSimon Schubert If the input is a null string (as opposed to a @code{NULL} pointer),
1545796c8dcSSimon Schubert then buildarg returns an argument vector that has one arg, a null
1555796c8dcSSimon Schubert string.
1565796c8dcSSimon Schubert 
1575796c8dcSSimon Schubert @end deftypefn
1585796c8dcSSimon Schubert 
1595796c8dcSSimon Schubert The memory for the argv array is dynamically expanded as necessary.
1605796c8dcSSimon Schubert 
1615796c8dcSSimon Schubert In order to provide a working buffer for extracting arguments into,
1625796c8dcSSimon Schubert with appropriate stripping of quotes and translation of backslash
1635796c8dcSSimon Schubert sequences, we allocate a working buffer at least as long as the input
1645796c8dcSSimon Schubert string.  This ensures that we always have enough space in which to
1655796c8dcSSimon Schubert work, since the extracted arg is never larger than the input string.
1665796c8dcSSimon Schubert 
1675796c8dcSSimon Schubert The argument vector is always kept terminated with a @code{NULL} arg
1685796c8dcSSimon Schubert pointer, so it can be passed to @code{freeargv} at any time, or
1695796c8dcSSimon Schubert returned, as appropriate.
1705796c8dcSSimon Schubert 
1715796c8dcSSimon Schubert */
1725796c8dcSSimon Schubert 
buildargv(const char * input)1735796c8dcSSimon Schubert char **buildargv (const char *input)
1745796c8dcSSimon Schubert {
1755796c8dcSSimon Schubert   char *arg;
1765796c8dcSSimon Schubert   char *copybuf;
1775796c8dcSSimon Schubert   int squote = 0;
1785796c8dcSSimon Schubert   int dquote = 0;
1795796c8dcSSimon Schubert   int bsquote = 0;
1805796c8dcSSimon Schubert   int argc = 0;
1815796c8dcSSimon Schubert   int maxargc = 0;
1825796c8dcSSimon Schubert   char **argv = NULL;
1835796c8dcSSimon Schubert   char **nargv;
1845796c8dcSSimon Schubert 
1855796c8dcSSimon Schubert   if (input != NULL)
1865796c8dcSSimon Schubert     {
187*ef5ccd6cSJohn Marino       copybuf = (char *) xmalloc (strlen (input) + 1);
1885796c8dcSSimon Schubert       /* Is a do{}while to always execute the loop once.  Always return an
1895796c8dcSSimon Schubert 	 argv, even for null strings.  See NOTES above, test case below. */
1905796c8dcSSimon Schubert       do
1915796c8dcSSimon Schubert 	{
1925796c8dcSSimon Schubert 	  /* Pick off argv[argc] */
193cf7f2e2dSJohn Marino 	  consume_whitespace (&input);
194cf7f2e2dSJohn Marino 
1955796c8dcSSimon Schubert 	  if ((maxargc == 0) || (argc >= (maxargc - 1)))
1965796c8dcSSimon Schubert 	    {
1975796c8dcSSimon Schubert 	      /* argv needs initialization, or expansion */
1985796c8dcSSimon Schubert 	      if (argv == NULL)
1995796c8dcSSimon Schubert 		{
2005796c8dcSSimon Schubert 		  maxargc = INITIAL_MAXARGC;
201*ef5ccd6cSJohn Marino 		  nargv = (char **) xmalloc (maxargc * sizeof (char *));
2025796c8dcSSimon Schubert 		}
2035796c8dcSSimon Schubert 	      else
2045796c8dcSSimon Schubert 		{
2055796c8dcSSimon Schubert 		  maxargc *= 2;
206*ef5ccd6cSJohn Marino 		  nargv = (char **) xrealloc (argv, maxargc * sizeof (char *));
2075796c8dcSSimon Schubert 		}
2085796c8dcSSimon Schubert 	      argv = nargv;
2095796c8dcSSimon Schubert 	      argv[argc] = NULL;
2105796c8dcSSimon Schubert 	    }
2115796c8dcSSimon Schubert 	  /* Begin scanning arg */
2125796c8dcSSimon Schubert 	  arg = copybuf;
2135796c8dcSSimon Schubert 	  while (*input != EOS)
2145796c8dcSSimon Schubert 	    {
2155796c8dcSSimon Schubert 	      if (ISSPACE (*input) && !squote && !dquote && !bsquote)
2165796c8dcSSimon Schubert 		{
2175796c8dcSSimon Schubert 		  break;
2185796c8dcSSimon Schubert 		}
2195796c8dcSSimon Schubert 	      else
2205796c8dcSSimon Schubert 		{
2215796c8dcSSimon Schubert 		  if (bsquote)
2225796c8dcSSimon Schubert 		    {
2235796c8dcSSimon Schubert 		      bsquote = 0;
2245796c8dcSSimon Schubert 		      *arg++ = *input;
2255796c8dcSSimon Schubert 		    }
2265796c8dcSSimon Schubert 		  else if (*input == '\\')
2275796c8dcSSimon Schubert 		    {
2285796c8dcSSimon Schubert 		      bsquote = 1;
2295796c8dcSSimon Schubert 		    }
2305796c8dcSSimon Schubert 		  else if (squote)
2315796c8dcSSimon Schubert 		    {
2325796c8dcSSimon Schubert 		      if (*input == '\'')
2335796c8dcSSimon Schubert 			{
2345796c8dcSSimon Schubert 			  squote = 0;
2355796c8dcSSimon Schubert 			}
2365796c8dcSSimon Schubert 		      else
2375796c8dcSSimon Schubert 			{
2385796c8dcSSimon Schubert 			  *arg++ = *input;
2395796c8dcSSimon Schubert 			}
2405796c8dcSSimon Schubert 		    }
2415796c8dcSSimon Schubert 		  else if (dquote)
2425796c8dcSSimon Schubert 		    {
2435796c8dcSSimon Schubert 		      if (*input == '"')
2445796c8dcSSimon Schubert 			{
2455796c8dcSSimon Schubert 			  dquote = 0;
2465796c8dcSSimon Schubert 			}
2475796c8dcSSimon Schubert 		      else
2485796c8dcSSimon Schubert 			{
2495796c8dcSSimon Schubert 			  *arg++ = *input;
2505796c8dcSSimon Schubert 			}
2515796c8dcSSimon Schubert 		    }
2525796c8dcSSimon Schubert 		  else
2535796c8dcSSimon Schubert 		    {
2545796c8dcSSimon Schubert 		      if (*input == '\'')
2555796c8dcSSimon Schubert 			{
2565796c8dcSSimon Schubert 			  squote = 1;
2575796c8dcSSimon Schubert 			}
2585796c8dcSSimon Schubert 		      else if (*input == '"')
2595796c8dcSSimon Schubert 			{
2605796c8dcSSimon Schubert 			  dquote = 1;
2615796c8dcSSimon Schubert 			}
2625796c8dcSSimon Schubert 		      else
2635796c8dcSSimon Schubert 			{
2645796c8dcSSimon Schubert 			  *arg++ = *input;
2655796c8dcSSimon Schubert 			}
2665796c8dcSSimon Schubert 		    }
2675796c8dcSSimon Schubert 		  input++;
2685796c8dcSSimon Schubert 		}
2695796c8dcSSimon Schubert 	    }
2705796c8dcSSimon Schubert 	  *arg = EOS;
271*ef5ccd6cSJohn Marino 	  argv[argc] = xstrdup (copybuf);
2725796c8dcSSimon Schubert 	  argc++;
2735796c8dcSSimon Schubert 	  argv[argc] = NULL;
2745796c8dcSSimon Schubert 
275cf7f2e2dSJohn Marino 	  consume_whitespace (&input);
2765796c8dcSSimon Schubert 	}
2775796c8dcSSimon Schubert       while (*input != EOS);
278*ef5ccd6cSJohn Marino 
279*ef5ccd6cSJohn Marino       free (copybuf);
2805796c8dcSSimon Schubert     }
2815796c8dcSSimon Schubert   return (argv);
2825796c8dcSSimon Schubert }
2835796c8dcSSimon Schubert 
2845796c8dcSSimon Schubert /*
2855796c8dcSSimon Schubert 
2865796c8dcSSimon Schubert @deftypefn Extension int writeargv (const char **@var{argv}, FILE *@var{file})
2875796c8dcSSimon Schubert 
2885796c8dcSSimon Schubert Write each member of ARGV, handling all necessary quoting, to the file
2895796c8dcSSimon Schubert named by FILE, separated by whitespace.  Return 0 on success, non-zero
2905796c8dcSSimon Schubert if an error occurred while writing to FILE.
2915796c8dcSSimon Schubert 
2925796c8dcSSimon Schubert @end deftypefn
2935796c8dcSSimon Schubert 
2945796c8dcSSimon Schubert */
2955796c8dcSSimon Schubert 
2965796c8dcSSimon Schubert int
writeargv(char ** argv,FILE * f)2975796c8dcSSimon Schubert writeargv (char **argv, FILE *f)
2985796c8dcSSimon Schubert {
2995796c8dcSSimon Schubert   int status = 0;
3005796c8dcSSimon Schubert 
3015796c8dcSSimon Schubert   if (f == NULL)
3025796c8dcSSimon Schubert     return 1;
3035796c8dcSSimon Schubert 
3045796c8dcSSimon Schubert   while (*argv != NULL)
3055796c8dcSSimon Schubert     {
3065796c8dcSSimon Schubert       const char *arg = *argv;
3075796c8dcSSimon Schubert 
3085796c8dcSSimon Schubert       while (*arg != EOS)
3095796c8dcSSimon Schubert         {
3105796c8dcSSimon Schubert           char c = *arg;
3115796c8dcSSimon Schubert 
3125796c8dcSSimon Schubert           if (ISSPACE(c) || c == '\\' || c == '\'' || c == '"')
3135796c8dcSSimon Schubert             if (EOF == fputc ('\\', f))
3145796c8dcSSimon Schubert               {
3155796c8dcSSimon Schubert                 status = 1;
3165796c8dcSSimon Schubert                 goto done;
3175796c8dcSSimon Schubert               }
3185796c8dcSSimon Schubert 
3195796c8dcSSimon Schubert           if (EOF == fputc (c, f))
3205796c8dcSSimon Schubert             {
3215796c8dcSSimon Schubert               status = 1;
3225796c8dcSSimon Schubert               goto done;
3235796c8dcSSimon Schubert             }
3245796c8dcSSimon Schubert           arg++;
3255796c8dcSSimon Schubert         }
3265796c8dcSSimon Schubert 
3275796c8dcSSimon Schubert       if (EOF == fputc ('\n', f))
3285796c8dcSSimon Schubert         {
3295796c8dcSSimon Schubert           status = 1;
3305796c8dcSSimon Schubert           goto done;
3315796c8dcSSimon Schubert         }
3325796c8dcSSimon Schubert       argv++;
3335796c8dcSSimon Schubert     }
3345796c8dcSSimon Schubert 
3355796c8dcSSimon Schubert  done:
3365796c8dcSSimon Schubert   return status;
3375796c8dcSSimon Schubert }
3385796c8dcSSimon Schubert 
3395796c8dcSSimon Schubert /*
3405796c8dcSSimon Schubert 
3415796c8dcSSimon Schubert @deftypefn Extension void expandargv (int *@var{argcp}, char ***@var{argvp})
3425796c8dcSSimon Schubert 
3435796c8dcSSimon Schubert The @var{argcp} and @code{argvp} arguments are pointers to the usual
3445796c8dcSSimon Schubert @code{argc} and @code{argv} arguments to @code{main}.  This function
3455796c8dcSSimon Schubert looks for arguments that begin with the character @samp{@@}.  Any such
3465796c8dcSSimon Schubert arguments are interpreted as ``response files''.  The contents of the
3475796c8dcSSimon Schubert response file are interpreted as additional command line options.  In
3485796c8dcSSimon Schubert particular, the file is separated into whitespace-separated strings;
3495796c8dcSSimon Schubert each such string is taken as a command-line option.  The new options
3505796c8dcSSimon Schubert are inserted in place of the option naming the response file, and
3515796c8dcSSimon Schubert @code{*argcp} and @code{*argvp} will be updated.  If the value of
3525796c8dcSSimon Schubert @code{*argvp} is modified by this function, then the new value has
3535796c8dcSSimon Schubert been dynamically allocated and can be deallocated by the caller with
3545796c8dcSSimon Schubert @code{freeargv}.  However, most callers will simply call
3555796c8dcSSimon Schubert @code{expandargv} near the beginning of @code{main} and allow the
3565796c8dcSSimon Schubert operating system to free the memory when the program exits.
3575796c8dcSSimon Schubert 
3585796c8dcSSimon Schubert @end deftypefn
3595796c8dcSSimon Schubert 
3605796c8dcSSimon Schubert */
3615796c8dcSSimon Schubert 
3625796c8dcSSimon Schubert void
expandargv(int * argcp,char *** argvp)3635796c8dcSSimon Schubert expandargv (int *argcp, char ***argvp)
3645796c8dcSSimon Schubert {
3655796c8dcSSimon Schubert   /* The argument we are currently processing.  */
3665796c8dcSSimon Schubert   int i = 0;
3675796c8dcSSimon Schubert   /* Non-zero if ***argvp has been dynamically allocated.  */
3685796c8dcSSimon Schubert   int argv_dynamic = 0;
369c50c785cSJohn Marino   /* Limit the number of response files that we parse in order
370c50c785cSJohn Marino      to prevent infinite recursion.  */
371c50c785cSJohn Marino   unsigned int iteration_limit = 2000;
3725796c8dcSSimon Schubert   /* Loop over the arguments, handling response files.  We always skip
3735796c8dcSSimon Schubert      ARGVP[0], as that is the name of the program being run.  */
3745796c8dcSSimon Schubert   while (++i < *argcp)
3755796c8dcSSimon Schubert     {
3765796c8dcSSimon Schubert       /* The name of the response file.  */
3775796c8dcSSimon Schubert       const char *filename;
3785796c8dcSSimon Schubert       /* The response file.  */
3795796c8dcSSimon Schubert       FILE *f;
3805796c8dcSSimon Schubert       /* An upper bound on the number of characters in the response
3815796c8dcSSimon Schubert 	 file.  */
3825796c8dcSSimon Schubert       long pos;
3835796c8dcSSimon Schubert       /* The number of characters in the response file, when actually
3845796c8dcSSimon Schubert 	 read.  */
3855796c8dcSSimon Schubert       size_t len;
3865796c8dcSSimon Schubert       /* A dynamically allocated buffer used to hold options read from a
3875796c8dcSSimon Schubert 	 response file.  */
3885796c8dcSSimon Schubert       char *buffer;
3895796c8dcSSimon Schubert       /* Dynamically allocated storage for the options read from the
3905796c8dcSSimon Schubert 	 response file.  */
3915796c8dcSSimon Schubert       char **file_argv;
3925796c8dcSSimon Schubert       /* The number of options read from the response file, if any.  */
3935796c8dcSSimon Schubert       size_t file_argc;
3945796c8dcSSimon Schubert       /* We are only interested in options of the form "@file".  */
3955796c8dcSSimon Schubert       filename = (*argvp)[i];
3965796c8dcSSimon Schubert       if (filename[0] != '@')
3975796c8dcSSimon Schubert 	continue;
398c50c785cSJohn Marino       /* If we have iterated too many times then stop.  */
399c50c785cSJohn Marino       if (-- iteration_limit == 0)
400c50c785cSJohn Marino 	{
401c50c785cSJohn Marino 	  fprintf (stderr, "%s: error: too many @-files encountered\n", (*argvp)[0]);
402c50c785cSJohn Marino 	  xexit (1);
403c50c785cSJohn Marino 	}
4045796c8dcSSimon Schubert       /* Read the contents of the file.  */
4055796c8dcSSimon Schubert       f = fopen (++filename, "r");
4065796c8dcSSimon Schubert       if (!f)
4075796c8dcSSimon Schubert 	continue;
4085796c8dcSSimon Schubert       if (fseek (f, 0L, SEEK_END) == -1)
4095796c8dcSSimon Schubert 	goto error;
4105796c8dcSSimon Schubert       pos = ftell (f);
4115796c8dcSSimon Schubert       if (pos == -1)
4125796c8dcSSimon Schubert 	goto error;
4135796c8dcSSimon Schubert       if (fseek (f, 0L, SEEK_SET) == -1)
4145796c8dcSSimon Schubert 	goto error;
4155796c8dcSSimon Schubert       buffer = (char *) xmalloc (pos * sizeof (char) + 1);
4165796c8dcSSimon Schubert       len = fread (buffer, sizeof (char), pos, f);
4175796c8dcSSimon Schubert       if (len != (size_t) pos
4185796c8dcSSimon Schubert 	  /* On Windows, fread may return a value smaller than POS,
4195796c8dcSSimon Schubert 	     due to CR/LF->CR translation when reading text files.
4205796c8dcSSimon Schubert 	     That does not in-and-of itself indicate failure.  */
4215796c8dcSSimon Schubert 	  && ferror (f))
4225796c8dcSSimon Schubert 	goto error;
4235796c8dcSSimon Schubert       /* Add a NUL terminator.  */
4245796c8dcSSimon Schubert       buffer[len] = '\0';
425cf7f2e2dSJohn Marino       /* If the file is empty or contains only whitespace, buildargv would
426cf7f2e2dSJohn Marino 	 return a single empty argument.  In this context we want no arguments,
427cf7f2e2dSJohn Marino 	 instead.  */
428cf7f2e2dSJohn Marino       if (only_whitespace (buffer))
429cf7f2e2dSJohn Marino 	{
430cf7f2e2dSJohn Marino 	  file_argv = (char **) xmalloc (sizeof (char *));
431cf7f2e2dSJohn Marino 	  file_argv[0] = NULL;
432cf7f2e2dSJohn Marino 	}
433cf7f2e2dSJohn Marino       else
4345796c8dcSSimon Schubert 	/* Parse the string.  */
4355796c8dcSSimon Schubert 	file_argv = buildargv (buffer);
4365796c8dcSSimon Schubert       /* If *ARGVP is not already dynamically allocated, copy it.  */
4375796c8dcSSimon Schubert       if (!argv_dynamic)
4385796c8dcSSimon Schubert 	*argvp = dupargv (*argvp);
4395796c8dcSSimon Schubert       /* Count the number of arguments.  */
4405796c8dcSSimon Schubert       file_argc = 0;
441cf7f2e2dSJohn Marino       while (file_argv[file_argc])
4425796c8dcSSimon Schubert 	++file_argc;
4435796c8dcSSimon Schubert       /* Now, insert FILE_ARGV into ARGV.  The "+1" below handles the
4445796c8dcSSimon Schubert 	 NULL terminator at the end of ARGV.  */
4455796c8dcSSimon Schubert       *argvp = ((char **)
4465796c8dcSSimon Schubert 		xrealloc (*argvp,
4475796c8dcSSimon Schubert 			  (*argcp + file_argc + 1) * sizeof (char *)));
4485796c8dcSSimon Schubert       memmove (*argvp + i + file_argc, *argvp + i + 1,
4495796c8dcSSimon Schubert 	       (*argcp - i) * sizeof (char *));
4505796c8dcSSimon Schubert       memcpy (*argvp + i, file_argv, file_argc * sizeof (char *));
4515796c8dcSSimon Schubert       /* The original option has been replaced by all the new
4525796c8dcSSimon Schubert 	 options.  */
4535796c8dcSSimon Schubert       *argcp += file_argc - 1;
4545796c8dcSSimon Schubert       /* Free up memory allocated to process the response file.  We do
4555796c8dcSSimon Schubert 	 not use freeargv because the individual options in FILE_ARGV
4565796c8dcSSimon Schubert 	 are now in the main ARGV.  */
4575796c8dcSSimon Schubert       free (file_argv);
4585796c8dcSSimon Schubert       free (buffer);
4595796c8dcSSimon Schubert       /* Rescan all of the arguments just read to support response
4605796c8dcSSimon Schubert 	 files that include other response files.  */
4615796c8dcSSimon Schubert       --i;
4625796c8dcSSimon Schubert     error:
4635796c8dcSSimon Schubert       /* We're all done with the file now.  */
4645796c8dcSSimon Schubert       fclose (f);
4655796c8dcSSimon Schubert     }
4665796c8dcSSimon Schubert }
4675796c8dcSSimon Schubert 
468a45ae5f8SJohn Marino /*
469a45ae5f8SJohn Marino 
470a45ae5f8SJohn Marino @deftypefn Extension int countargv (char **@var{argv})
471a45ae5f8SJohn Marino 
472a45ae5f8SJohn Marino Return the number of elements in @var{argv}.
473a45ae5f8SJohn Marino Returns zero if @var{argv} is NULL.
474a45ae5f8SJohn Marino 
475a45ae5f8SJohn Marino @end deftypefn
476a45ae5f8SJohn Marino 
477a45ae5f8SJohn Marino */
478a45ae5f8SJohn Marino 
479a45ae5f8SJohn Marino int
countargv(char ** argv)480a45ae5f8SJohn Marino countargv (char **argv)
481a45ae5f8SJohn Marino {
482a45ae5f8SJohn Marino   int argc;
483a45ae5f8SJohn Marino 
484a45ae5f8SJohn Marino   if (argv == NULL)
485a45ae5f8SJohn Marino     return 0;
486a45ae5f8SJohn Marino   for (argc = 0; argv[argc] != NULL; argc++)
487a45ae5f8SJohn Marino     continue;
488a45ae5f8SJohn Marino   return argc;
489a45ae5f8SJohn Marino }
490a45ae5f8SJohn Marino 
4915796c8dcSSimon Schubert #ifdef MAIN
4925796c8dcSSimon Schubert 
4935796c8dcSSimon Schubert /* Simple little test driver. */
4945796c8dcSSimon Schubert 
4955796c8dcSSimon Schubert static const char *const tests[] =
4965796c8dcSSimon Schubert {
4975796c8dcSSimon Schubert   "a simple command line",
4985796c8dcSSimon Schubert   "arg 'foo' is single quoted",
4995796c8dcSSimon Schubert   "arg \"bar\" is double quoted",
5005796c8dcSSimon Schubert   "arg \"foo bar\" has embedded whitespace",
5015796c8dcSSimon Schubert   "arg 'Jack said \\'hi\\'' has single quotes",
5025796c8dcSSimon Schubert   "arg 'Jack said \\\"hi\\\"' has double quotes",
5035796c8dcSSimon Schubert   "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",
5045796c8dcSSimon Schubert 
5055796c8dcSSimon Schubert   /* This should be expanded into only one argument.  */
5065796c8dcSSimon Schubert   "trailing-whitespace ",
5075796c8dcSSimon Schubert 
5085796c8dcSSimon Schubert   "",
5095796c8dcSSimon Schubert   NULL
5105796c8dcSSimon Schubert };
5115796c8dcSSimon Schubert 
5125796c8dcSSimon Schubert int
main(void)5135796c8dcSSimon Schubert main (void)
5145796c8dcSSimon Schubert {
5155796c8dcSSimon Schubert   char **argv;
5165796c8dcSSimon Schubert   const char *const *test;
5175796c8dcSSimon Schubert   char **targs;
5185796c8dcSSimon Schubert 
5195796c8dcSSimon Schubert   for (test = tests; *test != NULL; test++)
5205796c8dcSSimon Schubert     {
5215796c8dcSSimon Schubert       printf ("buildargv(\"%s\")\n", *test);
5225796c8dcSSimon Schubert       if ((argv = buildargv (*test)) == NULL)
5235796c8dcSSimon Schubert 	{
5245796c8dcSSimon Schubert 	  printf ("failed!\n\n");
5255796c8dcSSimon Schubert 	}
5265796c8dcSSimon Schubert       else
5275796c8dcSSimon Schubert 	{
5285796c8dcSSimon Schubert 	  for (targs = argv; *targs != NULL; targs++)
5295796c8dcSSimon Schubert 	    {
5305796c8dcSSimon Schubert 	      printf ("\t\"%s\"\n", *targs);
5315796c8dcSSimon Schubert 	    }
5325796c8dcSSimon Schubert 	  printf ("\n");
5335796c8dcSSimon Schubert 	}
5345796c8dcSSimon Schubert       freeargv (argv);
5355796c8dcSSimon Schubert     }
5365796c8dcSSimon Schubert 
5375796c8dcSSimon Schubert   return 0;
5385796c8dcSSimon Schubert }
5395796c8dcSSimon Schubert 
5405796c8dcSSimon Schubert #endif	/* MAIN */
541