aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2005-02-12 14:10:55 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2005-02-12 14:10:55 +0000
commitb972eb6459c5af44fdbe792615e61450e943ab2e (patch)
tree5fbf3847ca3292a2573ca419089c8fdcf1a8080c /lib
parenteb4f32d4c260783a5deb0a55f4680ed0d88a6d68 (diff)
downloadanubis-b972eb6459c5af44fdbe792615e61450e943ab2e.tar.gz
anubis-b972eb6459c5af44fdbe792615e61450e943ab2e.tar.bz2
Argument list parser
Diffstat (limited to 'lib')
-rw-r--r--lib/argcv.c443
-rw-r--r--lib/argcv.h53
2 files changed, 496 insertions, 0 deletions
diff --git a/lib/argcv.c b/lib/argcv.c
new file mode 100644
index 0000000..2728035
--- /dev/null
+++ b/lib/argcv.c
@@ -0,0 +1,443 @@
1/* argcv.c - simple functions for parsing input based on whitespace
2 Copyright (C) 1999, 2000, 2001, 2005 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
18#ifdef HAVE_CONFIG_H
19# include <config.h>
20#endif
21
22#include <ctype.h>
23#include <errno.h>
24#include <argcv.h>
25
26/*
27 * takes a string and splits it into several strings, breaking at ' '
28 * command is the string to split
29 * the number of strings is placed into argc
30 * the split strings are put into argv
31 * returns 0 on success, nonzero on failure
32 */
33
34#define isws(c) ((c)==' '||(c)=='\t'||(c)=='\n')
35#define isdelim(c,delim) (strchr(delim,(c))!=NULL)
36
37static int
38argcv_scan (int len, const char *command, const char *delim, const char* cmnt,
39 int *start, int *end, int *save)
40{
41 int i = 0;
42 int expect_delim;
43
44 for (;;)
45 {
46 i = *save;
47
48 if (i >= len)
49 return i + 1;
50
51 /* Skip initial whitespace */
52 while (i < len && isws (command[i]))
53 i++;
54 *start = i;
55
56 switch (command[i])
57 {
58 case '"':
59 case '\'':
60 while (++i < len
61 && (command[i] != command[*start]
62 || command[i-1] == '\\'))
63 ;
64 if (i < len) /* found matching quote */
65 break;
66 /*FALLTHRU*/ default:
67 if (isdelim (command[i], delim))
68 break;
69 /* Skip until next whitespace character or end of line. Honor
70 escaped whitespace. */
71 expect_delim = 0;
72 while (++i < len)
73 {
74 if (expect_delim)
75 {
76 if (command[i-1] != '\\' && command[i] == expect_delim)
77 expect_delim = 0;
78 else
79 continue;
80 }
81
82 if (command[i-1] != '\\')
83 {
84 if (command[i] == '\'' || command[i] == '"')
85 expect_delim = command[i];
86 else if (isws (command[i]) || isdelim (command[i], delim))
87 break;
88 }
89 else
90 i++; /* skip the escaped character */
91 }
92 i--;
93 break;
94 }
95
96 *end = i;
97 *save = i + 1;
98
99 /* If we have a token, and it starts with a comment character, skip
100 to the newline and restart the token search. */
101 if (*save <= len)
102 {
103 if (cmnt && strchr (cmnt, command[*start]) != NULL)
104 {
105 i = *save;
106 while (i < len && command[i] != '\n')
107 i++;
108
109 *save = i;
110 continue;
111 }
112 }
113 break;
114 }
115 return *save;
116}
117
118static char quote_transtab[] = "\\\\a\ab\bf\fn\nr\rt\t";
119
120int
121argcv_unquote_char (int c)
122{
123 char *p;
124
125 for (p = quote_transtab; *p; p += 2)
126 {
127 if (*p == c)
128 return p[1];
129 }
130 return c;
131}
132
133int
134argcv_quote_char (int c)
135{
136 char *p;
137
138 for (p = quote_transtab + sizeof(quote_transtab) - 2;
139 p > quote_transtab; p -= 2)
140 {
141 if (*p == c)
142 return p[-1];
143 }
144 return -1;
145}
146
147
148static int
149xtonum (const char *src, int base, size_t cnt)
150{
151 int val;
152 char *p;
153 char tmp[4]; /* At most three characters + zero */
154
155 /* Notice: No use to check `cnt'. It should be either 2 or 3 */
156 memcpy (tmp, src, cnt);
157 tmp[cnt] = 0;
158 val = strtoul (tmp, &p, base);
159 return (*p == 0) ? val : -1;
160}
161
162size_t
163argcv_quoted_length (const char *str, int *quote)
164{
165 size_t len = 0;
166
167 for (; *str; str++)
168 {
169 if (*str == ' ')
170 {
171 len++;
172 *quote = 1;
173 }
174 else if (*str == '"')
175 {
176 len += 2;
177 *quote = 1;
178 }
179 else if (isprint (*str))
180 len++;
181 else if (argcv_quote_char (*str) != -1)
182 len += 2;
183 else
184 len += 4;
185 }
186 return len;
187}
188
189void
190argcv_unquote_copy (char *dst, const char *src, size_t n)
191{
192 int c;
193 int expect_delim = 0;
194
195 while (n > 0)
196 {
197 n--;
198
199 switch (*src)
200 {
201 case '\'':
202 case '"':
203 ++src;
204 if (expect_delim)
205 expect_delim = 0;
206 else
207 expect_delim = *src;
208 break;
209
210 case '\\':
211 switch (*++src)
212 {
213 case 'x':
214 case 'X':
215 ++src;
216 --n;
217 if (n == 0)
218 {
219 *dst++ = '\\';
220 *dst++ = src[-1];
221 }
222 else
223 {
224 c = xtonum(src, 16, 2);
225 if (c == -1)
226 {
227 *dst++ = '\\';
228 *dst++ = src[-1];
229 }
230 else
231 {
232 *dst++ = c;
233 src += 2;
234 n -= 2;
235 }
236 }
237 break;
238
239 case '0':
240 ++src;
241 --n;
242 if (n == 0)
243 {
244 *dst++ = '\\';
245 *dst++ = src[-1];
246 }
247 else
248 {
249 c = xtonum(src, 8, 3);
250 if (c == -1)