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., 675 Mass Ave,
19
Cambridge, MA 02139, USA. */
22
/* Create and destroy argument vectors. An argument vector is simply an
23
array of string pointers, terminated by a NULL pointer. */
25
/* AIX requires this to be the first thing in the file. */
27
#define alloca __builtin_alloca
28
#else /* not __GNUC__ */
31
extern char *__builtin_alloca(); /* Stupid include file doesn't declare it */
37
#define alloca _alloca
38
#define strdup _strdup
44
#endif /* not __GNUC__ */
46
#define isspace(ch) ((ch) == ' ' || (ch) == '\t')
49
#include "alloca-conf.h"
52
/* Routines imported from standard C runtime libraries. */
57
extern void *memcpy (void *s1, const void *s2, size_t n); /* 4.11.2.1 */
58
extern size_t strlen (const char *s); /* 4.11.6.3 */
59
extern void *malloc (size_t size); /* 4.10.3.3 */
60
extern void *realloc (void *ptr, size_t size); /* 4.10.3.4 */
61
extern void free (void *ptr); /* 4.10.3.2 */
62
extern char *strdup (const char *s); /* Non-ANSI */
66
extern char *memcpy (); /* Copy memory region */
67
extern int strlen (); /* Count length of string */
68
extern char *malloc (); /* Standard memory allocater */
69
extern char *realloc (); /* Standard memory reallocator */
70
extern void free (); /* Free malloc'd memory */
71
extern char *strdup (); /* Duplicate a string */
83
#define INITIAL_MAXARGC 8 /* Number of args + NULL in initial argv */
86
void freeargv (char **vector);
87
char **buildargv (char *input);
94
freeargv -- free an argument vector
98
void freeargv (vector)
103
Free an argument vector that was built using buildargv. Simply scans
104
through the vector, freeing the memory for each argument until the
105
terminating NULL is found, and then frees the vector itself.
113
void freeargv (char **vector)
115
register char **scan;
119
for (scan = vector; *scan != NULL; scan++)
131
buildargv -- build an argument vector from a string
135
char **buildargv (sp)
140
Given a pointer to a string, parse the string extracting fields
141
separated by whitespace and optionally enclosed within either single
142
or double quotes (which are stripped off), and build a vector of
143
pointers to copies of the string for each field. The input string
146
All of the memory for the pointer array and copies of the string
147
is obtained from malloc. All of the memory can be returned to the
148
system with the single function call freeargv, which takes the
149
returned result of buildargv, as it's argument.
151
The memory for the argv array is dynamically expanded as necessary.
155
Returns a pointer to the argument vector if successful. Returns NULL
156
if the input string pointer is NULL or if there is insufficient
157
memory to complete building the argument vector.
161
In order to provide a working buffer for extracting arguments into,
162
with appropriate stripping of quotes and translation of backslash
163
sequences, we allocate a working buffer at least as long as the input
164
string. This ensures that we always have enough space in which to
165
work, since the extracted arg is never larger than the input string.
167
If the input is a null string (as opposed to a NULL pointer), then
168
buildarg returns an argv that has one arg, a null string.
170
Argv is always kept terminated with a NULL arg pointer, so it can
171
be passed to freeargv at any time, or returned, as appropriate.
174
char **buildargv (char *input)
188
copybuf = alloca (strlen (input) + 1);
189
/* Is a do{}while to always execute the loop once. Always return an
190
argv, even for null strings. See NOTES above, test case below. */
193
/* Pick off argv[argc] */
194
while (isspace (*input))
198
if ((maxargc == 0) || (argc >= (maxargc - 1)))
200
/* argv needs initialization, or expansion */
203
maxargc = INITIAL_MAXARGC;
204
nargv = (char **) malloc (maxargc * sizeof (char *));
209
nargv = (char **) realloc (argv, maxargc * sizeof (char *));
223
/* Begin scanning arg */
225
while (*input != EOS)
227
if (isspace (*input) && !squote && !dquote && !bsquote)
238
else if (*input == '\\')
270
else if (*input == '"')
283
argv[argc] = strdup (copybuf);
284
if (argv[argc] == NULL)
293
while (*input != EOS);
300
/* Simple little test driver. */
302
static char *tests[] =
304
"a simple command line",
305
"arg 'foo' is single quoted",
306
"arg \"bar\" is double quoted",
307
"arg \"foo bar\" has embedded whitespace",
308
"arg 'Jack said \\'hi\\'' has single quotes",
309
"arg 'Jack said \\\"hi\\\"' has double quotes",
310
"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",
321
for (test = tests; *test != NULL; test++)
323
printf ("buildargv(\"%s\")\n", *test);
324
if ((argv = buildargv (*test)) == NULL)
326
printf ("failed!\n\n");
330
for (targs = argv; *targs != NULL; targs++)
332
printf ("\t\"%s\"\n", *targs);