popt  1.14
poptparse.c
Go to the documentation of this file.
00001 
00005 /* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
00006    file accompanying popt source distributions, available from 
00007    ftp://ftp.rpm.org/pub/rpm/dist. */
00008 
00009 #include "system.h"
00010 
00011 #define POPT_ARGV_ARRAY_GROW_DELTA 5
00012 
00013 int poptDupArgv(int argc, const char **argv,
00014                 int * argcPtr, const char *** argvPtr)
00015 {
00016     size_t nb = (argc + 1) * sizeof(*argv);
00017     const char ** argv2;
00018     char * dst;
00019     int i;
00020 
00021     if (argc <= 0 || argv == NULL)      /* XXX can't happen */
00022         return POPT_ERROR_NOARG;
00023     for (i = 0; i < argc; i++) {
00024         if (argv[i] == NULL)
00025             return POPT_ERROR_NOARG;
00026         nb += strlen(argv[i]) + 1;
00027     }
00028         
00029     dst = malloc(nb);
00030     if (dst == NULL)                    /* XXX can't happen */
00031         return POPT_ERROR_MALLOC;
00032     argv2 = (void *) dst;
00033     dst += (argc + 1) * sizeof(*argv);
00034     *dst = '\0';
00035 
00036     for (i = 0; i < argc; i++) {
00037         argv2[i] = dst;
00038         dst = stpcpy(dst, argv[i]);
00039         dst++;  /* trailing NUL */
00040     }
00041     argv2[argc] = NULL;
00042 
00043     if (argvPtr) {
00044         *argvPtr = argv2;
00045     } else {
00046         free(argv2);
00047         argv2 = NULL;
00048     }
00049     if (argcPtr)
00050         *argcPtr = argc;
00051     return 0;
00052 }
00053 
00054 int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
00055 {
00056     const char * src;
00057     char quote = '\0';
00058     int argvAlloced = POPT_ARGV_ARRAY_GROW_DELTA;
00059     const char ** argv = malloc(sizeof(*argv) * argvAlloced);
00060     int argc = 0;
00061     size_t buflen = strlen(s) + 1;
00062     char * buf, * bufOrig = NULL;
00063     int rc = POPT_ERROR_MALLOC;
00064 
00065     if (argv == NULL) return rc;
00066     buf = bufOrig = calloc((size_t)1, buflen);
00067     if (buf == NULL) {
00068         free(argv);
00069         return rc;
00070     }
00071     argv[argc] = buf;
00072 
00073     for (src = s; *src != '\0'; src++) {
00074         if (quote == *src) {
00075             quote = '\0';
00076         } else if (quote != '\0') {
00077             if (*src == '\\') {
00078                 src++;
00079                 if (!*src) {
00080                     rc = POPT_ERROR_BADQUOTE;
00081                     goto exit;
00082                 }
00083                 if (*src != quote) *buf++ = '\\';
00084             }
00085             *buf++ = *src;
00086         } else if (_isspaceptr(src)) {
00087             if (*argv[argc] != '\0') {
00088                 buf++, argc++;
00089                 if (argc == argvAlloced) {
00090                     argvAlloced += POPT_ARGV_ARRAY_GROW_DELTA;
00091                     argv = realloc(argv, sizeof(*argv) * argvAlloced);
00092                     if (argv == NULL) goto exit;
00093                 }
00094                 argv[argc] = buf;
00095             }
00096         } else switch (*src) {
00097           case '"':
00098           case '\'':
00099             quote = *src;
00100             /*@switchbreak@*/ break;
00101           case '\\':
00102             src++;
00103             if (!*src) {
00104                 rc = POPT_ERROR_BADQUOTE;
00105                 goto exit;
00106             }
00107             /*@fallthrough@*/
00108           default:
00109             *buf++ = *src;
00110             /*@switchbreak@*/ break;
00111         }
00112     }
00113 
00114     if (strlen(argv[argc])) {
00115         argc++, buf++;
00116     }
00117 
00118     rc = poptDupArgv(argc, argv, argcPtr, argvPtr);
00119 
00120 exit:
00121     if (bufOrig) free(bufOrig);
00122     if (argv) free(argv);
00123     return rc;
00124 }
00125 
00126 /* still in the dev stage.
00127  * return values, perhaps 1== file erro
00128  * 2== line to long
00129  * 3== umm.... more?
00130  */
00131 int poptConfigFileToString(FILE *fp, char ** argstrp,
00132                 /*@unused@*/ UNUSED(int flags))
00133 {
00134     char line[999];
00135     char * argstr;
00136     char * p;
00137     char * q;
00138     char * x;
00139     size_t t;
00140     size_t argvlen = 0;
00141     size_t maxlinelen = sizeof(line);
00142     size_t linelen;
00143     size_t maxargvlen = (size_t)480;
00144 
00145     *argstrp = NULL;
00146 
00147     /*   |   this_is   =   our_line
00148      *       p             q      x
00149      */
00150 
00151     if (fp == NULL)
00152         return POPT_ERROR_NULLARG;
00153 
00154     argstr = calloc(maxargvlen, sizeof(*argstr));
00155     if (argstr == NULL) return POPT_ERROR_MALLOC;
00156 
00157     while (fgets(line, (int)maxlinelen, fp) != NULL) {
00158         p = line;
00159 
00160         /* loop until first non-space char or EOL */
00161         while( *p != '\0' && _isspaceptr(p) )
00162             p++;
00163 
00164         linelen = strlen(p);
00165         if (linelen >= maxlinelen-1) {
00166             free(argstr);
00167             return POPT_ERROR_OVERFLOW; /* XXX line too long */
00168         }
00169 
00170         if (*p == '\0' || *p == '\n') continue; /* line is empty */
00171         if (*p == '#') continue;                /* comment line */
00172 
00173         q = p;
00174 
00175         while (*q != '\0' && (!_isspaceptr(q)) && *q != '=')
00176             q++;
00177 
00178         if (_isspaceptr(q)) {
00179             /* a space after the name, find next non space */
00180             *q++='\0';
00181             while( *q != '\0' && _isspaceptr(q) ) q++;
00182         }
00183         if (*q == '\0') {
00184             /* single command line option (ie, no name=val, just name) */
00185             q[-1] = '\0';               /* kill off newline from fgets() call */
00186             argvlen += (t = (size_t)(q - p)) + (sizeof(" --")-1);
00187             if (argvlen >= maxargvlen) {
00188                 maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2;
00189                 argstr = realloc(argstr, maxargvlen);
00190                 if (argstr == NULL) return POPT_ERROR_MALLOC;
00191             }
00192             strcat(argstr, " --");
00193             strcat(argstr, p);
00194             continue;
00195         }
00196         if (*q != '=')
00197             continue;   /* XXX for now, silently ignore bogus line */
00198                 
00199         /* *q is an equal sign. */
00200         *q++ = '\0';
00201 
00202         /* find next non-space letter of value */
00203         while (*q != '\0' && _isspaceptr(q))
00204             q++;
00205         if (*q == '\0')
00206             continue;   /* XXX silently ignore missing value */
00207 
00208         /* now, loop and strip all ending whitespace */
00209         x = p + linelen;
00210         while (_isspaceptr(--x))
00211             *x = '\0';  /* null out last char if space (including fgets() NL) */
00212 
00213         /* rest of line accept */
00214         t = (size_t)(x - p);
00215         argvlen += t + (sizeof("' --='")-1);
00216         if (argvlen >= maxargvlen) {
00217             maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2;
00218             argstr = realloc(argstr, maxargvlen);
00219             if (argstr == NULL) return POPT_ERROR_MALLOC;
00220         }
00221         strcat(argstr, " --");
00222         strcat(argstr, p);
00223         strcat(argstr, "=\"");
00224         strcat(argstr, q);
00225         strcat(argstr, "\"");
00226     }
00227 
00228     *argstrp = argstr;
00229     return 0;
00230 }

Generated for popt by  doxygen 1.7.6.1