Annotation of GNUtools/libg++/libiberty/argv.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.