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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [libiberty/] [argv.c] - Blame information for rev 84

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 21 khays
/* Create and destroy argument vectors (argv's)
2
   Copyright (C) 1992, 2001, 2010 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
static void
123
consume_whitespace (const char **input)
124
{
125
  while (ISSPACE (**input))
126
    {
127
      (*input)++;
128
    }
129
}
130
 
131
static int
132
only_whitespace (const char* input)
133
{
134
  while (*input != EOS && ISSPACE (*input))
135
    input++;
136
 
137
  return (*input == EOS);
138
}
139
 
140
/*
141
 
142
@deftypefn Extension char** buildargv (char *@var{sp})
143
 
144
Given a pointer to a string, parse the string extracting fields
145
separated by whitespace and optionally enclosed within either single
146
or double quotes (which are stripped off), and build a vector of
147
pointers to copies of the string for each field.  The input string
148
remains unchanged.  The last element of the vector is followed by a
149
@code{NULL} element.
150
 
151
All of the memory for the pointer array and copies of the string
152
is obtained from @code{malloc}.  All of the memory can be returned to the
153
system with the single function call @code{freeargv}, which takes the
154
returned result of @code{buildargv}, as it's argument.
155
 
156
Returns a pointer to the argument vector if successful.  Returns
157
@code{NULL} if @var{sp} is @code{NULL} or if there is insufficient
158
memory to complete building the argument vector.
159
 
160
If the input is a null string (as opposed to a @code{NULL} pointer),
161
then buildarg returns an argument vector that has one arg, a null
162
string.
163
 
164
@end deftypefn
165
 
166
The memory for the argv array is dynamically expanded as necessary.
167
 
168
In order to provide a working buffer for extracting arguments into,
169
with appropriate stripping of quotes and translation of backslash
170
sequences, we allocate a working buffer at least as long as the input
171
string.  This ensures that we always have enough space in which to
172
work, since the extracted arg is never larger than the input string.
173
 
174
The argument vector is always kept terminated with a @code{NULL} arg
175
pointer, so it can be passed to @code{freeargv} at any time, or
176
returned, as appropriate.
177
 
178
*/
179
 
180
char **buildargv (const char *input)
181
{
182
  char *arg;
183
  char *copybuf;
184
  int squote = 0;
185
  int dquote = 0;
186
  int bsquote = 0;
187
  int argc = 0;
188
  int maxargc = 0;
189
  char **argv = NULL;
190
  char **nargv;
191
 
192
  if (input != NULL)
193
    {
194
      copybuf = (char *) alloca (strlen (input) + 1);
195
      /* Is a do{}while to always execute the loop once.  Always return an
196
         argv, even for null strings.  See NOTES above, test case below. */
197
      do
198
        {
199
          /* Pick off argv[argc] */
200
          consume_whitespace (&input);
201
 
202
          if ((maxargc == 0) || (argc >= (maxargc - 1)))
203
            {
204
              /* argv needs initialization, or expansion */
205
              if (argv == NULL)
206
                {
207
                  maxargc = INITIAL_MAXARGC;
208
                  nargv = (char **) malloc (maxargc * sizeof (char *));
209
                }
210
              else
211
                {
212
                  maxargc *= 2;
213
                  nargv = (char **) realloc (argv, maxargc * sizeof (char *));
214
                }
215
              if (nargv == NULL)
216
                {
217
                  if (argv != NULL)
218
                    {
219
                      freeargv (argv);
220
                      argv = NULL;
221
                    }
222
                  break;
223
                }
224
              argv = nargv;
225
              argv[argc] = NULL;
226
            }
227
          /* Begin scanning arg */
228
          arg = copybuf;
229
          while (*input != EOS)
230
            {
231
              if (ISSPACE (*input) && !squote && !dquote && !bsquote)
232
                {
233
                  break;
234
                }
235
              else
236
                {
237
                  if (bsquote)
238
                    {
239
                      bsquote = 0;
240
                      *arg++ = *input;
241
                    }
242
                  else if (*input == '\\')
243
                    {
244
                      bsquote = 1;
245
                    }
246
                  else if (squote)
247
                    {
248
                      if (*input == '\'')
249
                        {
250
                          squote = 0;
251
                        }
252
                      else
253
                        {
254
                          *arg++ = *input;
255
                        }
256
                    }
257
                  else if (dquote)
258
                    {
259
                      if (*input == '"')
260
                        {
261
                          dquote = 0;
262
                        }
263
                      else
264
                        {
265
                          *arg++ = *input;
266
                        }
267
                    }
268
                  else
269
                    {
270
                      if (*input == '\'')
271
                        {
272
                          squote = 1;
273
                        }
274
                      else if (*input == '"')
275
                        {
276
                          dquote = 1;
277
                        }
278
                      else
279
                        {
280
                          *arg++ = *input;
281
                        }
282
                    }
283
                  input++;
284
                }
285
            }
286
          *arg = EOS;
287
          argv[argc] = strdup (copybuf);
288
          if (argv[argc] == NULL)
289
            {
290
              freeargv (argv);
291
              argv = NULL;
292
              break;
293
            }
294
          argc++;
295
          argv[argc] = NULL;
296
 
297
          consume_whitespace (&input);
298
        }
299
      while (*input != EOS);
300
    }
301
  return (argv);
302
}
303
 
