]> git.ipfire.org Git - thirdparty/gcc.git/blame - libiberty/argv.c
* c-typeck.c (output_init_element, process_init_element):
[thirdparty/gcc.git] / libiberty / argv.c
CommitLineData
28e9041c 1/* Create and destroy argument vectors (argv's)
2 Copyright (C) 1992 Free Software Foundation, Inc.
3 Written by Fred Fish @ Cygnus Support
4
5This file is part of the libiberty library.
6Libiberty is free software; you can redistribute it and/or
7modify it under the terms of the GNU Library General Public
8License as published by the Free Software Foundation; either
9version 2 of the License, or (at your option) any later version.
10
11Libiberty is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14Library General Public License for more details.
15
16You should have received a copy of the GNU Library General Public
17License along with libiberty; see the file COPYING.LIB. If
18not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
20
21
22/* Create and destroy argument vectors. An argument vector is simply an
23 array of string pointers, terminated by a NULL pointer. */
24
25#include "ansidecl.h"
26#include "libiberty.h"
27
28#ifdef isspace
29#undef isspace
30#endif
31#define isspace(ch) ((ch) == ' ' || (ch) == '\t')
32
33/* Routines imported from standard C runtime libraries. */
34
35#ifdef __STDC__
36
37#include <stddef.h>
38extern void *memcpy (void *s1, const void *s2, size_t n); /* 4.11.2.1 */
39extern size_t strlen (const char *s); /* 4.11.6.3 */
40extern void *malloc (size_t size); /* 4.10.3.3 */
41extern void *realloc (void *ptr, size_t size); /* 4.10.3.4 */
42extern void free (void *ptr); /* 4.10.3.2 */
43extern char *strdup (const char *s); /* Non-ANSI */
44
45#else /* !__STDC__ */
46
47#if !defined _WIN32 || defined __GNUC__
48extern char *memcpy (); /* Copy memory region */
49extern int strlen (); /* Count length of string */
50extern char *malloc (); /* Standard memory allocater */
51extern char *realloc (); /* Standard memory reallocator */
52extern void free (); /* Free malloc'd memory */
53extern char *strdup (); /* Duplicate a string */
54#endif
55
56#endif /* __STDC__ */
57
58#include "alloca-conf.h"
59
60#ifndef NULL
61#define NULL 0
62#endif
63
64#ifndef EOS
65#define EOS '\0'
66#endif
67
68#define INITIAL_MAXARGC 8 /* Number of args + NULL in initial argv */
69
70
8f71bf1d 71/*
72
73NAME
74
75 dupargv -- duplicate an argument vector
76
77SYNOPSIS
78
79 char **dupargv (vector)
80 char **vector;
81
82DESCRIPTION
83
84 Duplicate an argument vector. Simply scans through the
3398e91d 85 vector, duplicating each argument until the
8f71bf1d 86 terminating NULL is found.
87
88RETURNS
89
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.
93
94*/
95
96char **
97dupargv (argv)
98 char **argv;
99{
100 int argc;
101 char **copy;
102
103 if (argv == NULL)
104 return NULL;
105
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;
111
112 /* the strings */
113 for (argc = 0; argv[argc] != NULL; argc++)
114 {
115 int len = strlen (argv[argc]);
116 copy[argc] = malloc (sizeof (char *) * (len + 1));
117 if (copy[argc] == NULL)
118 {
119 freeargv (copy);
120 return NULL;
121 }
122 strcpy (copy[argc], argv[argc]);
123 }
124 copy[argc] = NULL;
125 return copy;
126}
127
28e9041c 128/*
129
130NAME
131
132 freeargv -- free an argument vector
133
134SYNOPSIS
135
136 void freeargv (vector)
137 char **vector;
138
139DESCRIPTION
140
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.
144
145RETURNS
146
147 No value.
148
149*/
150
151void freeargv (vector)
152char **vector;
153{
154 register char **scan;
155
156 if (vector != NULL)
157 {
158 for (scan = vector; *scan != NULL; scan++)
159 {
160 free (*scan);
161 }
162 free (vector);
163 }
164}
165
166/*
167
168NAME
169
170 buildargv -- build an argument vector from a string
171
172SYNOPSIS
173
174 char **buildargv (sp)
175 char *sp;
176
177DESCRIPTION
178
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.
184
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.
189
190 The memory for the argv array is dynamically expanded as necessary.
191
192RETURNS
193
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.
197
198NOTES
199
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.
205
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.
208
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.
211*/
212
213char **buildargv (input)
214char *input;
215{
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;
225
226 if (input != NULL)
227 {
7c8c70e9 228 copybuf = (char *) alloca (strlen (input) + 1);
28e9041c 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. */
231 do
232 {
233 /* Pick off argv[argc] */
234 while (isspace (*input))
235 {
236 input++;
237 }
238 if ((maxargc == 0) || (argc >= (maxargc - 1)))
239 {
240 /* argv needs initialization, or expansion */
241 if (argv == NULL)
242 {
243 maxargc = INITIAL_MAXARGC;
244 nargv = (char **) malloc (maxargc * sizeof (char *));
245 }
246 else
247 {
248 maxargc *= 2;
249 nargv = (char **) realloc (argv, maxargc * sizeof (char *));
250 }
251 if (nargv == NULL)
252 {
253 if (argv != NULL)
254 {
255 freeargv (argv);
256 argv = NULL;
257 }
258 break;
259 }
260 argv = nargv;
261 argv[argc] = NULL;
262 }
263 /* Begin scanning arg */
264 arg = copybuf;
265 while (*input != EOS)
266 {
267 if (isspace (*input) && !squote && !dquote && !bsquote)
268 {
269 break;
270 }
271 else
272 {
273 if (bsquote)
274 {
275 bsquote = 0;
276 *arg++ = *input;
277 }
278 else if (*input == '\\')
279 {
280 bsquote = 1;
281 }
282 else if (squote)
283 {
284 if (*input == '\'')
285 {
286 squote = 0;
287 }
288 else
289 {
290 *arg++ = *input;
291 }
292 }
293 else if (dquote)
294 {
295 if (*input == '"')
296 {
297 dquote = 0;
298 }
299 else
300 {
301 *arg++ = *input;
302 }
303 }
304 else
305 {
306 if (*input == '\'')
307 {
308 squote = 1;
309 }
310 else if (*input == '"')
311 {
312 dquote = 1;
313 }
314 else
315 {
316 *arg++ = *input;
317 }
318 }
319 input++;
320 }
321 }
322 *arg = EOS;
323 argv[argc] = strdup (copybuf);
324 if (argv[argc] == NULL)
325 {
326 freeargv (argv);
327 argv = NULL;
328 break;
329 }
330 argc++;
331 argv[argc] = NULL;
332
333 while (isspace (*input))
334 {
335 input++;
336 }
337 }
338 while (*input != EOS);
339 }
340 return (argv);
341}
342
343#ifdef MAIN
344
345/* Simple little test driver. */
346
347static char *tests[] =
348{
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",
356
357 /* This should be expanded into only one argument. */
358 "trailing-whitespace ",
359
360 "",
361 NULL
362};
363
364main ()
365{
366 char **argv;
367 char **test;
368 char **targs;
369
370 for (test = tests; *test != NULL; test++)
371 {
372 printf ("buildargv(\"%s\")\n", *test);
373 if ((argv = buildargv (*test)) == NULL)
374 {
375 printf ("failed!\n\n");
376 }
377 else
378 {
379 for (targs = argv; *targs != NULL; targs++)
380 {
381 printf ("\t\"%s\"\n", *targs);
382 }
383 printf ("\n");
384 }
385 freeargv (argv);
386 }
387
388}
389
390#endif /* MAIN */