Back to index

cell-binutils  2.17cvs20070401
argv.c
Go to the documentation of this file.
00001 /* Create and destroy argument vectors (argv's)
00002    Copyright (C) 1992, 2001 Free Software Foundation, Inc.
00003    Written by Fred Fish @ Cygnus Support
00004 
00005 This file is part of the libiberty library.
00006 Libiberty is free software; you can redistribute it and/or
00007 modify it under the terms of the GNU Library General Public
00008 License as published by the Free Software Foundation; either
00009 version 2 of the License, or (at your option) any later version.
00010 
00011 Libiberty is distributed in the hope that it will be useful,
00012 but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 Library General Public License for more details.
00015 
00016 You should have received a copy of the GNU Library General Public
00017 License along with libiberty; see the file COPYING.LIB.  If
00018 not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
00019 Boston, MA 02110-1301, USA.  */
00020 
00021 
00022 /*  Create and destroy argument vectors.  An argument vector is simply an
00023     array of string pointers, terminated by a NULL pointer. */
00024 
00025 #ifdef HAVE_CONFIG_H
00026 #include "config.h"
00027 #endif
00028 #include "ansidecl.h"
00029 #include "libiberty.h"
00030 #include "safe-ctype.h"
00031 
00032 /*  Routines imported from standard C runtime libraries. */
00033 
00034 #include <stddef.h>
00035 #include <string.h>
00036 #include <stdlib.h>
00037 #include <stdio.h>
00038 
00039 #ifndef NULL
00040 #define NULL 0
00041 #endif
00042 
00043 #ifndef EOS
00044 #define EOS '\0'
00045 #endif
00046 
00047 #define INITIAL_MAXARGC 8   /* Number of args + NULL in initial argv */
00048 
00049 
00050 /*
00051 
00052 @deftypefn Extension char** dupargv (char **@var{vector})
00053 
00054 Duplicate an argument vector.  Simply scans through @var{vector},
00055 duplicating each argument until the terminating @code{NULL} is found.
00056 Returns a pointer to the argument vector if successful.  Returns
00057 @code{NULL} if there is insufficient memory to complete building the
00058 argument vector.
00059 
00060 @end deftypefn
00061 
00062 */
00063 
00064 char **
00065 dupargv (char **argv)
00066 {
00067   int argc;
00068   char **copy;
00069   
00070   if (argv == NULL)
00071     return NULL;
00072   
00073   /* the vector */
00074   for (argc = 0; argv[argc] != NULL; argc++);
00075   copy = (char **) malloc ((argc + 1) * sizeof (char *));
00076   if (copy == NULL)
00077     return NULL;
00078   
00079   /* the strings */
00080   for (argc = 0; argv[argc] != NULL; argc++)
00081     {
00082       int len = strlen (argv[argc]);
00083       copy[argc] = (char *) malloc (len + 1);
00084       if (copy[argc] == NULL)
00085        {
00086          freeargv (copy);
00087          return NULL;
00088        }
00089       strcpy (copy[argc], argv[argc]);
00090     }
00091   copy[argc] = NULL;
00092   return copy;
00093 }
00094 
00095 /*
00096 
00097 @deftypefn Extension void freeargv (char **@var{vector})
00098 
00099 Free an argument vector that was built using @code{buildargv}.  Simply
00100 scans through @var{vector}, freeing the memory for each argument until
00101 the terminating @code{NULL} is found, and then frees @var{vector}
00102 itself.
00103 
00104 @end deftypefn
00105 
00106 */
00107 
00108 void freeargv (char **vector)
00109 {
00110   register char **scan;
00111 
00112   if (vector != NULL)
00113     {
00114       for (scan = vector; *scan != NULL; scan++)
00115        {
00116          free (*scan);
00117        }
00118       free (vector);
00119     }
00120 }
00121 
00122 /*
00123 
00124 @deftypefn Extension char** buildargv (char *@var{sp})
00125 
00126 Given a pointer to a string, parse the string extracting fields
00127 separated by whitespace and optionally enclosed within either single
00128 or double quotes (which are stripped off), and build a vector of
00129 pointers to copies of the string for each field.  The input string
00130 remains unchanged.  The last element of the vector is followed by a
00131 @code{NULL} element.
00132 
00133 All of the memory for the pointer array and copies of the string
00134 is obtained from @code{malloc}.  All of the memory can be returned to the
00135 system with the single function call @code{freeargv}, which takes the
00136 returned result of @code{buildargv}, as it's argument.
00137 
00138 Returns a pointer to the argument vector if successful.  Returns
00139 @code{NULL} if @var{sp} is @code{NULL} or if there is insufficient
00140 memory to complete building the argument vector.
00141 
00142 If the input is a null string (as opposed to a @code{NULL} pointer),
00143 then buildarg returns an argument vector that has one arg, a null
00144 string.
00145 
00146 @end deftypefn
00147 
00148 The memory for the argv array is dynamically expanded as necessary.
00149 
00150 In order to provide a working buffer for extracting arguments into,
00151 with appropriate stripping of quotes and translation of backslash
00152 sequences, we allocate a working buffer at least as long as the input
00153 string.  This ensures that we always have enough space in which to
00154 work, since the extracted arg is never larger than the input string.
00155 
00156 The argument vector is always kept terminated with a @code{NULL} arg
00157 pointer, so it can be passed to @code{freeargv} at any time, or
00158 returned, as appropriate.
00159 
00160 */
00161 
00162 char **buildargv (const char *input)
00163 {
00164   char *arg;
00165   char *copybuf;
00166   int squote = 0;
00167   int dquote = 0;
00168   int bsquote = 0;
00169   int argc = 0;
00170   int maxargc = 0;
00171   char **argv = NULL;
00172   char **nargv;
00173 
00174   if (input != NULL)
00175     {
00176       copybuf = (char *) alloca (strlen (input) + 1);
00177       /* Is a do{}while to always execute the loop once.  Always return an
00178         argv, even for null strings.  See NOTES above, test case below. */
00179       do
00180        {
00181          /* Pick off argv[argc] */
00182          while (ISBLANK (*input))
00183            {
00184              input++;
00185            }
00186          if ((maxargc == 0) || (argc >= (maxargc - 1)))
00187            {
00188              /* argv needs initialization, or expansion */
00189              if (argv == NULL)
00190               {
00191                 maxargc = INITIAL_MAXARGC;
00192                 nargv = (char **) malloc (maxargc * sizeof (char *));
00193               }
00194              else
00195               {
00196                 maxargc *= 2;
00197                 nargv = (char **) realloc (argv, maxargc * sizeof (char *));
00198               }
00199              if (nargv == NULL)
00200               {
00201                 if (argv != NULL)
00202                   {
00203                     freeargv (argv);
00204                     argv = NULL;
00205                   }
00206                 break;
00207               }
00208              argv = nargv;
00209              argv[argc] = NULL;
00210            }
00211          /* Begin scanning arg */
00212          arg = copybuf;
00213          while (*input != EOS)
00214            {
00215              if (ISSPACE (*input) && !squote && !dquote && !bsquote)
00216               {
00217                 break;
00218               }
00219              else
00220               {
00221                 if (bsquote)
00222                   {
00223                     bsquote = 0;
00224                     *arg++ = *input;
00225                   }
00226                 else if (*input == '\\')
00227                   {
00228                     bsquote = 1;
00229                   }
00230                 else if (squote)
00231                   {
00232                     if (*input == '\'')
00233                      {
00234                        squote = 0;
00235                      }
00236                     else
00237                      {
00238                        *arg++ = *input;
00239                      }
00240                   }
00241                 else if (dquote)
00242                   {
00243                     if (*input == '"')
00244                      {
00245                        dquote = 0;
00246                      }
00247                     else
00248                      {
00249                        *arg++ = *input;
00250                      }
00251                   }
00252                 else
00253                   {
00254                     if (*input == '\'')
00255                      {
00256                        squote = 1;
00257                      }
00258                     else if (*input == '"')
00259                      {
00260                        dquote = 1;
00261                      }
00262                     else
00263                      {
00264                        *arg++ = *input;
00265                      }
00266                   }
00267                 input++;
00268               }
00269            }
00270          *arg = EOS;
00271          argv[argc] = strdup (copybuf);
00272          if (argv[argc] == NULL)
00273            {
00274              freeargv (argv);
00275              argv = NULL;
00276              break;
00277            }
00278          argc++;
00279          argv[argc] = NULL;
00280 
00281          while (ISSPACE (*input))
00282            {
00283              input++;
00284            }
00285        }
00286       while (*input != EOS);
00287     }
00288   return (argv);
00289 }
00290 
00291 /*
00292 
00293 @deftypefn Extension void expandargv (int *@var{argcp}, char ***@var{argvp})
00294 
00295 The @var{argcp} and @code{argvp} arguments are pointers to the usual
00296 @code{argc} and @code{argv} arguments to @code{main}.  This function
00297 looks for arguments that begin with the character @samp{@@}.  Any such
00298 arguments are interpreted as ``response files''.  The contents of the
00299 response file are interpreted as additional command line options.  In
00300 particular, the file is separated into whitespace-separated strings;
00301 each such string is taken as a command-line option.  The new options
00302 are inserted in place of the option naming the response file, and
00303 @code{*argcp} and @code{*argvp} will be updated.  If the value of
00304 @code{*argvp} is modified by this function, then the new value has
00305 been dynamically allocated and can be deallocated by the caller with
00306 @code{freeargv}.  However, most callers will simply call
00307 @code{expandargv} near the beginning of @code{main} and allow the
00308 operating system to free the memory when the program exits.
00309 
00310 @end deftypefn
00311 
00312 */
00313 
00314 void
00315 expandargv (argcp, argvp)
00316      int *argcp;
00317      char ***argvp;
00318 {
00319   /* The argument we are currently processing.  */
00320   int i = 0;
00321   /* Non-zero if ***argvp has been dynamically allocated.  */
00322   int argv_dynamic = 0;
00323   /* Loop over the arguments, handling response files.  We always skip
00324      ARGVP[0], as that is the name of the program being run.  */
00325   while (++i < *argcp)
00326     {
00327       /* The name of the response file.  */
00328       const char *filename;
00329       /* The response file.  */
00330       FILE *f;
00331       /* An upper bound on the number of characters in the response
00332         file.  */
00333       long pos;
00334       /* The number of characters in the response file, when actually
00335         read.  */
00336       size_t len;
00337       /* A dynamically allocated buffer used to hold options read from a
00338         response file.  */
00339       char *buffer;
00340       /* Dynamically allocated storage for the options read from the
00341         response file.  */
00342       char **file_argv;
00343       /* The number of options read from the response file, if any.  */
00344       size_t file_argc;
00345       /* We are only interested in options of the form "@file".  */
00346       filename = (*argvp)[i];
00347       if (filename[0] != '@')
00348        continue;
00349       /* Read the contents of the file.  */
00350       f = fopen (++filename, "r");
00351       if (!f)
00352        continue;
00353       if (fseek (f, 0L, SEEK_END) == -1)
00354        goto error;
00355       pos = ftell (f);
00356       if (pos == -1)
00357        goto error;
00358       if (fseek (f, 0L, SEEK_SET) == -1)
00359        goto error;
00360       buffer = (char *) xmalloc (pos * sizeof (char) + 1);
00361       len = fread (buffer, sizeof (char), pos, f);
00362       if (len != (size_t) pos
00363          /* On Windows, fread may return a value smaller than POS,
00364             due to CR/LF->CR translation when reading text files.
00365             That does not in-and-of itself indicate failure.  */
00366          && ferror (f))
00367        goto error;
00368       /* Add a NUL terminator.  */
00369       buffer[len] = '\0';
00370       /* Parse the string.  */
00371       file_argv = buildargv (buffer);
00372       /* If *ARGVP is not already dynamically allocated, copy it.  */
00373       if (!argv_dynamic)
00374        {
00375          *argvp = dupargv (*argvp);
00376          if (!*argvp)
00377            {
00378              fputs ("\nout of memory\n", stderr);
00379              xexit (1);
00380            }
00381        }
00382       /* Count the number of arguments.  */
00383       file_argc = 0;
00384       while (file_argv[file_argc] && *file_argv[file_argc])
00385        ++file_argc;
00386       /* Now, insert FILE_ARGV into ARGV.  The "+1" below handles the
00387         NULL terminator at the end of ARGV.  */ 
00388       *argvp = ((char **) 
00389               xrealloc (*argvp, 
00390                        (*argcp + file_argc + 1) * sizeof (char *)));
00391       memmove (*argvp + i + file_argc, *argvp + i + 1, 
00392               (*argcp - i) * sizeof (char *));
00393       memcpy (*argvp + i, file_argv, file_argc * sizeof (char *));
00394       /* The original option has been replaced by all the new
00395         options.  */
00396       *argcp += file_argc - 1;
00397       /* Free up memory allocated to process the response file.  We do
00398         not use freeargv because the individual options in FILE_ARGV
00399         are now in the main ARGV.  */
00400       free (file_argv);
00401       free (buffer);
00402       /* Rescan all of the arguments just read to support response
00403         files that include other response files.  */
00404       --i;
00405     error:
00406       /* We're all done with the file now.  */
00407       fclose (f);
00408     }
00409 }
00410 
00411 #ifdef MAIN
00412 
00413 /* Simple little test driver. */
00414 
00415 static const char *const tests[] =
00416 {
00417   "a simple command line",
00418   "arg 'foo' is single quoted",
00419   "arg \"bar\" is double quoted",
00420   "arg \"foo bar\" has embedded whitespace",
00421   "arg 'Jack said \\'hi\\'' has single quotes",
00422   "arg 'Jack said \\\"hi\\\"' has double quotes",
00423   "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",
00424   
00425   /* This should be expanded into only one argument.  */
00426   "trailing-whitespace ",
00427 
00428   "",
00429   NULL
00430 };
00431 
00432 int
00433 main (void)
00434 {
00435   char **argv;
00436   const char *const *test;
00437   char **targs;
00438 
00439   for (test = tests; *test != NULL; test++)
00440     {
00441       printf ("buildargv(\"%s\")\n", *test);
00442       if ((argv = buildargv (*test)) == NULL)
00443        {
00444          printf ("failed!\n\n");
00445        }
00446       else
00447        {
00448          for (targs = argv; *targs != NULL; targs++)
00449            {
00450              printf ("\t\"%s\"\n", *targs);
00451            }
00452          printf ("\n");
00453        }
00454       freeargv (argv);
00455     }
00456 
00457   return 0;
00458 }
00459 
00460 #endif /* MAIN */