OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libiberty/] [argv.c] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* Create and destroy argument vectors (argv's)
2
   Copyright (C) 1992, 2001 Free Software Foundation, Inc.
3
   Written by Fred Fish @ Cygnus Support
4
 
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.
10
 
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.
15
 
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., 51 Franklin Street - Fifth Floor,
19
Boston, MA 02110-1301, 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
#ifdef HAVE_CONFIG_H
26
#include "config.h"
27
#endif
28
#include "ansidecl.h"
29
#include "libiberty.h"
30
#include "safe-ctype.h"
31
 
32
/*  Routines imported from standard C runtime libraries. */
33
 
34
#include <stddef.h>
35
#include <string.h>
36
#include <stdlib.h>
37
#include <stdio.h>
38
 
39
#ifndef NULL
40
#define NULL 0
41
#endif
42
 
43
#ifndef EOS
44
#define EOS '\0'
45
#endif
46
 
47
#define INITIAL_MAXARGC 8       /* Number of args + NULL in initial argv */
48
 
49
 
50
/*
51
 
52
@deftypefn Extension char** dupargv (char **@var{vector})
53
 
54
Duplicate an argument vector.  Simply scans through @var{vector},
55
duplicating each argument until the terminating @code{NULL} is found.
56
Returns a pointer to the argument vector if successful.  Returns
57
@code{NULL} if there is insufficient memory to complete building the
58
argument vector.
59
 
60
@end deftypefn
61
 
62
*/
63
 
64
char **
65
dupargv (char **argv)
66
{
67
  int argc;
68
  char **copy;
69
 
70
  if (argv == NULL)
71
    return NULL;
72
 
73
  /* the vector */
74
  for (argc = 0; argv[argc] != NULL; argc++);
75
  copy = (char **) malloc ((argc + 1) * sizeof (char *));
76
  if (copy == NULL)
77
    return NULL;
78
 
79
  /* the strings */
80
  for (argc = 0; argv[argc] != NULL; argc++)
81
    {
82
      int len = strlen (argv[argc]);
83
      copy[argc] = (char *) malloc (len + 1);
84
      if (copy[argc] == NULL)
85
        {
86
          freeargv (copy);
87
          return NULL;
88
        }
89
      strcpy (copy[argc], argv[argc]);
90
    }
91
  copy[argc] = NULL;
92
  return copy;
93
}
94
 
95
/*
96
 
97
@deftypefn Extension void freeargv (char **@var{vector})
98
 
99
Free an argument vector that was built using @code{buildargv}.  Simply
100
scans through @var{vector}, freeing the memory for each argument until
101
the terminating @code{NULL} is found, and then frees @var{vector}
102
itself.
103
 
104
@end deftypefn
105
 
106
*/
107
 
108
void freeargv (char **vector)
109
{
110
  register char **scan;
111
 
112
  if (vector != NULL)
113
    {
114
      for (scan = vector; *scan != NULL; scan++)
115
        {
116
          free (*scan);
117
        }
118
      free (vector);
119
    }
120
}
121
 
122
/*
123
 
124
@deftypefn Extension char** buildargv (char *@var{sp})
125
 
126
Given a pointer to a string, parse the string extracting fields
127
separated by whitespace and optionally enclosed within either single
128
or double quotes (which are stripped off), and build a vector of
129
pointers to copies of the string for each field.  The input string
130
remains unchanged.  The last element of the vector is followed by a
131
@code{NULL} element.
132
 
133
All of the memory for the pointer array and copies of the string
134
is obtained from @code{malloc}.  All of the memory can be returned to the
135
system with the single function call @code{freeargv}, which takes the
136
returned result of @code{buildargv}, as it's argument.
137
 
138
Returns a pointer to the argument vector if successful.  Returns
139
@code{NULL} if @var{sp} is @code{NULL} or if there is insufficient
140
memory to complete building the argument vector.
141
 
142
If the input is a null string (as opposed to a @code{NULL} pointer),
143
then buildarg returns an argument vector that has one arg, a null
144
string.
145
 
146
@end deftypefn
147
 
148
The memory for the argv array is dynamically expanded as necessary.
149
 
150
In order to provide a working buffer for extracting arguments into,
151
with appropriate stripping of quotes and translation of backslash
152
sequences, we allocate a working buffer at least as long as the input
153
string.  This ensures that we always have enough space in which to
154
work, since the extracted arg is never larger than the input string.
155
 
156
The argument vector is always kept terminated with a @code{NULL} arg
157
pointer, so it can be passed to @code{freeargv} at any time, or
158
returned, as appropriate.
159
 
160
*/
161
 
162
char **buildargv (const char *input)
163
{
164
  char *arg;
165
  char *copybuf;
166
  int squote = 0;
167
  int dquote = 0;
168
  int bsquote = 0;
169
  int argc = 0;
170
  int maxargc = 0;
171
  char **argv = NULL;
172
  char **nargv;
173
 
174
  if (input != NULL)
175
    {
176
      copybuf = (char *) alloca (strlen (input) + 1);
177
      /* Is a do{}while to always execute the loop once.  Always return an
178
         argv, even for null strings.  See NOTES above, test case below. */
179
      do
180
        {
181
          /* Pick off argv[argc] */
182
          while (ISBLANK (*input))
183
            {
184
              input++;
185
            }
186
          if ((maxargc == 0) || (argc >= (maxargc - 1)))
187
            {
188
              /* argv needs initialization, or expansion */
189
              if (argv == NULL)
190
                {
191
                  maxargc = INITIAL_MAXARGC;
192
                  nargv = (char **) malloc (maxargc * sizeof (char *));
193
                }
194
              else
195
                {
196
                  maxargc *= 2;
197
                  nargv = (char **) realloc (argv, maxargc * sizeof (char *));
198
                }
199
              if (nargv == NULL)
200
                {
201
                  if (argv != NULL)
202
                    {
203
                      freeargv (argv);
204
                      argv = NULL;
205
                    }
206
                  break;
207
                }
208
              argv = nargv;
209
              argv[argc] = NULL;
210
            }
211
          /* Begin scanning arg */
212
          arg = copybuf;
213
          while (*input != EOS)
214
            {
215
              if (ISSPACE (*input) && !squote && !dquote && !bsquote)
216
                {
217
                  break;
218
                }
219
              else
220
                {
221
                  if (bsquote)
222
                    {
223
                      bsquote = 0;
224
                      *arg++ = *input;
225
                    }
226
                  else if (*input == '\\')
227
                    {
228
                      bsquote = 1;
229
                    }
230
                  else if (squote)
231
                    {
232
                      if (*input == '\'')
233
                        {
234
                          squote = 0;
235
                        }
236
                      else
237
                        {
238
                          *arg++ = *input;
239
                        }
240
                    }
241
                  else if (dquote)
242
                    {
243
                      if (*input == '"')
244
                        {
245
                          dquote = 0;
246
                        }
247
                      else
248
                        {
249
                          *arg++ = *input;
250
                        }
251
                    }
252
                  else
253
                    {
254
                      if (*input == '\'')
255
                        {
256
                          squote = 1;
257
                        }
258
                      else if (*input == '"')
259
                        {
260
                          dquote = 1;
261
                        }
262
                      else
263
                        {
264
                          *arg++ = *input;
265
                        }
266
                    }
267
                  input++;
268
                }
269
            }
270
          *arg = EOS;
271
          argv[argc] = strdup (copybuf);
272
          if (argv[argc] == NULL)
273
            {
274
              freeargv (argv);
275
              argv = NULL;
276
              break;
277
            }
278
          argc++;
279
          argv[argc] = NULL;
280
 
281
          while (ISSPACE (*input))
282
            {
283
              input++;
284
            }
285
        }
286
      while (*input != EOS);
287
    }
288
  return (argv);
289
}
290
 
291
/*
292
 
293
@deftypefn Extension void expandargv (int *@var{argcp}, char ***@var{argvp})
294
 
295
The @var{argcp} and @code{argvp} arguments are pointers to the usual
296
@code{argc} and @code{argv} arguments to @code{main}.  This function
297
looks for arguments that begin with the character @samp{@@}.  Any such
298
arguments are interpreted as ``response files''.  The contents of the
299
response file are interpreted as additional command line options.  In
300
particular, the file is separated into whitespace-separated strings;
301
each such string is taken as a command-line option.  The new options
302
are inserted in place of the option naming the response file, and
303
@code{*argcp} and @code{*argvp} will be updated.  If the value of
304
@code{*argvp} is modified by this function, then the new value has
305
been dynamically allocated and can be deallocated by the caller with
306
@code{freeargv}.  However, most callers will simply call
307
@code{expandargv} near the beginning of @code{main} and allow the
308
operating system to free the memory when the program exits.
309
 
310
@end deftypefn
311
 
312
*/
313
 
314
void
315
expandargv (argcp, argvp)
316
     int *argcp;
317
     char ***argvp;
318
{
319
  /* The argument we are currently processing.  */
320
  int i = 0;
321
  /* Non-zero if ***argvp has been dynamically allocated.  */
322
  int argv_dynamic = 0;
323
  /* Loop over the arguments, handling response files.  We always skip
324
     ARGVP[0], as that is the name of the program being run.  */
325
  while (++i < *argcp)
326
    {
327
      /* The name of the response file.  */
328
      const char *filename;
329
      /* The response file.  */
330
      FILE *f;
331
      /* The number of characters in the response file.  */
332
      long pos;
333
      /* A dynamically allocated buffer used to hold options read from a
334
         response file.  */
335
      char *buffer;
336
      /* Dynamically allocated storage for the options read from the
337
         response file.  */
338
      char **file_argv;
339
      /* The number of options read from the response file, if any.  */
340
     size_t file_argc;
341
      /* We are only interested in options of the form "@file".  */
342
      filename = (*argvp)[i];
343
      if (filename[0] != '@')
344
        continue;
345
      /* Read the contents of the file.  */
346
      f = fopen (++filename, "r");
347
      if (!f)
348
        continue;
349
      if (fseek (f, 0L, SEEK_END) == -1)
350
        goto error;
351
      pos = ftell (f);
352
      if (pos == -1)
353
        goto error;
354
      if (fseek (f, 0L, SEEK_SET) == -1)
355
        goto error;
356
      buffer = (char *) xmalloc (pos * sizeof (char) + 1);
357
      if (fread (buffer, sizeof (char), pos, f) != (size_t) pos)
358
        goto error;
359
      /* Add a NUL terminator.  */
360
      buffer[pos] = '\0';
361
      /* Parse the string.  */
362
      file_argv = buildargv (buffer);
363
      /* If *ARGVP is not already dynamically allocated, copy it.  */
364
      if (!argv_dynamic)
365
        {
366
          *argvp = dupargv (*argvp);
367
          if (!*argvp)
368
            {
369
              fputs ("\nout of memory\n", stderr);
370
              xexit (1);
371
            }
372
        }
373
      /* Count the number of arguments.  */
374
      file_argc = 0;
375
      while (file_argv[file_argc] && *file_argv[file_argc])
376
        ++file_argc;
377
      /* Now, insert FILE_ARGV into ARGV.  The "+1" below handles the
378
         NULL terminator at the end of ARGV.  */
379
      *argvp = ((char **)
380
                xrealloc (*argvp,
381
                          (*argcp + file_argc + 1) * sizeof (char *)));
382
      memmove (*argvp + i + file_argc, *argvp + i + 1,
383
               (*argcp - i) * sizeof (char *));
384
      memcpy (*argvp + i, file_argv, file_argc * sizeof (char *));
385
      /* The original option has been replaced by all the new
386
         options.  */
387
      *argcp += file_argc - 1;
388
      /* Free up memory allocated to process the response file.  We do
389
         not use freeargv because the individual options in FILE_ARGV
390
         are now in the main ARGV.  */
391
      free (file_argv);
392
      free (buffer);
393
      /* Rescan all of the arguments just read to support response
394
         files that include other response files.  */
395
      --i;
396
    error:
397
      /* We're all done with the file now.  */
398
      fclose (f);
399
    }
400
}
401
 
402
#ifdef MAIN
403
 
404
/* Simple little test driver. */
405
 
406
static const char *const tests[] =
407
{
408
  "a simple command line",
409
  "arg 'foo' is single quoted",
410
  "arg \"bar\" is double quoted",
411
  "arg \"foo bar\" has embedded whitespace",
412
  "arg 'Jack said \\'hi\\'' has single quotes",
413
  "arg 'Jack said \\\"hi\\\"' has double quotes",
414
  "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",
415
 
416
  /* This should be expanded into only one argument.  */
417
  "trailing-whitespace ",
418
 
419
  "",
420
  NULL
421
};
422
 
423
int
424
main (void)
425
{
426
  char **argv;
427
  const char *const *test;
428
  char **targs;
429
 
430
  for (test = tests; *test != NULL; test++)
431
    {
432
      printf ("buildargv(\"%s\")\n", *test);
433
      if ((argv = buildargv (*test)) == NULL)
434
        {
435
          printf ("failed!\n\n");
436
        }
437
      else
438
        {
439
          for (targs = argv; *targs != NULL; targs++)
440
            {
441
              printf ("\t\"%s\"\n", *targs);
442
            }
443
          printf ("\n");
444
        }
445
      freeargv (argv);
446
    }
447
 
448
  return 0;
449
}
450
 
451
#endif  /* MAIN */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.