Main Page Modules Data Structures File List Data Fields Globals Related Pages

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