2 * \file popt/poptparse.c
5 /* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
6 file accompanying popt source distributions, available from
7 ftp://ftp.rpm.org/pub/rpm/dist. */
13 #define POPT_ARGV_ARRAY_GROW_DELTA 5
16 int poptDupArgv(int argc, const char **argv,
17 int * argcPtr, const char *** argvPtr)
19 size_t nb = (argc + 1) * sizeof(*argv);
24 if (argc <= 0 || argv == NULL) /* XXX can't happen */
25 return POPT_ERROR_NOARG;
26 for (i = 0; i < argc; i++) {
28 return POPT_ERROR_NOARG;
29 nb += strlen(argv[i]) + 1;
33 if (dst == NULL) /* XXX can't happen */
34 return POPT_ERROR_MALLOC;
36 dst += (argc + 1) * sizeof(*argv);
39 for (i = 0; i < argc; i++) {
41 dst += strlcpy(dst, argv[i], nb) + 1;
59 int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
63 int argvAlloced = POPT_ARGV_ARRAY_GROW_DELTA;
64 const char ** argv = malloc(sizeof(*argv) * argvAlloced);
66 int buflen = strlen(s) + 1;
67 char * buf = memset(alloca(buflen), 0, buflen);
68 int rc = POPT_ERROR_MALLOC;
70 if (argv == NULL) return rc;
73 for (src = s; *src != '\0'; src++) {
76 } else if (quote != '\0') {
80 rc = POPT_ERROR_BADQUOTE;
83 if (*src != quote) *buf++ = '\\';
86 } else if (isSpace(src)) {
87 if (*argv[argc] != '\0') {
89 if (argc == argvAlloced) {
90 argvAlloced += POPT_ARGV_ARRAY_GROW_DELTA;
91 argv = realloc(argv, sizeof(*argv) * argvAlloced);
92 if (argv == NULL) goto exit;
96 } else switch (*src) {
100 /*@switchbreak@*/ break;
104 rc = POPT_ERROR_BADQUOTE;
110 /*@switchbreak@*/ break;
114 if (strlen(argv[argc])) {
118 rc = poptDupArgv(argc, argv, argcPtr, argvPtr);
121 if (argv) free(argv);
126 /* still in the dev stage.
127 * return values, perhaps 1== file erro
131 int poptConfigFileToString(FILE *fp, char ** argstrp, /*@unused@*/ UNUSED(int flags))
140 size_t maxlinelen = sizeof(line);
142 int maxargvlen = 480;
147 /* | this_is = our_line
152 return POPT_ERROR_NULLARG;
154 argstr = calloc(maxargvlen, sizeof(*argstr));
155 if (argstr == NULL) return POPT_ERROR_MALLOC;
157 while (fgets(line, (int)maxlinelen, fp) != NULL) {
161 /* loop until first non-space char or EOL */
162 while( *p != '\0' && isSpace(p) )
166 if (linelen >= maxlinelen-1) {
168 return POPT_ERROR_OVERFLOW; /* XXX line too long */
171 if (*p == '\0' || *p == '\n') continue; /* line is empty */
172 if (*p == '#') continue; /* comment line */
176 while (*q != '\0' && (!isSpace(q)) && *q != '=')
180 /* a space after the name, find next non space */
182 while( *q != '\0' && isSpace(q) ) q++;
185 /* single command line option (ie, no name=val, just name) */
186 q[-1] = '\0'; /* kill off newline from fgets() call */
187 argvlen += (t = q - p) + (sizeof(" --")-1);
188 if (argvlen >= maxargvlen) {
189 maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2;
190 argstr = realloc(argstr, maxargvlen);
191 if (argstr == NULL) return POPT_ERROR_MALLOC;
193 strlcat(argstr, " --", maxargvlen);
194 strlcat(argstr, p, maxargvlen);
198 continue; /* XXX for now, silently ignore bogus line */
200 /* *q is an equal sign. */
203 /* find next non-space letter of value */
204 while (*q != '\0' && isSpace(q))
207 continue; /* XXX silently ignore missing value */
209 /* now, loop and strip all ending whitespace */
212 *x = 0; /* null out last char if space (including fgets() NL) */
214 /* rest of line accept */
216 argvlen += t + (sizeof("' --='")-1);
217 if (argvlen >= maxargvlen) {
218 maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2;
219 argstr = realloc(argstr, maxargvlen);
220 if (argstr == NULL) return POPT_ERROR_MALLOC;
222 strlcat(argstr, " --", maxargvlen);
223 strlcat(argstr, p, maxargvlen);
224 strlcat(argstr, "=\"", maxargvlen);
225 strlcat(argstr, q, maxargvlen);
226 strlcat(argstr, "\"", maxargvlen);