Add aliases in nested blocks
[official-gcc.git] / libiberty / argv.c
blob195d31019a0a6731a6420578680f5aee16bd5305
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. */
25 #include "ansidecl.h"
26 #include "libiberty.h"
28 #ifdef isspace
29 #undef isspace
30 #endif
31 #define isspace(ch) ((ch) == ' ' || (ch) == '\t')
33 /* Routines imported from standard C runtime libraries. */
35 #ifdef __STDC__
37 #include <stddef.h>
38 extern void *memcpy (void *s1, const void *s2, size_t n); /* 4.11.2.1 */
39 extern size_t strlen (const char *s); /* 4.11.6.3 */
40 extern void *malloc (size_t size); /* 4.10.3.3 */
41 extern void *realloc (void *ptr, size_t size); /* 4.10.3.4 */
42 extern void free (void *ptr); /* 4.10.3.2 */
43 extern char *strdup (const char *s); /* Non-ANSI */
45 #else /* !__STDC__ */
47 #if !defined _WIN32 || defined __GNUC__
48 extern char *memcpy (); /* Copy memory region */
49 extern int strlen (); /* Count length of string */
50 extern char *malloc (); /* Standard memory allocater */
51 extern char *realloc (); /* Standard memory reallocator */
52 extern void free (); /* Free malloc'd memory */
53 extern char *strdup (); /* Duplicate a string */
54 #endif
56 #endif /* __STDC__ */
58 #include "alloca-conf.h"
60 #ifndef NULL
61 #define NULL 0
62 #endif
64 #ifndef EOS
65 #define EOS '\0'
66 #endif
68 #define INITIAL_MAXARGC 8 /* Number of args + NULL in initial argv */
73 NAME
75 dupargv -- duplicate an argument vector
77 SYNOPSIS
79 char **dupargv (vector)
80 char **vector;
82 DESCRIPTION
84 Duplicate an argument vector. Simply scans through the
85 vector, duplicating each argument until the
86 terminating NULL is found.
88 RETURNS
90 Returns a pointer to the argument vector if
91 successful. Returns NULL if there is insufficient memory to
92 complete building the argument vector.
96 char **
97 dupargv (argv)
98 char **argv;
100 int argc;
101 char **copy;
103 if (argv == NULL)
104 return NULL;
106 /* the vector */
107 for (argc = 0; argv[argc] != NULL; argc++);
108 copy = (char **) malloc ((argc + 1) * sizeof (char *));
109 if (copy == NULL)
110 return NULL;
112 /* the strings */
113 for (argc = 0; argv[argc] != NULL; argc++)
115 int len = strlen (argv[argc]);
116 copy[argc] = malloc (sizeof (char *) * (len + 1));
117 if (copy[argc] == NULL)
119 freeargv (copy);
120 return NULL;
122 strcpy (copy[argc], argv[argc]);
124 copy[argc] = NULL;
125 return copy;
130 NAME
132 freeargv -- free an argument vector
134 SYNOPSIS
136 void freeargv (vector)
137 char **vector;
139 DESCRIPTION
141 Free an argument vector that was built using buildargv. Simply scans
142 through the vector, freeing the memory for each argument until the
143 terminating NULL is found, and then frees the vector itself.
145 RETURNS
147 No value.
151 void freeargv (vector)
152 char **vector;
154 register char **scan;
156 if (vector != NULL)
158 for (scan = vector; *scan != NULL; scan++)
160 free (*scan);
162 free (vector);
168 NAME
170 buildargv -- build an argument vector from a string
172 SYNOPSIS
174 char **buildargv (sp)
175 char *sp;
177 DESCRIPTION
179 Given a pointer to a string, parse the string extracting fields
180 separated by whitespace and optionally enclosed within either single
181 or double quotes (which are stripped off), and build a vector of
182 pointers to copies of the string for each field. The input string
183 remains unchanged.
185 All of the memory for the pointer array and copies of the string
186 is obtained from malloc. All of the memory can be returned to the
187 system with the single function call freeargv, which takes the
188 returned result of buildargv, as it's argument.
190 The memory for the argv array is dynamically expanded as necessary.
192 RETURNS
194 Returns a pointer to the argument vector if successful. Returns NULL
195 if the input string pointer is NULL or if there is insufficient
196 memory to complete building the argument vector.
198 NOTES
200 In order to provide a working buffer for extracting arguments into,
201 with appropriate stripping of quotes and translation of backslash
202 sequences, we allocate a working buffer at least as long as the input
203 string. This ensures that we always have enough space in which to
204 work, since the extracted arg is never larger than the input string.
206 If the input is a null string (as opposed to a NULL pointer), then
207 buildarg returns an argv that has one arg, a null string.
209 Argv is always kept terminated with a NULL arg pointer, so it can
210 be passed to freeargv at any time, or returned, as appropriate.
213 char **buildargv (input)
214 char *input;
216 char *arg;
217 char *copybuf;
218 int squote = 0;
219 int dquote = 0;
220 int bsquote = 0;
221 int argc = 0;
222 int maxargc = 0;
223 char **argv = NULL;
224 char **nargv;
226 if (input != NULL)
228 copybuf = alloca (strlen (input) + 1);
229 /* Is a do{}while to always execute the loop once. Always return an
230 argv, even for null strings. See NOTES above, test case below. */
233 /* Pick off argv[argc] */
234 while (isspace (*input))
236 input++;
238 if ((maxargc == 0) || (argc >= (maxargc - 1)))
240 /* argv needs initialization, or expansion */
241 if (argv == NULL)
243 maxargc = INITIAL_MAXARGC;
244 nargv = (char **) malloc (maxargc * sizeof (char *));
246 else
248 maxargc *= 2;
249 nargv = (char **) realloc (argv, maxargc * sizeof (char *));
251 if (nargv == NULL)
253 if (argv != NULL)
255 freeargv (argv);
256 argv = NULL;
258 break;
260 argv = nargv;
261 argv[argc] = NULL;
263 /* Begin scanning arg */
264 arg = copybuf;
265 while (*input != EOS)
267 if (isspace (*input) && !squote && !dquote && !bsquote)
269 break;
271 else
273 if (bsquote)
275 bsquote = 0;
276 *arg++ = *input;
278 else if (*input == '\\')
280 bsquote = 1;
282 else if (squote)
284 if (*input == '\'')
286 squote = 0;
288 else
290 *arg++ = *input;
293 else if (dquote)
295 if (*input == '"')
297 dquote = 0;
299 else
301 *arg++ = *input;
304 else
306 if (*input == '\'')
308 squote = 1;
310 else if (*input == '"')
312 dquote = 1;
314 else
316 *arg++ = *input;
319 input++;
322 *arg = EOS;
323 argv[argc] = strdup (copybuf);
324 if (argv[argc] == NULL)
326 freeargv (argv);
327 argv = NULL;
328 break;
330 argc++;
331 argv[argc] = NULL;
333 while (isspace (*input))
335 input++;
338 while (*input != EOS);
340 return (argv);
343 #ifdef MAIN
345 /* Simple little test driver. */
347 static char *tests[] =
349 "a simple command line",
350 "arg 'foo' is single quoted",
351 "arg \"bar\" is double quoted",
352 "arg \"foo bar\" has embedded whitespace",
353 "arg 'Jack said \\'hi\\'' has single quotes",
354 "arg 'Jack said \\\"hi\\\"' has double quotes",
355 "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",
357 /* This should be expanded into only one argument. */
358 "trailing-whitespace ",
361 NULL
364 main ()
366 char **argv;
367 char **test;
368 char **targs;
370 for (test = tests; *test != NULL; test++)
372 printf ("buildargv(\"%s\")\n", *test);
373 if ((argv = buildargv (*test)) == NULL)
375 printf ("failed!\n\n");
377 else
379 for (targs = argv; *targs != NULL; targs++)
381 printf ("\t\"%s\"\n", *targs);
383 printf ("\n");
385 freeargv (argv);
390 #endif /* MAIN */