root/lib/popt/poptparse.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. poptDupArgv
  2. poptParseArgvString
  3. poptConfigFileToString

   1 /** \ingroup popt
   2  * \file popt/poptparse.c
   3  */
   4 
   5 /* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
   6    file accompanying popt source distributions, available from 
   7    ftp://ftp.rpm.org/pub/rpm/dist. */
   8 
   9 #include "system.h"
  10 
  11 #define POPT_ARGV_ARRAY_GROW_DELTA 5
  12 
  13 /*@-boundswrite@*/
  14 int poptDupArgv(int argc, const char **argv,
     /* [<][>][^][v][top][bottom][index][help] */
  15                 int * argcPtr, const char *** argvPtr)
  16 {
  17     size_t nb = (argc + 1) * sizeof(*argv);
  18     const char ** argv2;
  19     char * dst;
  20     int i;
  21 
  22     if (argc <= 0 || argv == NULL)      /* XXX can't happen */
  23         return POPT_ERROR_NOARG;
  24     for (i = 0; i < argc; i++) {
  25         if (argv[i] == NULL)
  26             return POPT_ERROR_NOARG;
  27         nb += strlen(argv[i]) + 1;
  28     }
  29         
  30     dst = (char *)malloc(nb);
  31     if (dst == NULL)                    /* XXX can't happen */
  32         return POPT_ERROR_MALLOC;
  33     argv2 = (const char **) dst;
  34     dst += (argc + 1) * sizeof(*argv);
  35 
  36     /*@-branchstate@*/
  37     for (i = 0; i < argc; i++) {
  38         argv2[i] = dst;
  39         dst += strlen(strcpy(dst, argv[i])) + 1;
  40     }
  41     /*@=branchstate@*/
  42     argv2[argc] = NULL;
  43 
  44     if (argvPtr) {
  45         *argvPtr = argv2;
  46     } else {
  47         free(argv2);
  48         argv2 = NULL;
  49     }
  50     if (argcPtr)
  51         *argcPtr = argc;
  52     return 0;
  53 }
  54 /*@=boundswrite@*/
  55 
  56 /*@-bounds@*/
  57 int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
     /* [<][>][^][v][top][bottom][index][help] */
  58 {
  59     const char * src;
  60     char quote = '\0';
  61     int argvAlloced = POPT_ARGV_ARRAY_GROW_DELTA;
  62     const char ** argv = (const char **)malloc(sizeof(*argv) * argvAlloced);
  63     int argc = 0;
  64     int buflen = strlen(s) + 1;
  65     char * buf = (char*)memset(alloca(buflen), 0, buflen);
  66     int rc = POPT_ERROR_MALLOC;
  67 
  68     if (argv == NULL) return rc;
  69     argv[argc] = buf;
  70 
  71     for (src = s; *src != '\0'; src++) {
  72         if (quote == *src) {
  73             quote = '\0';
  74         } else if (quote != '\0') {
  75             if (*src == '\\') {
  76                 src++;
  77                 if (!*src) {
  78                     rc = POPT_ERROR_BADQUOTE;
  79                     goto exit;
  80                 }
  81                 if (*src != quote) *buf++ = '\\';
  82             }
  83             *buf++ = *src;
  84         } else if (isspace(*src)) {
  85             if (*argv[argc] != '\0') {
  86                 buf++, argc++;
  87                 if (argc == argvAlloced) {
  88                     argvAlloced += POPT_ARGV_ARRAY_GROW_DELTA;
  89                     argv = (const char **)realloc(argv, sizeof(*argv) * argvAlloced);
  90                     if (argv == NULL) goto exit;
  91                 }
  92                 argv[argc] = buf;
  93             }
  94         } else switch (*src) {
  95           case '"':
  96           case '\'':
  97             quote = *src;
  98             /*@switchbreak@*/ break;
  99           case '\\':
 100             src++;
 101             if (!*src) {
 102                 rc = POPT_ERROR_BADQUOTE;
 103                 goto exit;
 104             }
 105             /*@fallthrough@*/
 106           default:
 107             *buf++ = *src;
 108             /*@switchbreak@*/ break;
 109         }
 110     }
 111 
 112     if (strlen(argv[argc])) {
 113         argc++, buf++;
 114     }
 115 
 116     rc = poptDupArgv(argc, argv, argcPtr, argvPtr);
 117 
 118 exit:
 119     if (argv) free(argv);
 120     return rc;
 121 }
 122 /*@=bounds@*/
 123 
 124 /* still in the dev stage.
 125  * return values, perhaps 1== file erro
 126  * 2== line to long
 127  * 3== umm.... more?
 128  */
 129 int poptConfigFileToString(FILE *fp, char ** argstrp, /*@unused@*/ int flags)
     /* [<][>][^][v][top][bottom][index][help] */
 130 {
 131     char line[999];
 132     char * argstr;
 133     char * p;
 134     char * q;
 135     char * x;
 136     int t;
 137     int argvlen = 0;
 138     size_t maxlinelen = sizeof(line);
 139     size_t linelen;
 140     int maxargvlen = 480;
 141     int linenum = 0;
 142 
 143     *argstrp = NULL;
 144 
 145     /*   |   this_is   =   our_line
 146      *       p             q      x
 147      */
 148 
 149     if (fp == NULL)
 150         return POPT_ERROR_NULLARG;
 151 
 152     argstr = (char *)calloc(maxargvlen, sizeof(*argstr));
 153     if (argstr == NULL) return POPT_ERROR_MALLOC;
 154 
 155     while (fgets(line, (int)maxlinelen, fp) != NULL) {
 156         linenum++;
 157         p = line;
 158 
 159         /* loop until first non-space char or EOL */
 160         while( *p != '\0' && isspace(*p) )
 161             p++;
 162 
 163         linelen = strlen(p);
 164         if (linelen >= maxlinelen-1)
 165             return POPT_ERROR_OVERFLOW; /* XXX line too long */
 166 
 167         if (*p == '\0' || *p == '\n') continue; /* line is empty */
 168         if (*p == '#') continue;                /* comment line */
 169 
 170         q = p;
 171 
 172         while (*q != '\0' && (!isspace(*q)) && *q != '=')
 173             q++;
 174 
 175         if (isspace(*q)) {
 176             /* a space after the name, find next non space */
 177             *q++='\0';
 178             while( *q != '\0' && isspace((int)*q) ) q++;
 179         }
 180         if (*q == '\0') {
 181             /* single command line option (ie, no name=val, just name) */
 182             q[-1] = '\0';               /* kill off newline from fgets() call */
 183             argvlen += (t = q - p) + (sizeof(" --")-1);
 184             if (argvlen >= maxargvlen) {
 185                 maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2;
 186                 argstr = (char *)realloc(argstr, maxargvlen);
 187                 if (argstr == NULL) return POPT_ERROR_MALLOC;
 188             }
 189             strcat(argstr, " --");
 190             strcat(argstr, p);
 191             continue;
 192         }
 193         if (*q != '=')
 194             continue;   /* XXX for now, silently ignore bogus line */
 195 
 196         /* *q is an equal sign. */
 197         *q++ = '\0';
 198 
 199         /* find next non-space letter of value */
 200         while (*q != '\0' && isspace(*q))
 201             q++;
 202         if (*q == '\0')
 203             continue;   /* XXX silently ignore missing value */
 204 
 205         /* now, loop and strip all ending whitespace */
 206         x = p + linelen;
 207         while (isspace(*--x))
 208             *x = 0;     /* null out last char if space (including fgets() NL) */
 209 
 210         /* rest of line accept */
 211         t = x - p;
 212         argvlen += t + (sizeof("' --='")-1);
 213         if (argvlen >= maxargvlen) {
 214             maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2;
 215             argstr = (char *)realloc(argstr, maxargvlen);
 216             if (argstr == NULL) return POPT_ERROR_MALLOC;
 217         }
 218         strcat(argstr, " --");
 219         strcat(argstr, p);
 220         strcat(argstr, "=\"");
 221         strcat(argstr, q);
 222         strcat(argstr, "\"");
 223     }
 224 
 225     *argstrp = argstr;
 226     return 0;
 227 }

/* [<][>][^][v][top][bottom][index][help] */