Treat a sequence of whitespace characters as a single whitespace.
Break string on given delimiters. Do not split quoted arguments.
Showing
2 changed files
with
79 additions
and
15 deletions
... | @@ -25,37 +25,85 @@ | ... | @@ -25,37 +25,85 @@ |
25 | * returns 0 on success, nonzero on failure | 25 | * returns 0 on success, nonzero on failure |
26 | */ | 26 | */ |
27 | 27 | ||
28 | #define isws(c) ((c)==' '||(c)=='\t') | ||
29 | #define isdelim(c,delim) ((c)=='"'||strchr(delim,(c))!=NULL) | ||
30 | |||
31 | static int | ||
32 | argcv_scan (int len, const char *command, const char *delim, | ||
33 | int *start, int *end, int *save) | ||
34 | { | ||
35 | int i = *save; | ||
36 | |||
37 | /* Skip initial whitespace */ | ||
38 | while (i < len && isws (command[i])) | ||
39 | i++; | ||
40 | *start = i; | ||
41 | |||
42 | switch (command[i]) | ||
43 | { | ||
44 | case '"': | ||
45 | while (++i < len && command[i] != command[*start]) | ||
46 | ; | ||
47 | if (i < len) /* found matching quote */ | ||
48 | break; | ||
49 | /*FALLTHRU*/ | ||
50 | default: | ||
51 | if (isdelim (command [i], delim)) | ||
52 | break; | ||
53 | /* Skip until next whitespace character or end of line */ | ||
54 | while (++i < len && !(isws (command [i]) || isdelim (command [i], delim))) | ||
55 | ; | ||
56 | if (i < len) | ||
57 | i--; | ||
58 | break; | ||
59 | } | ||
60 | |||
61 | *end = i; | ||
62 | *save = i+1; | ||
63 | return *save; | ||
64 | } | ||
65 | |||
28 | int | 66 | int |
29 | argcv_get (const char *command, int *argc, char ***argv) | 67 | argcv_get (const char *command, const char *delim, int *argc, char ***argv) |
30 | { | 68 | { |
31 | int len = strlen (command); | 69 | int len = strlen (command); |
32 | int i = 0, j = 0; | 70 | int i = 0, j = 0; |
33 | int start = 0; | 71 | int start, end, save; |
34 | 72 | ||
73 | *argc = 0; | ||
74 | *argv = NULL; | ||
35 | if (len < 1) | 75 | if (len < 1) |
36 | return 1; | 76 | return 1; |
37 | 77 | ||
78 | /* Count number of arguments */ | ||
38 | *argc = 1; | 79 | *argc = 1; |
39 | 80 | save = 0; | |
40 | for (i = 0; i < len; i++) | 81 | while (argcv_scan (len, command, delim, &start, &end, &save) < len) |
41 | if (command[i] == ' ') | ||
42 | (*argc)++; | 82 | (*argc)++; |
43 | 83 | ||
44 | *argv = calloc ((*argc + 1), sizeof (char *)); | 84 | *argv = calloc ((*argc + 1), sizeof (char *)); |
45 | 85 | ||
46 | for (i = 0; i <= len; i++) | 86 | i = 0; |
87 | save = 0; | ||
88 | do | ||
47 | { | 89 | { |
48 | if (command[i] == ' ' || command[i] == '\0') | 90 | int n; |
91 | argcv_scan (len, command, delim, &start, &end, &save); | ||
92 | |||
93 | if (command[start] == '"' && command[end] == '"') | ||
49 | { | 94 | { |
50 | /* Reserve space for the null. */ | 95 | start++; |
51 | (*argv)[j] = calloc ((i - start + 1), sizeof (char)); | 96 | end--; |
52 | if ((*argv)[j] == NULL) | ||
53 | return 1; | ||
54 | strncpy ((*argv)[j], &command[start], i - start); | ||
55 | j++; | ||
56 | start = i+1; | ||
57 | } | 97 | } |
98 | n = end - start + 1; | ||
99 | (*argv)[i] = calloc (n+1, sizeof (char)); | ||
100 | if ((*argv)[i] == NULL) | ||
101 | return 1; | ||
102 | memcpy ((*argv)[i], &command[start], n); | ||
103 | (*argv)[i][n] = 0; | ||
104 | i++; | ||
58 | } | 105 | } |
106 | while (end < len); | ||
59 | return 0; | 107 | return 0; |
60 | } | 108 | } |
61 | 109 | ||
... | @@ -115,3 +163,18 @@ argcv_string (int argc, char **argv, char **pstring) | ... | @@ -115,3 +163,18 @@ argcv_string (int argc, char **argv, char **pstring) |
115 | *pstring = buffer; | 163 | *pstring = buffer; |
116 | return 0; | 164 | return 0; |
117 | } | 165 | } |
166 | |||
167 | #if 0 | ||
168 | char *command = "set prompt=\"& \""; | ||
169 | |||
170 | main() | ||
171 | { | ||
172 | int i, argc; | ||
173 | char **argv; | ||
174 | |||
175 | argcv_get (command, "=", &argc, &argv); | ||
176 | printf ("%d args:\n", argc); | ||
177 | for (i = 0; i < argc; i++) | ||
178 | printf ("%s\n", argv[i]); | ||
179 | } | ||
180 | #endif | ... | ... |
... | @@ -35,7 +35,8 @@ extern "C" { | ... | @@ -35,7 +35,8 @@ extern "C" { |
35 | # endif | 35 | # endif |
36 | #endif /*__P */ | 36 | #endif /*__P */ |
37 | 37 | ||
38 | extern int argcv_get __P ((const char *command, int *argc, char ***argv)); | 38 | extern int argcv_get __P ((const char *command, const char *delim, |
39 | int *argc, char ***argv)); | ||
39 | extern int argcv_string __P ((int argc, char **argv, char **string)); | 40 | extern int argcv_string __P ((int argc, char **argv, char **string)); |
40 | extern int argcv_free __P ((int argc, char **argv)); | 41 | extern int argcv_free __P ((int argc, char **argv)); |
41 | 42 | ... | ... |
-
Please register or sign in to post a comment