popt  1.13
poptparse.c
Go to the documentation of this file.
1 
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. */
8 
9 #include "system.h"
10 
11 #define POPT_ARGV_ARRAY_GROW_DELTA 5
12 
13 int poptDupArgv(int argc, const char **argv,
14  int * argcPtr, const char *** argvPtr)
15 {
16  size_t nb = (argc + 1) * sizeof(*argv);
17  const char ** argv2;
18  char * dst;
19  int i;
20 
21  if (argc <= 0 || argv == NULL) /* XXX can't happen */
22  return POPT_ERROR_NOARG;
23  for (i = 0; i < argc; i++) {
24  if (argv[i] == NULL)
25  return POPT_ERROR_NOARG;
26  nb += strlen(argv[i]) + 1;
27  }
28 
29  dst = malloc(nb);
30  if (dst == NULL) /* XXX can't happen */
31  return POPT_ERROR_MALLOC;
32  argv2 = (void *) dst;
33  dst += (argc + 1) * sizeof(*argv);
34 
35  for (i = 0; i < argc; i++) {
36  argv2[i] = dst;
37  dst += strlen(strcpy(dst, argv[i])) + 1;
38  }
39  argv2[argc] = NULL;
40 
41  if (argvPtr) {
42  *argvPtr = argv2;
43  } else {
44  free(argv2);
45  argv2 = NULL;
46  }
47  if (argcPtr)
48  *argcPtr = argc;
49  return 0;
50 }
51 
52 int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
53 {
54  const char * src;
55  char quote = '\0';
56  int argvAlloced = POPT_ARGV_ARRAY_GROW_DELTA;
57  const char ** argv = malloc(sizeof(*argv) * argvAlloced);
58  int argc = 0;
59  size_t buflen = strlen(s) + 1;
60  char * buf, * bufOrig = NULL;
61  int rc = POPT_ERROR_MALLOC;
62 
63  if (argv == NULL) return rc;
64  buf = bufOrig = calloc(1, buflen);
65  if (buf == NULL) {
66  free(argv);
67  return rc;
68  }
69  argv[argc] = buf;
70 
71  for (src = s; *src != '\0'; src++) {
72  if (quote == *src) {
73  quote = '\0';
74  } else if (quote != '\0') {
75  if (*src == '\\') {
76  src++;
77  if (!*src) {
79  goto exit;
80  }
81  if (*src != quote) *buf++ = '\\';
82  }
83  *buf++ = *src;
84  } else if (_isspaceptr(src)) {
85  if (*argv[argc] != '\0') {
86  buf++, argc++;
87  if (argc == argvAlloced) {
88  argvAlloced += POPT_ARGV_ARRAY_GROW_DELTA;
89  argv = realloc(argv, sizeof(*argv) * argvAlloced);
90  if (argv == NULL) goto exit;
91  }
92  argv[argc] = buf;
93  }
94  } else switch (*src) {
95  case '"':
96  case '\'':
97  quote = *src;
98  /*@switchbreak@*/ break;
99  case '\\':
100  src++;
101  if (!*src) {
102  rc = POPT_ERROR_BADQUOTE;
103  goto exit;
104  }
105  /*@fallthrough@*/
106  default:
107  *buf++ = *src;
108  /*@switchbreak@*/ break;
109  }
110  }
111 
112  if (strlen(argv[argc])) {
113  argc++, buf++;
114  }
115 
116  rc = poptDupArgv(argc, argv, argcPtr, argvPtr);
117 
118 exit:
119  if (bufOrig) free(bufOrig);
120  if (argv) free(argv);
121  return rc;
122 }
123 
124 /* still in the dev stage.
125  * return values, perhaps 1== file erro
126  * 2== line to long
127  * 3== umm.... more?
128  */
129 int poptConfigFileToString(FILE *fp, char ** argstrp, /*@unused@*/ int flags)
130 {
131  char line[999];
132  char * argstr;
133  char * p;
134  char * q;
135  char * x;
136  size_t t;
137  size_t argvlen = 0;
138  size_t maxlinelen = sizeof(line);
139  size_t linelen;
140  size_t maxargvlen = (size_t)480;
141 
142  *argstrp = NULL;
143 
144  /* | this_is = our_line
145  * p q x
146  */
147 
148  if (fp == NULL)
149  return POPT_ERROR_NULLARG;
150 
151  argstr = calloc(maxargvlen, sizeof(*argstr));
152  if (argstr == NULL) return POPT_ERROR_MALLOC;
153 
154  while (fgets(line, (int)maxlinelen, fp) != NULL) {
155  p = line;
156 
157  /* loop until first non-space char or EOL */
158  while( *p != '\0' && _isspaceptr(p) )
159  p++;
160 
161  linelen = strlen(p);
162  if (linelen >= maxlinelen-1) {
163  free(argstr);
164  return POPT_ERROR_OVERFLOW; /* XXX line too long */
165  }
166 
167  if (*p == '\0' || *p == '\n') continue; /* line is empty */
168  if (*p == '#') continue; /* comment line */
169 
170  q = p;
171 
172  while (*q != '\0' && (!_isspaceptr(q)) && *q != '=')
173  q++;
174 
175  if (_isspaceptr(q)) {
176  /* a space after the name, find next non space */
177  *q++='\0';
178  while( *q != '\0' && _isspaceptr(q) ) q++;
179  }
180  if (*q == '\0') {
181  /* single command line option (ie, no name=val, just name) */
182  q[-1] = '\0'; /* kill off newline from fgets() call */
183  argvlen += (t = q - p) + (sizeof(" --")-1);
184  if (argvlen >= maxargvlen) {
185  maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2;
186  argstr = realloc(argstr, maxargvlen);
187  if (argstr == NULL) return POPT_ERROR_MALLOC;
188  }
189  strcat(argstr, " --");
190  strcat(argstr, p);
191  continue;
192  }
193  if (*q != '=')
194  continue; /* XXX for now, silently ignore bogus line */
195 
196  /* *q is an equal sign. */
197  *q++ = '\0';
198 
199  /* find next non-space letter of value */
200  while (*q != '\0' && _isspaceptr(q))
201  q++;
202  if (*q == '\0')
203  continue; /* XXX silently ignore missing value */
204 
205  /* now, loop and strip all ending whitespace */
206  x = p + linelen;
207  while (_isspaceptr(--x))
208  *x = '\0'; /* null out last char if space (including fgets() NL) */
209 
210  /* rest of line accept */
211  t = x - p;
212  argvlen += t + (sizeof("' --='")-1);
213  if (argvlen >= maxargvlen) {
214  maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2;
215  argstr = realloc(argstr, maxargvlen);
216  if (argstr == NULL) return POPT_ERROR_MALLOC;
217  }
218  strcat(argstr, " --");
219  strcat(argstr, p);
220  strcat(argstr, "=\"");
221  strcat(argstr, q);
222  strcat(argstr, "\"");
223  }
224 
225  *argstrp = argstr;
226  return 0;
227 }

Generated for popt by  doxygen 1.8.1.2