home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1999 March / PCWK3A99.iso / Linux / DDD331 / DDD-3_1_.000 / DDD-3_1_ / ddd-3.1.1 / libiberty / argv.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-12-15  |  8.1 KB  |  391 lines

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