Commit | Line | Data |
---|---|---|
cc248aae WD |
1 | /** \ingroup popt |
2 | * \file popt/poptparse.c | |
3 | */ | |
4 | ||
5 | /* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING | |
62402cb1 | 6 | file accompanying popt source distributions, available from |
cc248aae | 7 | ftp://ftp.rpm.org/pub/rpm/dist. */ |
62402cb1 | 8 | |
b348deae | 9 | #include "system.h" |
62402cb1 | 10 | |
b348deae | 11 | #define POPT_ARGV_ARRAY_GROW_DELTA 5 |
62402cb1 | 12 | |
b348deae MP |
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 | ||
cc248aae WD |
21 | if (argc <= 0 || argv == NULL) /* XXX can't happen */ |
22 | return POPT_ERROR_NOARG; | |
b348deae MP |
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); | |
cc248aae WD |
30 | if (dst == NULL) /* XXX can't happen */ |
31 | return POPT_ERROR_MALLOC; | |
b348deae MP |
32 | argv2 = (void *) dst; |
33 | dst += (argc + 1) * sizeof(*argv); | |
34 | ||
cc248aae | 35 | /*@-branchstate@*/ |
b348deae MP |
36 | for (i = 0; i < argc; i++) { |
37 | argv2[i] = dst; | |
38 | dst += strlen(strcpy(dst, argv[i])) + 1; | |
39 | } | |
cc248aae | 40 | /*@=branchstate@*/ |
b348deae MP |
41 | argv2[argc] = NULL; |
42 | ||
cc248aae WD |
43 | if (argvPtr) { |
44 | *argvPtr = argv2; | |
45 | } else { | |
46 | free(argv2); | |
47 | argv2 = NULL; | |
48 | } | |
49 | if (argcPtr) | |
50 | *argcPtr = argc; | |
b348deae MP |
51 | return 0; |
52 | } | |
62402cb1 | 53 | |
b348deae MP |
54 | int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr) |
55 | { | |
56 | const char * src; | |
62402cb1 | 57 | char quote = '\0'; |
b348deae MP |
58 | int argvAlloced = POPT_ARGV_ARRAY_GROW_DELTA; |
59 | const char ** argv = malloc(sizeof(*argv) * argvAlloced); | |
62402cb1 | 60 | int argc = 0; |
b348deae | 61 | int buflen = strlen(s) + 1; |
cc248aae WD |
62 | char * buf = memset(alloca(buflen), 0, buflen); |
63 | int rc = POPT_ERROR_MALLOC; | |
62402cb1 | 64 | |
cc248aae | 65 | if (argv == NULL) return rc; |
62402cb1 MP |
66 | argv[argc] = buf; |
67 | ||
cc248aae | 68 | for (src = s; *src != '\0'; src++) { |
62402cb1 MP |
69 | if (quote == *src) { |
70 | quote = '\0'; | |
cc248aae | 71 | } else if (quote != '\0') { |
62402cb1 MP |
72 | if (*src == '\\') { |
73 | src++; | |
74 | if (!*src) { | |
cc248aae WD |
75 | rc = POPT_ERROR_BADQUOTE; |
76 | goto exit; | |
62402cb1 MP |
77 | } |
78 | if (*src != quote) *buf++ = '\\'; | |
79 | } | |
80 | *buf++ = *src; | |
81 | } else if (isspace(*src)) { | |
cc248aae | 82 | if (*argv[argc] != '\0') { |
62402cb1 MP |
83 | buf++, argc++; |
84 | if (argc == argvAlloced) { | |
b348deae | 85 | argvAlloced += POPT_ARGV_ARRAY_GROW_DELTA; |
62402cb1 | 86 | argv = realloc(argv, sizeof(*argv) * argvAlloced); |
cc248aae | 87 | if (argv == NULL) goto exit; |
62402cb1 MP |
88 | } |
89 | argv[argc] = buf; | |
90 | } | |
91 | } else switch (*src) { | |
92 | case '"': | |
93 | case '\'': | |
94 | quote = *src; | |
cc248aae | 95 | /*@switchbreak@*/ break; |
62402cb1 MP |
96 | case '\\': |
97 | src++; | |
98 | if (!*src) { | |
cc248aae WD |
99 | rc = POPT_ERROR_BADQUOTE; |
100 | goto exit; | |
62402cb1 | 101 | } |
b348deae | 102 | /*@fallthrough@*/ |
62402cb1 MP |
103 | default: |
104 | *buf++ = *src; | |
cc248aae | 105 | /*@switchbreak@*/ break; |
62402cb1 | 106 | } |
62402cb1 MP |
107 | } |
108 | ||
109 | if (strlen(argv[argc])) { | |
110 | argc++, buf++; | |
111 | } | |
112 | ||
cc248aae | 113 | rc = poptDupArgv(argc, argv, argcPtr, argvPtr); |
62402cb1 | 114 | |
cc248aae WD |
115 | exit: |
116 | if (argv) free(argv); | |
117 | return rc; | |
62402cb1 | 118 | } |