rpm  5.2.1
argv.c
Go to the documentation of this file.
1 
5 #include "system.h"
6 
7 #include "rpmio_internal.h" /* XXX fdGetFILE() */
8 #include <argv.h>
9 
10 #include "debug.h"
11 
12 /*@access FD_t @*/ /* XXX fdGetFILE() */
13 
14 void argvPrint(const char * msg, ARGV_t argv, FILE * fp)
15 {
16  ARGV_t av;
17 
18  if (fp == NULL) fp = stderr;
19 
20  if (msg)
21  fprintf(fp, "===================================== %s\n", msg);
22 
23  if (argv)
24  for (av = argv; *av; av++)
25  fprintf(fp, "\t%s\n", *av);
26 
27 }
28 
30 {
31  if (argi) {
32  argi->nvals = 0;
33  argi->vals = _free(argi->vals);
34  }
35  argi = _free(argi);
36  return NULL;
37 }
38 
39 ARGV_t argvFree(/*@only@*/ /*@null@*/ ARGV_t argv)
40 {
41  ARGV_t av;
42 
43  if (argv)
44  for (av = argv; *av; av++)
45  *av = _free(*av);
46  argv = _free(argv);
47  return NULL;
48 }
49 
50 int argiCount(ARGI_t argi)
51 {
52  int nvals = 0;
53  if (argi)
54  nvals = argi->nvals;
55  return nvals;
56 }
57 
59 {
60  ARGint_t vals = NULL;
61  if (argi && argi->nvals > 0)
62  vals = argi->vals;
63  return vals;
64 }
65 
66 int argvCount(const ARGV_t argv)
67 {
68  int argc = 0;
69  if (argv)
70  while (argv[argc] != NULL)
71  argc++;
72  return argc;
73 }
74 
76 {
77 /*@-retalias -temptrans @*/
78  return argv;
79 /*@=retalias =temptrans @*/
80 }
81 
82 int argiCmp(const void * a, const void * b)
83 {
84  unsigned aint = *(ARGint_t)a;
85  unsigned bint = *(ARGint_t)b;
86  return ((aint < bint) ? -1 :
87  (aint > bint) ? +1 : 0);
88 }
89 
90 int argvCmp(const void * a, const void * b)
91 {
92  ARGstr_t astr = *(ARGV_t)a;
93  ARGstr_t bstr = *(ARGV_t)b;
94  return strcmp(astr, bstr);
95 }
96 
97 int argvStrcasecmp(const void * a, const void * b)
98 {
99  ARGstr_t astr = *(ARGV_t)a;
100  ARGstr_t bstr = *(ARGV_t)b;
101  return xstrcasecmp(astr, bstr);
102 }
103 
104 #if defined(RPM_VENDOR_OPENPKG) /* wildcard-matching-arbitrary-tagnames */
105 int argvFnmatch(const void * a, const void * b)
106 {
107  ARGstr_t astr = *(ARGV_t)a;
108  ARGstr_t bstr = *(ARGV_t)b;
109  return (fnmatch(astr, bstr, 0) == 0 ? 0 : 1);
110 }
111 
112 int argvFnmatchCasefold(const void * a, const void * b)
113 {
114  ARGstr_t astr = *(ARGV_t)a;
115  ARGstr_t bstr = *(ARGV_t)b;
116  return (fnmatch(astr, bstr, FNM_CASEFOLD) == 0 ? 0 : 1);
117 }
118 #endif
119 
120 int argiSort(ARGI_t argi, int (*compar)(const void *, const void *))
121 {
122  unsigned nvals = argiCount(argi);
123  ARGint_t vals = argiData(argi);
124  if (compar == NULL)
125  compar = argiCmp;
126  if (nvals > 1)
127  qsort(vals, nvals, sizeof(*vals), compar);
128  return 0;
129 }
130 
131 int argvSort(ARGV_t argv, int (*compar)(const void *, const void *))
132 {
133  if (compar == NULL)
134  compar = argvCmp;
135  qsort(argv, argvCount(argv), sizeof(*argv), compar);
136  return 0;
137 }
138 
140  int (*compar)(const void *, const void *))
141 {
142  if (argv == NULL)
143  return NULL;
144  if (compar == NULL)
145  compar = argvCmp;
146  return bsearch(&val, argv, argvCount(argv), sizeof(*argv), compar);
147 }
148 
149 #if defined(RPM_VENDOR_OPENPKG) /* wildcard-matching-arbitrary-tagnames */
150 ARGV_t argvSearchLinear(ARGV_t argv, ARGstr_t val,
151  int (*compar)(const void *, const void *))
152 {
153  ARGV_t result;
154  ARGV_t av;
155  if (argv == NULL)
156  return NULL;
157  if (compar == NULL)
158  compar = argvCmp;
159  result = NULL;
160  for (av = argv; *av != NULL; av++) {
161  if (compar(av, &val) == 0) {
162  result = av;
163  break;
164  }
165  }
166  return result;
167 }
168 #endif
169 
170 int argiAdd(/*@out@*/ ARGI_t * argip, int ix, int val)
171 {
172  ARGI_t argi;
173 
174  if (argip == NULL)
175  return -1;
176  if (*argip == NULL)
177  *argip = xcalloc(1, sizeof(**argip));
178  argi = *argip;
179  if (ix < 0)
180  ix = argi->nvals;
181  if (ix >= (int)argi->nvals) {
182  argi->vals = xrealloc(argi->vals, (ix + 1) * sizeof(*argi->vals));
183  memset(argi->vals + argi->nvals, 0,
184  (ix - argi->nvals) * sizeof(*argi->vals));
185  argi->nvals = ix + 1;
186  }
187  argi->vals[ix] = val;
188  return 0;
189 }
190 
191 int argvAdd(/*@out@*/ ARGV_t * argvp, ARGstr_t val)
192 {
193  ARGV_t argv;
194  int argc;
195 
196  if (argvp == NULL)
197  return -1;
198  argc = argvCount(*argvp);
199 /*@-unqualifiedtrans@*/
200  *argvp = xrealloc(*argvp, (argc + 1 + 1) * sizeof(**argvp));
201 /*@=unqualifiedtrans@*/
202  argv = *argvp;
203  argv[argc++] = xstrdup(val);
204  argv[argc ] = NULL;
205  return 0;
206 }
207 
208 int argvAppend(/*@out@*/ ARGV_t * argvp, ARGV_t av)
209 {
210  int ac = argvCount(av);
211 
212  if (av != NULL && ac > 0) {
213  ARGV_t argv = *argvp;
214  int argc = argvCount(argv);
215 
216  argv = xrealloc(argv, (argc + ac + 1) * sizeof(*argv));
217  while (*av++)
218  argv[argc++] = xstrdup(av[-1]);
219  argv[argc] = NULL;
220  *argvp = argv;
221  }
222  return 0;
223 }
224 
225 int argvSplit(ARGV_t * argvp, const char * str, const char * seps)
226 {
227  static char whitespace[] = " \f\n\r\t\v";
228  char * dest = xmalloc(strlen(str) + 1);
229  ARGV_t argv;
230  int argc = 1;
231  const char * s;
232  char * t;
233  int c;
234 
235  if (seps == NULL)
236  seps = whitespace;
237 
238  for (argc = 1, s = str, t = dest; (c = (int) *s); s++, t++) {
239  if (strchr(seps, c) && !(s[0] == ':' && s[1] == '/' && s[2] == '/')) {
240  argc++;
241  c = (int) '\0';
242  }
243  *t = (char) c;
244  }
245  *t = '\0';
246 
247  argv = xmalloc( (argc + 1) * sizeof(*argv));
248 
249  for (c = 0, s = dest; s < t; s += strlen(s) + 1) {
250  /* XXX Skip repeated seperators (i.e. whitespace). */
251  if (seps == whitespace && s[0] == '\0')
252  continue;
253  argv[c++] = xstrdup(s);
254  }
255  argv[c] = NULL;
256  if (argvp)
257  *argvp = argv;
258  else
259  argv = argvFree(argv);
260  dest = _free(dest);
261 /*@-nullstate@*/
262  return 0;
263 /*@=nullstate@*/
264 }
265 
266 char * argvJoin(ARGV_t argv)
267 {
268  size_t nb = 0;
269  int argc;
270  char *t, *te;
271 
272  for (argc = 0; argv[argc] != NULL; argc++) {
273  if (argc != 0)
274  nb++;
275  nb += strlen(argv[argc]);
276  }
277  nb++;
278 
279  te = t = xmalloc(nb);
280  *te = '\0';
281  for (argc = 0; argv[argc] != NULL; argc++) {
282  if (argc != 0)
283  *te++ = ' ';
284  te = stpcpy(te, argv[argc]);
285  }
286  *te = '\0';
287  return t;
288 }
289 
290 /*@-mustmod@*/
291 int argvFgets(ARGV_t * argvp, void * fd)
292 {
293  FILE * fp = (fd ? fdGetFILE(fd) : stdin);
294  ARGV_t av = NULL;
295  char buf[BUFSIZ];
296  char * b, * be;
297  int rc = 0;
298 
299  if (fp == NULL)
300  return -2;
301  while (!rc && (b = fgets(buf, (int)sizeof(buf), fp)) != NULL) {
302  buf[sizeof(buf)-1] = '\0';
303  be = b + strlen(buf);
304  if (be > b) be--;
305  while (strchr("\r\n", *be) != NULL)
306  *be-- = '\0';
307  rc = argvAdd(&av, b);
308  }
309 
310  if (!rc)
311  rc = ferror(fp);
312  if (!rc)
313  rc = (feof(fp) ? 0 : 1);
314  if (!rc && argvp)
315  *argvp = av;
316  else
317  av = argvFree(av);
318 
319 /*@-nullstate@*/ /* XXX *argvp may be NULL. */
320  return rc;
321 /*@=nullstate@*/
322 }
323 /*@=mustmod@*/