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 }

Generated on Wed Jan 28 12:45:25 2009 for rpm by  doxygen 1.4.7