1 /* Create and destroy argument vectors (argv's)
2 Copyright (C) 1992 Free Software Foundation, Inc.
3 Written by Fred Fish @ Cygnus Support
5 This file is part of the libiberty library.
6 Libiberty is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
11 Libiberty is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with libiberty; see the file COPYING.LIB. If
18 not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
22 /* Create and destroy argument vectors. An argument vector is simply an
23 array of string pointers, terminated by a NULL pointer. */
26 #include "libiberty.h"
28 #define isspace(ch) ((ch) == ' ' || (ch) == '\t')
30 /* Routines imported from standard C runtime libraries. */
35 extern void *memcpy (void *s1, const void *s2, size_t n); /* 4.11.2.1 */
36 extern size_t strlen (const char *s); /* 4.11.6.3 */
37 extern void *malloc (size_t size); /* 4.10.3.3 */
38 extern void *realloc (void *ptr, size_t size); /* 4.10.3.4 */
39 extern void free (void *ptr); /* 4.10.3.2 */
40 extern char *strdup (const char *s); /* Non-ANSI */
44 extern char *memcpy (); /* Copy memory region */
45 extern int strlen (); /* Count length of string */
46 extern char *malloc (); /* Standard memory allocater */
47 extern char *realloc (); /* Standard memory reallocator */
48 extern void free (); /* Free malloc'd memory */
49 extern char *strdup (); /* Duplicate a string */
53 #include "alloca-conf.h"
63 #define INITIAL_MAXARGC 8 /* Number of args + NULL in initial argv */
70 freeargv -- free an argument vector
74 void freeargv (vector)
79 Free an argument vector that was built using buildargv. Simply scans
80 through the vector, freeing the memory for each argument until the
81 terminating NULL is found, and then frees the vector itself.
89 void freeargv (vector)
96 for (scan = vector; *scan != NULL; scan++)
108 buildargv -- build an argument vector from a string
112 char **buildargv (sp)
117 Given a pointer to a string, parse the string extracting fields
118 separated by whitespace and optionally enclosed within either single
119 or double quotes (which are stripped off), and build a vector of
120 pointers to copies of the string for each field. The input string
123 All of the memory for the pointer array and copies of the string
124 is obtained from malloc. All of the memory can be returned to the
125 system with the single function call freeargv, which takes the
126 returned result of buildargv, as it's argument.
128 The memory for the argv array is dynamically expanded as necessary.
132 Returns a pointer to the argument vector if successful. Returns NULL
133 if the input string pointer is NULL or if there is insufficient
134 memory to complete building the argument vector.
138 In order to provide a working buffer for extracting arguments into,
139 with appropriate stripping of quotes and translation of backslash
140 sequences, we allocate a working buffer at least as long as the input
141 string. This ensures that we always have enough space in which to
142 work, since the extracted arg is never larger than the input string.
144 If the input is a null string (as opposed to a NULL pointer), then
145 buildarg returns an argv that has one arg, a null string.
147 Argv is always kept terminated with a NULL arg pointer, so it can
148 be passed to freeargv at any time, or returned, as appropriate.
151 char **buildargv (input)
166 copybuf = alloca (strlen (input) + 1);
167 /* Is a do{}while to always execute the loop once. Always return an
168 argv, even for null strings. See NOTES above, test case below. */
171 /* Pick off argv[argc] */
172 while (isspace (*input))
176 if ((maxargc == 0) || (argc >= (maxargc - 1)))
178 /* argv needs initialization, or expansion */
181 maxargc = INITIAL_MAXARGC;
182 nargv = (char **) malloc (maxargc * sizeof (char *));
187 nargv = (char **) realloc (argv, maxargc * sizeof (char *));
201 /* Begin scanning arg */
203 while (*input != EOS)
205 if (isspace (*input) && !squote && !dquote && !bsquote)
216 else if (*input == '\\')
248 else if (*input == '"')
261 argv[argc] = strdup (copybuf);
262 if (argv[argc] == NULL)
271 while (isspace (*input))
276 while (*input != EOS);
283 /* Simple little test driver. */
285 static char *tests[] =
287 "a simple command line",
288 "arg 'foo' is single quoted",
289 "arg \"bar\" is double quoted",
290 "arg \"foo bar\" has embedded whitespace",
291 "arg 'Jack said \\'hi\\'' has single quotes",
292 "arg 'Jack said \\\"hi\\\"' has double quotes",
293 "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",
295 /* This should be expanded into only one argument. */
296 "trailing-whitespace ",
308 for (test = tests; *test != NULL; test++)
310 printf ("buildargv(\"%s\")\n", *test);
311 if ((argv = buildargv (*test)) == NULL)
313 printf ("failed!\n\n");
317 for (targs = argv; *targs != NULL; targs++)
319 printf ("\t\"%s\"\n", *targs);