~ubuntu-branches/ubuntu/dapper/gnats/dapper

« back to all changes in this revision

Viewing changes to libiberty/argv.c

  • Committer: Bazaar Package Importer
  • Author(s): Chad Walstrom
  • Date: 2005-03-07 17:56:31 UTC
  • mfrom: (1.1.1 upstream) (2.1.1 hoary)
  • Revision ID: james.westby@ubuntu.com-20050307175631-agtm10dvjbemuc64
Tags: 4.1.0-0
* New upstream version
* debian/rules: now uses '--with-lispdir' option instead of environment
  variable overloading. Re-enabled optimization.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Create and destroy argument vectors (argv's)
2
 
   Copyright (C) 1992 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., 59 Temple Place - Suite 330,
19
 
Boston, MA 02111-1307, 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
 
#include "ansidecl.h"
26
 
#include "libiberty.h"
27
 
 
28
 
#define ISBLANK(ch) ((ch) == ' ' || (ch) == '\t')
29
 
 
30
 
/*  Routines imported from standard C runtime libraries. */
31
 
 
32
 
#ifdef __STDC__
33
 
 
34
 
#include <stddef.h>
35
 
#include <string.h>
36
 
#include <stdlib.h>
37
 
 
38
 
#else   /* !__STDC__ */
39
 
 
40
 
#if !defined _WIN32 || defined __GNUC__
41
 
extern char *memcpy ();         /* Copy memory region */
42
 
extern int strlen ();           /* Count length of string */
43
 
extern char *malloc ();         /* Standard memory allocater */
44
 
extern char *realloc ();        /* Standard memory reallocator */
45
 
extern void free ();            /* Free malloc'd memory */
46
 
extern char *strdup ();         /* Duplicate a string */
47
 
#endif
48
 
 
49
 
#endif  /* __STDC__ */
50
 
 
51
 
#include "alloca-conf.h"
52
 
 
53
 
#ifndef NULL
54
 
#define NULL 0
55
 
#endif
56
 
 
57
 
#ifndef EOS
58
 
#define EOS '\0'
59
 
#endif
60
 
 
61
 
#define INITIAL_MAXARGC 8       /* Number of args + NULL in initial argv */
62
 
 
63
 
 
64
 
/*
65
 
 
66
 
NAME
67
 
 
68
 
        dupargv -- duplicate an argument vector
69
 
 
70
 
SYNOPSIS
71
 
 
72
 
        char **dupargv (vector)
73
 
        char **vector;
74
 
 
75
 
DESCRIPTION
76
 
 
77
 
        Duplicate an argument vector.  Simply scans through the
78
 
        vector, duplicating each argument until the
79
 
        terminating NULL is found.
80
 
 
81
 
RETURNS
82
 
 
83
 
        Returns a pointer to the argument vector if
84
 
        successful. Returns NULL if there is insufficient memory to
85
 
        complete building the argument vector.
86
 
 
87
 
*/
88
 
 
89
 
char **
90
 
dupargv (argv)
91
 
     char **argv;
92
 
{
93
 
  int argc;
94
 
  char **copy;
95
 
  
96
 
  if (argv == NULL)
97
 
    return NULL;
98
 
  
99
 
  /* the vector */
100
 
  for (argc = 0; argv[argc] != NULL; argc++);
101
 
  copy = (char **) malloc ((argc + 1) * sizeof (char *));
102
 
  if (copy == NULL)
103
 
    return NULL;
104
 
  
105
 
  /* the strings */
106
 
  for (argc = 0; argv[argc] != NULL; argc++)
107
 
    {
108
 
      int len = strlen (argv[argc]);
109
 
      copy[argc] = malloc (sizeof (char *) * (len + 1));
110
 
      if (copy[argc] == NULL)
111
 
        {
112
 
          freeargv (copy);
113
 
          return NULL;
114
 
        }
115
 
      strcpy (copy[argc], argv[argc]);
116
 
    }
117
 
  copy[argc] = NULL;
118
 
  return copy;
119
 
}
120
 
 
121
 
/*
122
 
 
123
 
NAME
124
 
 
125
 
        freeargv -- free an argument vector
126
 
 
127
 
SYNOPSIS
128
 
 
129
 
        void freeargv (vector)
130
 
        char **vector;
131
 
 
132
 
DESCRIPTION
133
 
 
134
 
        Free an argument vector that was built using buildargv.  Simply scans
135
 
        through the vector, freeing the memory for each argument until the
136
 
        terminating NULL is found, and then frees the vector itself.
137
 
 
138
 
RETURNS
139
 
 
140
 
        No value.
141
 
 
142
 
*/
143
 
 
144
 
void freeargv (vector)
145
 
char **vector;
146
 
{
147
 
  register char **scan;
148
 
 
149
 
  if (vector != NULL)
150
 
    {
151
 
      for (scan = vector; *scan != NULL; scan++)
152
 
        {
153
 
          free (*scan);
154
 
        }
155
 
      free (vector);
156
 
    }
157
 
}
158
 
 
159
 
/*
160
 
 
161
 
NAME
162
 
 
163
 
        buildargv -- build an argument vector from a string
164
 
 
165
 
SYNOPSIS
166
 
 
167
 
        char **buildargv (sp)
168
 
        char *sp;
169
 
 
170
 
DESCRIPTION
171
 
 
172
 
        Given a pointer to a string, parse the string extracting fields
173
 
        separated by whitespace and optionally enclosed within either single
174
 
        or double quotes (which are stripped off), and build a vector of
175
 
        pointers to copies of the string for each field.  The input string
176
 
        remains unchanged.
177
 
 
178
 
        All of the memory for the pointer array and copies of the string
179
 
        is obtained from malloc.  All of the memory can be returned to the
180
 
        system with the single function call freeargv, which takes the
181
 
        returned result of buildargv, as it's argument.
182
 
 
183
 
        The memory for the argv array is dynamically expanded as necessary.
184
 
 
185
 
RETURNS
186
 
 
187
 
        Returns a pointer to the argument vector if successful. Returns NULL
188
 
        if the input string pointer is NULL or if there is insufficient
189
 
        memory to complete building the argument vector.
190
 
 
191
 
NOTES
192
 
 
193
 
        In order to provide a working buffer for extracting arguments into,
194
 
        with appropriate stripping of quotes and translation of backslash
195
 
        sequences, we allocate a working buffer at least as long as the input
196
 
        string.  This ensures that we always have enough space in which to
197
 
        work, since the extracted arg is never larger than the input string.
198
 
 
199
 
        If the input is a null string (as opposed to a NULL pointer), then
200
 
        buildarg returns an argv that has one arg, a null string.
201
 
 
202
 
        Argv is always kept terminated with a NULL arg pointer, so it can
203
 
        be passed to freeargv at any time, or returned, as appropriate.
204
 
*/
205
 
 
206
 
char **buildargv (input)
207
 
char *input;
208
 
{
209
 
  char *arg;
210
 
  char *copybuf;
211
 
  int squote = 0;
212
 
  int dquote = 0;
213
 
  int bsquote = 0;
214
 
  int argc = 0;
215
 
  int maxargc = 0;
216
 
  char **argv = NULL;
217
 
  char **nargv;
218
 
 
219
 
  if (input != NULL)
220
 
    {
221
 
      copybuf = (char *) alloca (strlen (input) + 1);
222
 
      /* Is a do{}while to always execute the loop once.  Always return an
223
 
         argv, even for null strings.  See NOTES above, test case below. */
224
 
      do
225
 
        {
226
 
          /* Pick off argv[argc] */
227
 
          while (ISBLANK (*input))
228
 
            {
229
 
              input++;
230
 
            }
231
 
          if ((maxargc == 0) || (argc >= (maxargc - 1)))
232
 
            {
233
 
              /* argv needs initialization, or expansion */
234
 
              if (argv == NULL)
235
 
                {
236
 
                  maxargc = INITIAL_MAXARGC;
237
 
                  nargv = (char **) malloc (maxargc * sizeof (char *));
238
 
                }
239
 
              else
240
 
                {
241
 
                  maxargc *= 2;
242
 
                  nargv = (char **) realloc (argv, maxargc * sizeof (char *));
243
 
                }
244
 
              if (nargv == NULL)
245
 
                {
246
 
                  if (argv != NULL)
247
 
                    {
248
 
                      freeargv (argv);
249
 
                      argv = NULL;
250
 
                    }
251
 
                  break;
252
 
                }
253
 
              argv = nargv;
254
 
              argv[argc] = NULL;
255
 
            }
256
 
          /* Begin scanning arg */
257
 
          arg = copybuf;
258
 
          while (*input != EOS)
259
 
            {
260
 
              if (ISBLANK (*input) && !squote && !dquote && !bsquote)
261
 
                {
262
 
                  break;
263
 
                }
264
 
              else
265
 
                {
266
 
                  if (bsquote)
267
 
                    {
268
 
                      bsquote = 0;
269
 
                      *arg++ = *input;
270
 
                    }
271
 
                  else if (*input == '\\')
272
 
                    {
273
 
                      bsquote = 1;
274
 
                    }
275
 
                  else if (squote)
276
 
                    {
277
 
                      if (*input == '\'')
278
 
                        {
279
 
                          squote = 0;
280
 
                        }
281
 
                      else
282
 
                        {
283
 
                          *arg++ = *input;
284
 
                        }
285
 
                    }
286
 
                  else if (dquote)
287
 
                    {
288
 
                      if (*input == '"')
289
 
                        {
290
 
                          dquote = 0;
291
 
                        }
292
 
                      else
293
 
                        {
294
 
                          *arg++ = *input;
295
 
                        }
296
 
                    }
297
 
                  else
298
 
                    {
299
 
                      if (*input == '\'')
300
 
                        {
301
 
                          squote = 1;
302
 
                        }
303
 
                      else if (*input == '"')
304
 
                        {
305
 
                          dquote = 1;
306
 
                        }
307
 
                      else
308
 
                        {
309
 
                          *arg++ = *input;
310
 
                        }
311
 
                    }
312
 
                  input++;
313
 
                }
314
 
            }
315
 
          *arg = EOS;
316
 
          argv[argc] = strdup (copybuf);
317
 
          if (argv[argc] == NULL)
318
 
            {
319
 
              freeargv (argv);
320
 
              argv = NULL;
321
 
              break;
322
 
            }
323
 
          argc++;
324
 
          argv[argc] = NULL;
325
 
 
326
 
          while (ISBLANK (*input))
327
 
            {
328
 
              input++;
329
 
            }
330
 
        }
331
 
      while (*input != EOS);
332
 
    }
333
 
  return (argv);
334
 
}
335
 
 
336
 
#ifdef MAIN
337
 
 
338
 
/* Simple little test driver. */
339
 
 
340
 
static char *tests[] =
341
 
{
342
 
  "a simple command line",
343
 
  "arg 'foo' is single quoted",
344
 
  "arg \"bar\" is double quoted",
345
 
  "arg \"foo bar\" has embedded whitespace",
346
 
  "arg 'Jack said \\'hi\\'' has single quotes",
347
 
  "arg 'Jack said \\\"hi\\\"' has double quotes",
348
 
  "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",
349
 
  
350
 
  /* This should be expanded into only one argument.  */
351
 
  "trailing-whitespace ",
352
 
 
353
 
  "",
354
 
  NULL
355
 
};
356
 
 
357
 
main ()
358
 
{
359
 
  char **argv;
360
 
  char **test;
361
 
  char **targs;
362
 
 
363
 
  for (test = tests; *test != NULL; test++)
364
 
    {
365
 
      printf ("buildargv(\"%s\")\n", *test);
366
 
      if ((argv = buildargv (*test)) == NULL)
367
 
        {
368
 
          printf ("failed!\n\n");
369
 
        }
370
 
      else
371
 
        {
372
 
          for (targs = argv; *targs != NULL; targs++)
373
 
            {
374
 
              printf ("\t\"%s\"\n", *targs);
375
 
            }
376
 
          printf ("\n");
377
 
        }
378
 
      freeargv (argv);
379
 
    }
380
 
 
381
 
}
382
 
 
383
 
#endif  /* MAIN */