#include <freeradius-devel/ident.h>
RCSID("$Id$")
#include <freeradius-devel/libradius.h>
#include <freeradius-devel/token.h>
#include <ctype.h>
static const FR_NAME_NUMBER tokens[] = {
{ "=~", T_OP_REG_EQ, },
{ "!~", T_OP_REG_NE, },
{ "{", T_LCBRACE, },
{ "}", T_RCBRACE, },
{ "(", T_LBRACE, },
{ ")", T_RBRACE, },
{ ",", T_COMMA, },
{ "+=", T_OP_ADD, },
{ "-=", T_OP_SUB, },
{ ":=", T_OP_SET, },
{ "=*", T_OP_CMP_TRUE, },
{ "!*", T_OP_CMP_FALSE, },
{ "==", T_OP_CMP_EQ, },
{ "=", T_OP_EQ, },
{ "!=", T_OP_NE, },
{ ">=", T_OP_GE, },
{ ">", T_OP_GT, },
{ "<=", T_OP_LE, },
{ "<", T_OP_LT, },
{ "#", T_HASH, },
{ ";", T_SEMICOLON, },
{ NULL, 0, },
};
#define TOKEN_MATCH(bptr, tptr) \
( (tptr)[0] == (bptr)[0] && \
((tptr)[1] == (bptr)[1] || (tptr)[1] == 0))
static FR_TOKEN getthing(const char **ptr, char *buf, int buflen, int tok,
const FR_NAME_NUMBER *tokenlist)
{
char *s;
const char *p;
int quote, end = 0;
int escape;
unsigned int x;
const FR_NAME_NUMBER*t;
FR_TOKEN rcode;
buf[0] = 0;
p = *ptr;
while (*p && isspace((int) *p))
p++;
if (*p == 0) {
*ptr = p;
return T_EOL;
}
if (tok) for (t = tokenlist; t->name; t++) {
if (TOKEN_MATCH(p, t->name)) {
strcpy(buf, t->name);
p += strlen(t->name);
while (isspace((int) *p))
p++;
*ptr = p;
return (FR_TOKEN) t->number;
}
}
quote = 0;
if ((*p == '"') ||
(*p == '\'') ||
(*p == '`')) {
quote = *p;
end = 0;
p++;
}
s = buf;
escape = 0;
while (*p && buflen-- > 1) {
if (quote && (*p == '\\')) {
p++;
switch(*p) {
case 'r':
*s++ = '\r';
break;
case 'n':
*s++ = '\n';
break;
case 't':
*s++ = '\t';
break;
case '\0':
*s++ = '\\';
p--;
break;
default:
if (*p >= '0' && *p <= '9' &&
sscanf(p, "%3o", &x) == 1) {
*s++ = x;
p += 2;
} else
*s++ = *p;
break;
}
p++;
continue;
}
if (quote && (*p == quote)) {
end = 1;
p++;
break;
}
if (!quote) {
if (isspace((int) *p))
break;
if (tok) {
for (t = tokenlist; t->name; t++)
if (TOKEN_MATCH(p, t->name))
break;
if (t->name != NULL)
break;
}
}
*s++ = *p++;
}
*s++ = 0;
if (quote && !end) {
fr_strerror_printf("Unterminated string");
return T_OP_INVALID;
}
while (*p && isspace((int) *p))
p++;
*ptr = p;
switch (quote) {
default:
rcode = T_BARE_WORD;
break;
case '\'':
rcode = T_SINGLE_QUOTED_STRING;
break;
case '"':
rcode = T_DOUBLE_QUOTED_STRING;
break;
case '`':
rcode = T_BACK_QUOTED_STRING;
break;
}
return rcode;
}
int getword(const char **ptr, char *buf, int buflen)
{
return getthing(ptr, buf, buflen, 0, tokens) == T_EOL ? 0 : 1;
}
int getbareword(const char **ptr, char *buf, int buflen)
{
FR_TOKEN token;
token = getthing(ptr, buf, buflen, 0, NULL);
if (token != T_BARE_WORD) {
return 0;
}
return 1;
}
FR_TOKEN gettoken(const char **ptr, char *buf, int buflen)
{
return getthing(ptr, buf, buflen, 1, tokens);
}
FR_TOKEN getstring(const char **ptr, char *buf, int buflen)
{
const char *p = *ptr;
while (*p && (isspace((int)*p))) p++;
*ptr = p;
if ((*p == '"') || (*p == '\'') || (*p == '`')) {
return gettoken(ptr, buf, buflen);
}
return getthing(ptr, buf, buflen, 0, tokens);
}
int fr_str2int(const FR_NAME_NUMBER *table, const char *name, int def)
{
const FR_NAME_NUMBER *this;
for (this = table; this->name != NULL; this++) {
if (strcasecmp(this->name, name) == 0) {
return this->number;
}
}
return def;
}
const char *fr_int2str(const FR_NAME_NUMBER *table, int number,
const char *def)
{
const FR_NAME_NUMBER *this;
for (this = table; this->name != NULL; this++) {
if (this->number == number) {
return this->name;
}
}
return def;
}
const char *fr_token_name(int token)
{
return fr_int2str(tokens, token, "???");
}