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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gdb-7.2/] [libiberty/] [argv.c] - Blame information for rev 330

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

Line No. Rev Author Line
1 330 jeremybenn
/* 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
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
  /* Loop over the arguments, handling response files.  We always skip
390
     ARGVP[0], as that is the name of the program being run.  */
391
  while (++i < *argcp)
392
    {
393
      /* The name of the response file.  */
394
      const char *filename;
395
      /* The response file.  */
396
      FILE *f;
397
      /* An upper bound on the number of characters in the response
398
         file.  */
399
      long pos;
400
      /* The number of characters in the response file, when actually
401
         read.  */
402
      size_t len;
403
      /* A dynamically allocated buffer used to hold options read from a
404
         response file.  */
405
      char *buffer;
406
      /* Dynamically allocated storage for the options read from the
407
         response file.  */
408
      char **file_argv;
409
      /* The number of options read from the response file, if any.  */
410
      size_t file_argc;
411
      /* We are only interested in options of the form "@file".  */
412
      filename = (*argvp)[i];
413
      if (filename[0] != '@')
414
        continue;
415
      /* Read the contents of the file.  */
416
      f = fopen (++filename, "r");
417
      if (!f)
418
        continue;
419
      if (fseek (f, 0L, SEEK_END) == -1)
420
        goto error;
421
      pos = ftell (f);
422
      if (pos == -1)
423
        goto error;
424
      if (fseek (f, 0L, SEEK_SET) == -1)
425
        goto error;
426
      buffer = (char *) xmalloc (pos * sizeof (char) + 1);
427
      len = fread (buffer, sizeof (char), pos, f);
428
      if (len != (size_t) pos
429
          /* On Windows, fread may return a value smaller than POS,
430
             due to CR/LF->CR translation when reading text files.
431
             That does not in-and-of itself indicate failure.  */
432
          && ferror (f))
433
        goto error;
434
      /* Add a NUL terminator.  */
435
      buffer[len] = '\0';
436
      /* If the file is empty or contains only whitespace, buildargv would
437
         return a single empty argument.  In this context we want no arguments,
438
         instead.  */
439
      if (only_whitespace (buffer))
440
        {
441
          file_argv = (char **) xmalloc (sizeof (char *));
442
          file_argv[0] = NULL;
443
        }
444
      else
445
        /* Parse the string.  */
446
        file_argv = buildargv (buffer);
447
      /* If *ARGVP is not already dynamically allocated, copy it.  */
448
      if (!argv_dynamic)
449
        {
450
          *argvp = dupargv (*argvp);
451
          if (!*argvp)
452
            {
453
              fputs ("\nout of memory\n", stderr);
454
              xexit (1);
455
            }
456
        }
457
      /* Count the number of arguments.  */
458
      file_argc = 0;
459
      while (file_argv[file_argc])
460
        ++file_argc;
461
      /* Now, insert FILE_ARGV into ARGV.  The "+1" below handles the
462
         NULL terminator at the end of ARGV.  */
463
      *argvp = ((char **)
464
                xrealloc (*argvp,
465
                          (*argcp + file_argc + 1) * sizeof (char *)));
466
      memmove (*argvp + i + file_argc, *argvp + i + 1,
467
               (*argcp - i) * sizeof (char *));
468
      memcpy (*argvp + i, file_argv, file_argc * sizeof (char *));
469
      /* The original option has been replaced by all the new
470
         options.  */
471
      *argcp += file_argc - 1;
472
      /* Free up memory allocated to process the response file.  We do
473
         not use freeargv because the individual options in FILE_ARGV
474
         are now in the main ARGV.  */
475
      free (file_argv);
476
      free (buffer);
477
      /* Rescan all of the arguments just read to support response
478
         files that include other response files.  */
479
      --i;
480
    error:
481
      /* We're all done with the file now.  */
482
      fclose (f);
483
    }
484
}
485
 
486
#ifdef MAIN
487
 
488
/* Simple little test driver. */
489
 
490
static const char *const tests[] =
491
{
492
  "a simple command line",
493
  "arg 'foo' is single quoted",
494
  "arg \"bar\" is double quoted",
495
  "arg \"foo bar\" has embedded whitespace",
496
  "arg 'Jack said \\'hi\\'' has single quotes",
497
  "arg 'Jack said \\\"hi\\\"' has double quotes",
498
  "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",
499
 
500
  /* This should be expanded into only one argument.  */
501
  "trailing-whitespace ",
502
 
503
  "",
504
  NULL
505
};
506
 
507
int
508
main (void)
509
{
510
  char **argv;
511
  const char *const *test;
512
  char **targs;
513
 
514
  for (test = tests; *test != NULL; test++)
515
    {
516
      printf ("buildargv(\"%s\")\n", *test);
517
      if ((argv = buildargv (*test)) == NULL)
518
        {
519
          printf ("failed!\n\n");
520
        }
521
      else
522
        {
523
          for (targs = argv; *targs != NULL; targs++)
524
            {
525
              printf ("\t\"%s\"\n", *targs);
526
            }
527
          printf ("\n");
528
        }
529
      freeargv (argv);
530
    }
531
 
532
  return 0;
533
}
534
 
535
#endif  /* MAIN */

powered by: WebSVN 2.1.0

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