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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [libiberty/] [argv.c] - Blame information for rev 868

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

Line No. Rev Author Line
1 38 julius
/* 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 int writeargv (const char **@var{argv}, FILE *@var{file})
294
 
295
Write each member of ARGV, handling all necessary quoting, to the file
296
named by FILE, separated by whitespace.  Return 0 on success, non-zero
297
if an error occurred while writing to FILE.
298
 
299
@end deftypefn
300
 
301
*/
302
 
303
int
304
writeargv (char **argv, FILE *f)
305
{
306
  int status = 0;
307
 
308
  if (f == NULL)
309
    return 1;
310
 
311
  while (*argv != NULL)
312
    {
313
      const char *arg = *argv;
314
 
315
      while (*arg != EOS)
316
        {
317
          char c = *arg;
318
 
319
          if (ISSPACE(c) || c == '\\' || c == '\'' || c == '"')
320
            if (EOF == fputc ('\\', f))
321
              {
322
                status = 1;
323
                goto done;
324
              }
325
 
326
          if (EOF == fputc (c, f))
327
            {
328
              status = 1;
329
              goto done;
330
            }
331
          arg++;
332
        }
333
 
334
      if (EOF == fputc ('\n', f))
335
        {
336
          status = 1;
337
          goto done;
338
        }
339
      argv++;
340
    }
341
 
342
 done:
343
  return status;
344
}
345
 
346
/*
347
 
348
@deftypefn Extension void expandargv (int *@var{argcp}, char ***@var{argvp})
349
 
350
The @var{argcp} and @code{argvp} arguments are pointers to the usual
351
@code{argc} and @code{argv} arguments to @code{main}.  This function
352
looks for arguments that begin with the character @samp{@@}.  Any such
353
arguments are interpreted as ``response files''.  The contents of the
354
response file are interpreted as additional command line options.  In
355
particular, the file is separated into whitespace-separated strings;
356
each such string is taken as a command-line option.  The new options
357
are inserted in place of the option naming the response file, and
358
@code{*argcp} and @code{*argvp} will be updated.  If the value of
359
@code{*argvp} is modified by this function, then the new value has
360
been dynamically allocated and can be deallocated by the caller with
361
@code{freeargv}.  However, most callers will simply call
362
@code{expandargv} near the beginning of @code{main} and allow the
363
operating system to free the memory when the program exits.
364
 
365
@end deftypefn
366
 
367
*/
368
 
369
void
370
expandargv (int *argcp, char ***argvp)
371
{
372
  /* The argument we are currently processing.  */
373
  int i = 0;
374
  /* Non-zero if ***argvp has been dynamically allocated.  */
375
  int argv_dynamic = 0;
376
  /* Loop over the arguments, handling response files.  We always skip
377
     ARGVP[0], as that is the name of the program being run.  */
378
  while (++i < *argcp)
379
    {
380
      /* The name of the response file.  */
381
      const char *filename;
382
      /* The response file.  */
383
      FILE *f;
384
      /* An upper bound on the number of characters in the response
385
         file.  */
386
      long pos;
387
      /* The number of characters in the response file, when actually
388
         read.  */
389
      size_t len;
390
      /* A dynamically allocated buffer used to hold options read from a
391
         response file.  */
392
      char *buffer;
393
      /* Dynamically allocated storage for the options read from the
394
         response file.  */
395
      char **file_argv;
396
      /* The number of options read from the response file, if any.  */
397
      size_t file_argc;
398
      /* We are only interested in options of the form "@file".  */
399
      filename = (*argvp)[i];
400
      if (filename[0] != '@')
401
        continue;
402
      /* Read the contents of the file.  */
403
      f = fopen (++filename, "r");
404
      if (!f)
405
        continue;
406
      if (fseek (f, 0L, SEEK_END) == -1)
407
        goto error;
408
      pos = ftell (f);
409
      if (pos == -1)
410
        goto error;
411
      if (fseek (f, 0L, SEEK_SET) == -1)
412
        goto error;
413
      buffer = (char *) xmalloc (pos * sizeof (char) + 1);
414
      len = fread (buffer, sizeof (char), pos, f);
415
      if (len != (size_t) pos
416
          /* On Windows, fread may return a value smaller than POS,
417
             due to CR/LF->CR translation when reading text files.
418
             That does not in-and-of itself indicate failure.  */
419
          && ferror (f))
420
        goto error;
421
      /* Add a NUL terminator.  */
422
      buffer[len] = '\0';
423
      /* Parse the string.  */
424
      file_argv = buildargv (buffer);
425
      /* If *ARGVP is not already dynamically allocated, copy it.  */
426
      if (!argv_dynamic)
427
        {
428
          *argvp = dupargv (*argvp);
429
          if (!*argvp)
430
            {
431
              fputs ("\nout of memory\n", stderr);
432
              xexit (1);
433
            }
434
        }
435
      /* Count the number of arguments.  */
436
      file_argc = 0;
437
      while (file_argv[file_argc] && *file_argv[file_argc])
438
        ++file_argc;
439
      /* Now, insert FILE_ARGV into ARGV.  The "+1" below handles the
440
         NULL terminator at the end of ARGV.  */
441
      *argvp = ((char **)
442
                xrealloc (*argvp,
443
                          (*argcp + file_argc + 1) * sizeof (char *)));
444
      memmove (*argvp + i + file_argc, *argvp + i + 1,
445
               (*argcp - i) * sizeof (char *));
446
      memcpy (*argvp + i, file_argv, file_argc * sizeof (char *));
447
      /* The original option has been replaced by all the new
448
         options.  */
449
      *argcp += file_argc - 1;
450
      /* Free up memory allocated to process the response file.  We do
451
         not use freeargv because the individual options in FILE_ARGV
452
         are now in the main ARGV.  */
453
      free (file_argv);
454
      free (buffer);
455
      /* Rescan all of the arguments just read to support response
456
         files that include other response files.  */
457
      --i;
458
    error:
459
      /* We're all done with the file now.  */
460
      fclose (f);
461
    }
462
}
463
 
464
#ifdef MAIN
465
 
466
/* Simple little test driver. */
467
 
468
static const char *const tests[] =
469
{
470
  "a simple command line",
471
  "arg 'foo' is single quoted",
472
  "arg \"bar\" is double quoted",
473
  "arg \"foo bar\" has embedded whitespace",
474
  "arg 'Jack said \\'hi\\'' has single quotes",
475
  "arg 'Jack said \\\"hi\\\"' has double quotes",
476
  "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",
477
 
478
  /* This should be expanded into only one argument.  */
479
  "trailing-whitespace ",
480
 
481
  "",
482
  NULL
483
};
484
 
485
int
486
main (void)
487
{
488
  char **argv;
489
  const char *const *test;
490
  char **targs;
491
 
492
  for (test = tests; *test != NULL; test++)
493
    {
494
      printf ("buildargv(\"%s\")\n", *test);
495
      if ((argv = buildargv (*test)) == NULL)
496
        {
497
          printf ("failed!\n\n");
498
        }
499
      else
500
        {
501
          for (targs = argv; *targs != NULL; targs++)
502
            {
503
              printf ("\t\"%s\"\n", *targs);
504
            }
505
          printf ("\n");
506
        }
507
      freeargv (argv);
508
    }
509
 
510
  return 0;
511
}
512
 
513
#endif  /* MAIN */

powered by: WebSVN 2.1.0

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