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

Generated on Thu Aug 30 14:33:19 2007 for popt by  doxygen 1.5.2