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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [libiberty/] [argv.c] - Blame information for rev 823

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 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
      /* An upper bound on the number of characters in the response
332
         file.  */
333
      long pos;
334
      /* The number of characters in the response file, when actually
335
         read.  */
336
      size_t len;
337
      /* A dynamically allocated buffer used to hold options read from a
338
         response file.  */
339
      char *buffer;
340
      /* Dynamically allocated storage for the options read from the
341
         response file.  */
342
      char **file_argv;
343
      /* The number of options read from the response file, if any.  */
344
      size_t file_argc;
345
      /* We are only interested in options of the form "@file".  */
346
      filename = (*argvp)[i];
347
      if (filename[0] != '@')
348
        continue;
349
      /* Read the contents of the file.  */
350
      f = fopen (++filename, "r");
351
      if (!f)
352
        continue;
353
      if (fseek (f, 0L, SEEK_END) == -1)
354
        goto error;
355
      pos = ftell (f);
356
      if (pos == -1)
357
        goto error;
358
      if (fseek (f, 0L, SEEK_SET) == -1)
359
        goto error;
360
      buffer = (char *) xmalloc (pos * sizeof (char) + 1);
361
      len = fread (buffer, sizeof (char), pos, f);
362
      if (len != (size_t) pos
363
          /* On Windows, fread may return a value smaller than POS,
364
             due to CR/LF->CR translation when reading text files.
365
             That does not in-and-of itself indicate failure.  */
366
          && ferror (f))
367
        goto error;
368
      /* Add a NUL terminator.  */
369
      buffer[len] = '\0';
370
      /* Parse the string.  */
371
      file_argv = buildargv (buffer);
372
      /* If *ARGVP is not already dynamically allocated, copy it.  */
373
      if (!argv_dynamic)
374
        {
375
          *argvp = dupargv (*argvp);
376
          if (!*argvp)
377
            {
378
              fputs ("\nout of memory\n", stderr);
379
              xexit (1);
380
            }
381
        }
382
      /* Count the number of arguments.  */
383
      file_argc = 0;
384
      while (file_argv[file_argc] && *file_argv[file_argc])
385
        ++file_argc;
386
      /* Now, insert FILE_ARGV into ARGV.  The "+1" below handles the
387
         NULL terminator at the end of ARGV.  */
388
      *argvp = ((char **)
389
                xrealloc (*argvp,
390
                          (*argcp + file_argc + 1) * sizeof (char *)));
391
      memmove (*argvp + i + file_argc, *argvp + i + 1,
392
               (*argcp - i) * sizeof (char *));
393
      memcpy (*argvp + i, file_argv, file_argc * sizeof (char *));
394
      /* The original option has been replaced by all the new
395
         options.  */
396
      *argcp += file_argc - 1;
397
      /* Free up memory allocated to process the response file.  We do
398
         not use freeargv because the individual options in FILE_ARGV
399
         are now in the main ARGV.  */
400
      free (file_argv);
401
      free (buffer);
402
      /* Rescan all of the arguments just read to support response
403
         files that include other response files.  */
404
      --i;
405
    error:
406
      /* We're all done with the file now.  */
407
      fclose (f);
408
    }
409
}
410
 
411
#ifdef MAIN
412
 
413
/* Simple little test driver. */
414
 
415
static const char *const tests[] =
416
{
417
  "a simple command line",
418
  "arg 'foo' is single quoted",
419
  "arg \"bar\" is double quoted",
420
  "arg \"foo bar\" has embedded whitespace",
421
  "arg 'Jack said \\'hi\\'' has single quotes",
422
  "arg 'Jack said \\\"hi\\\"' has double quotes",
423
  "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",
424
 
425
  /* This should be expanded into only one argument.  */
426
  "trailing-whitespace ",
427
 
428
  "",
429
  NULL
430
};
431
 
432
int
433
main (void)
434
{
435
  char **argv;
436
  const char *const *test;
437
  char **targs;
438
 
439
  for (test = tests; *test != NULL; test++)
440
    {
441
      printf ("buildargv(\"%s\")\n", *test);
442
      if ((argv = buildargv (*test)) == NULL)
443
        {
444
          printf ("failed!\n\n");
445
        }
446
      else
447
        {
448
          for (targs = argv; *targs != NULL; targs++)
449
            {
450
              printf ("\t\"%s\"\n", *targs);
451
            }
452
          printf ("\n");
453
        }
454
      freeargv (argv);
455
    }
456
 
457
  return 0;
458
}
459
 
460
#endif  /* MAIN */

powered by: WebSVN 2.1.0

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