304
/*
305
 
306
@deftypefn Extension int writeargv (const char **@var{argv}, FILE *@var{file})
307
 
308
Write each member of ARGV, handling all necessary quoting, to the file
309
named by FILE, separated by whitespace.  Return 0 on success, non-zero
310
if an error occurred while writing to FILE.
311
 
312
@end deftypefn
313
 
314
*/
315
 
316
int
317
writeargv (char **argv, FILE *f)
318
{
319
  int status = 0;
320
 
321
  if (f == NULL)
322
    return 1;
323
 
324
  while (*argv != NULL)
325
    {
326
      const char *arg = *argv;
327
 
328
      while (*arg != EOS)
329
        {
330
          char c = *arg;
331
 
332
          if (ISSPACE(c) || c == '\\' || c == '\'' || c == '"')
333
            if (EOF == fputc ('\\', f))
334
              {
335
                status = 1;
336
                goto done;
337
              }
338
 
339
          if (EOF == fputc (c, f))
340
            {
341
              status = 1;
342
              goto done;
343
            }
344
          arg++;
345
        }
346
 
347
      if (EOF == fputc ('\n', f))
348
        {
349
          status = 1;
350
          goto done;
351
        }
352
      argv++;
353
    }
354
 
355
 done:
356
  return status;
357
}
358
 
359
/*
360
 
361
@deftypefn Extension void expandargv (int *@var{argcp}, char ***@var{argvp})
362
 
363
The @var{argcp} and @code{argvp} arguments are pointers to the usual
364
@code{argc} and @code{argv} arguments to @code{main}.  This function
365
looks for arguments that begin with the character @samp{@@}.  Any such
366
arguments are interpreted as ``response files''.  The contents of the
367
response file are interpreted as additional command line options.  In
368
particular, the file is separated into whitespace-separated strings;
369
each such string is taken as a command-line option.  The new options
370
are inserted in place of the option naming the response file, and
371
@code{*argcp} and @code{*argvp} will be updated.  If the value of
372
@code{*argvp} is modified by this function, then the new value has
373
been dynamically allocated and can be deallocated by the caller with
374
@code{freeargv}.  However, most callers will simply call
375
@code{expandargv} near the beginning of @code{main} and allow the
376
operating system to free the memory when the program exits.
377
 
378
@end deftypefn
379
 
380
*/
381
 
