popt 1.13
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 
00035     for (i = 0; i < argc; i++) {
00036         argv2[i] = dst;
00037         dst += strlen(strcpy(dst, argv[i])) + 1;
00038     }
00039     argv2[argc] = NULL;
00040 
00041     if (argvPtr) {
00042         *argvPtr = argv2;
00043     } else {
00044         free(argv2);
00045         argv2 = NULL;
00046     }
00047     if (argcPtr)
00048         *argcPtr = argc;
00049     return 0;
00050 }
00051 
00052 int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
00053 {
00054     const char * src;
00055     char quote = '\0';
00056     int argvAlloced = POPT_ARGV_ARRAY_GROW_DELTA;
00057     const char ** argv = malloc(sizeof(*argv) * argvAlloced);
00058     int argc = 0;
00059     size_t buflen = strlen(s) + 1;
00060     char * buf, * bufOrig = NULL;
00061     int rc = POPT_ERROR_MALLOC;
00062 
00063     if (argv == NULL) return rc;
00064     buf = bufOrig = calloc(1, buflen);
00065     if (buf == NULL) {
00066         free(argv);
00067         return rc;
00068     }
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 (_isspaceptr(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 (bufOrig) free(bufOrig);
00120     if (argv) free(argv);
00121     return rc;
00122 }
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     size_t t;
00137     size_t argvlen = 0;
00138     size_t maxlinelen = sizeof(line);
00139     size_t linelen;
00140     size_t maxargvlen = (size_t)480;
00141 
00142     *argstrp = NULL;
00143 
00144     /*   |   this_is   =   our_line
00145      *       p             q      x
00146      */
00147 
00148     if (fp == NULL)
00149         return POPT_ERROR_NULLARG;
00150 
00151     argstr = calloc(maxargvlen, sizeof(*argstr));
00152     if (argstr == NULL) return POPT_ERROR_MALLOC;
00153 
00154     while (fgets(line, (int)maxlinelen, fp) != NULL) {
00155         p = line;
00156 
00157         /* loop until first non-space char or EOL */
00158         while( *p != '\0' && _isspaceptr(p) )
00159             p++;
00160 
00161         linelen = strlen(p);
00162         if (linelen >= maxlinelen-1) {
00163             free(argstr);
00164             return POPT_ERROR_OVERFLOW; /* XXX line too long */
00165         }
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' && (!_isspaceptr(q)) && *q != '=')
00173             q++;
00174 
00175         if (_isspaceptr(q)) {
00176             /* a space after the name, find next non space */
00177             *q++='\0';
00178             while( *q != '\0' && _isspaceptr(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' && _isspaceptr(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 (_isspaceptr(--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 }

Generated for popt by  doxygen 1.7.4