Commit 3f0e9e7a 3f0e9e7a67ea41319c5535958cc93d5d18af366a by Sergey Poznyakoff

Treat a sequence of whitespace characters as a single whitespace.

Break string on given delimiters. Do not split quoted arguments.
1 parent dc8fe4d0
...@@ -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
......