382
void
383
expandargv (int *argcp, char ***argvp)
384
{
385
  /* The argument we are currently processing.  */
386
  int i = 0;
387
  /* Non-zero if ***argvp has been dynamically allocated.  */
388
  int argv_dynamic = 0;
389
  /* Limit the number of response files that we parse in order
390
     to prevent infinite recursion.  */
391
  unsigned int iteration_limit = 2000;
392
  /* Loop over the arguments, handling response files.  We always skip
393
     ARGVP[0], as that is the name of the program being run.  */
394
  while (++i < *argcp)
395
    {
396
      /* The name of the response file.  */
397
      const char *filename;
398
      /* The response file.  */
399
      FILE *f;
400
      /* An upper bound on the number of characters in the response
401
         file.  */
402
      long pos;
403
      /* The number of characters in the response file, when actually
404
         read.  */
405
      size_t len;
406
      /* A dynamically allocated buffer used to hold options read from a
407
         response file.  */
408
      char *buffer;
409
      /* Dynamically allocated storage for the options read from the
410
         response file.  */
411
      char **file_argv;
412
      /* The number of options read from the response file, if any.  */
413
      size_t file_argc;
414
      /* We are only interested in options of the form "@file".  */
415
      filename = (*argvp)[i];
416
      if (filename[0] != '@')
417
        continue;
418
      /* If we have iterated too many times then stop.  */
419
      if (-- iteration_limit == 0)
420
        {
421
          fprintf (stderr, "%s: error: too many @-files encountered\n", (*argvp)[0]);
422
          xexit (1);
423
        }
424
      /* Read the contents of the file.  */
425
      f = fopen (++filename, "r");
426
      if (!f)
427
        continue;
428
      if (fseek (f, 0L, SEEK_END) == -1)
429
        goto error;
430
      pos = ftell (f);
431
      if (pos == -1)
432
        goto error;
433
      if (fseek (f, 0L, SEEK_SET) == -1)
434
        goto error;
435
      buffer = (char *) xmalloc (pos * sizeof (char) + 1);
436
      len = fread (buffer, sizeof (char), pos, f);
437
      if (len != (size_t) pos
438
          /* On Windows, fread may return a value smaller than POS,
439
             due to CR/LF->CR translation when reading text files.
440
             That does not in-and-of itself indicate failure.  */
441
          && ferror (f))
442
        goto error;
443
      /* Add a NUL terminator.  */
444
      buffer[len] = '\0';
445
      /* If the file is empty or contains only whitespace, buildargv would
446
         return a single empty argument.  In this context we want no arguments,
447
         instead.  */
448
      if (only_whitespace (buffer))
449
        {
450
          file_argv = (char **) xmalloc (sizeof (char *));
451
          file_argv[0] = NULL;
452
        }
453
      else
454
        /* Parse the string.  */
455
        file_argv = buildargv (buffer);
456
      /* If *ARGVP is not already dynamically allocated, copy it.  */
457
      if (!argv_dynamic)
458
        {
459
          *argvp = dupargv (*argvp);
460
          if (!*argvp)
461
            {
462
              fputs ("\nout of memory\n", stderr);
463
              xexit (1);
464
            }
465
        }
466
      /* Count the number of arguments.  */
467
      file_argc = 0;
468
      while (file_argv[file_argc])
469
        ++file_argc;
470
      /* Now, insert FILE_ARGV into ARGV.  The "+1" below handles the
471
         NULL terminator at the end of ARGV.  */
472
      *argvp = ((char **)
473
                xrealloc (*argvp,
474
                          (*argcp + file_argc + 1) * sizeof (char *)));
475
      memmove (*argvp + i + file_argc, *argvp + i + 1,
476
               (*argcp - i) * sizeof (char *));
477
      memcpy (*argvp + i, file_argv, file_argc * sizeof (char *));
478
      /* The original option has been replaced by all the new
479
         options.  */
480
      *argcp += file_argc - 1;
481
      /* Free up memory allocated to process the response file.  We do
482
         not use freeargv because the individual options in FILE_ARGV
483
         are now in the main ARGV.  */
484
      free (file_argv);
485
      free (buffer);
486
      /* Rescan all of the arguments just read to support response
487
         files that include other response files.  */
488
      --i;
489
    error:
490
      /* We're all done with the file now.  */
491
      fclose (f);
492
    }
493
}
494
 
495
#ifdef MAIN
496
 
497
/* Simple little test driver. */
498
 
499
static const char *const tests[] =
500
{
501
  "a simple command line",
502
  "arg 'foo' is single quoted",
503
  "arg \"bar\" is double quoted",
504
  "arg \"foo bar\" has embedded whitespace",
505
  "arg 'Jack said \\'hi\\'' has single quotes",
506
  "arg 'Jack said \\\"hi\\\"' has double quotes",
507
  "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",
508
 
509
  /* This should be expanded into only one argument.  */
510
  "trailing-whitespace ",
511
 
512
  "",
513
  NULL
514
};
515
 
516
int
517
main (void)
518
{
519
  char **argv;
520
  const char *const *test;
521
  char **targs;
522
 
523
  for (test = tests; *test != NULL; test++)
524
    {
525
      printf ("buildargv(\"%s\")\n", *test);
526
      if ((argv = buildargv (*test)) == NULL)
527
        {
528
          printf ("failed!\n\n");
529
        }
530
      else
531
        {
532
          for (targs = argv; *targs != NULL; targs++)
533
            {
534
              printf ("\t\"%s\"\n", *targs);
535
            }
536
          printf ("\n");
537
        }
538
      freeargv (argv);
539
    }
540
 
541
  return 0;
542
}
543
 
544
#endif  /* MAIN */

powered by: WebSVN 2.1.0

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