2 * token.c Read the next token from a string.
3 * Yes it's pretty primitive but effective.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * Copyright 2000,2006 The FreeRADIUS server project
24 #include <freeradius-devel/ident.h>
27 #include <freeradius-devel/libradius.h>
28 #include <freeradius-devel/token.h>
32 static const FR_NAME_NUMBER tokens[] = {
33 { "=~", T_OP_REG_EQ, }, /* order is important! */
34 { "!~", T_OP_REG_NE, },
43 { "=*", T_OP_CMP_TRUE, },
44 { "!*", T_OP_CMP_FALSE, },
45 { "==", T_OP_CMP_EQ, },
53 { ";", T_SEMICOLON, },
58 * This works only as long as special tokens
59 * are max. 2 characters, but it's fast.
61 #define TOKEN_MATCH(bptr, tptr) \
62 ( (tptr)[0] == (bptr)[0] && \
63 ((tptr)[1] == (bptr)[1] || (tptr)[1] == 0))
66 * Read a word from a buffer and advance pointer.
67 * This function knows about escapes and quotes.
69 * At end-of-line, buf[0] is set to '\0'.
70 * Returns 0 or special token value.
72 static FR_TOKEN getthing(const char **ptr, char *buf, int buflen, int tok,
73 const FR_NAME_NUMBER *tokenlist)
79 const FR_NAME_NUMBER*t;
86 while (*p && isspace((int) *p))
95 * Might be a 1 or 2 character token.
97 if (tok) for (t = tokenlist; t->name; t++) {
98 if (TOKEN_MATCH(p, t->name)) {
100 p += strlen(t->name);
101 while (isspace((int) *p))
104 return (FR_TOKEN) t->number;
119 while (*p && buflen-- > 1) {
120 if (quote && (*p == '\\')) {
138 if (*p >= '0' && *p <= '9' &&
139 sscanf(p, "%3o", &x) == 1) {
149 if (quote && (*p == quote)) {
155 if (isspace((int) *p))
158 for (t = tokenlist; t->name; t++)
159 if (TOKEN_MATCH(p, t->name))
170 fr_strerror_printf("Unterminated string");
174 /* Skip whitespace again. */
175 while (*p && isspace((int) *p))
179 /* we got SOME form of output string, even if it is empty */
186 rcode = T_SINGLE_QUOTED_STRING;
190 rcode = T_DOUBLE_QUOTED_STRING;
194 rcode = T_BACK_QUOTED_STRING;
202 * Read a "word" - this means we don't honor
203 * tokens as delimiters.
205 int getword(const char **ptr, char *buf, int buflen)
207 return getthing(ptr, buf, buflen, 0, tokens) == T_EOL ? 0 : 1;
211 * Read a bare "word" - this means we don't honor
212 * tokens as delimiters.
214 int getbareword(const char **ptr, char *buf, int buflen)
218 token = getthing(ptr, buf, buflen, 0, NULL);
219 if (token != T_BARE_WORD) {
227 * Read the next word, use tokens as delimiters.
229 FR_TOKEN gettoken(const char **ptr, char *buf, int buflen)
231 return getthing(ptr, buf, buflen, 1, tokens);
237 FR_TOKEN getstring(const char **ptr, char *buf, int buflen)
241 if (!ptr || !*ptr || !buf) return T_OP_INVALID;
245 while (p && (isspace((int)*p))) p++;
249 if ((*p == '"') || (*p == '\'') || (*p == '`')) {
250 return gettoken(ptr, buf, buflen);
253 return getthing(ptr, buf, buflen, 0, tokens);
257 * Convert a string to an integer
259 int fr_str2int(const FR_NAME_NUMBER *table, const char *name, int def)
261 const FR_NAME_NUMBER *this;
263 for (this = table; this->name != NULL; this++) {
264 if (strcasecmp(this->name, name) == 0) {
273 * Convert an integer to a string.
275 const char *fr_int2str(const FR_NAME_NUMBER *table, int number,
278 const FR_NAME_NUMBER *this;
280 for (this = table; this->name != NULL; this++) {
281 if (this->number == number) {