/* * token.c Read the next token from a string. * Yes it's pretty primitive but effective. * * Version: $Id: token.c,v 1.16 2002/11/21 17:37:16 aland Exp $ * */ #include #include #include #include #include "token.h" static const char rcsid[] = "$Id: token.c,v 1.16 2002/11/21 17:37:16 aland Exp $"; static const LRAD_NAME_NUMBER tokens[] = { { "=~", T_OP_REG_EQ, }, /* order is important! */ { "!~", 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, }, }; /* * This works only as long as special tokens * are max. 2 characters, but it's fast. */ #define TOKEN_MATCH(bptr, tptr) \ ( (tptr)[0] == (bptr)[0] && \ ((tptr)[1] == (bptr)[1] || (tptr)[1] == 0)) /* * Read a word from a buffer and advance pointer. * This function knows about escapes and quotes. * * At end-of-line, buf[0] is set to '\0'. * Returns 0 or special token value. */ static LRAD_TOKEN getthing(char **ptr, char *buf, int buflen, int tok, const LRAD_NAME_NUMBER *tokenlist) { char *s, *p; int quote; int escape; int x; const LRAD_NAME_NUMBER*t; LRAD_TOKEN rcode; buf[0] = 0; /* Skip whitespace */ p = *ptr; while (*p && isspace((int) *p)) p++; if (*p == 0) { *ptr = p; return T_EOL; } /* * Might be a 1 or 2 character token. */ 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 (LRAD_TOKEN) t->number; } } /* Read word. */ quote = 0; if ((*p == '"') || (*p == '\'') || (*p == '`')) { quote = *p; p++; } s = buf; escape = 0; while (*p && buflen-- > 0) { if (escape) { escape = 0; switch(*p) { case 'r': *s++ = '\r'; break; case 'n': *s++ = '\n'; break; case 't': *s++ = '\t'; break; case '"': *s++ = '"'; break; case '\'': *s++ = '\''; break; case '`': *s++ = '`'; break; default: if (*p >= '0' && *p <= '9' && sscanf(p, "%3o", &x) == 1) { *s++ = x; p += 2; } else *s++ = *p; break; } p++; continue; } if (*p == '\\') { p++; escape = 1; continue; } if (quote && (*p == quote)) { 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; /* Skip whitespace again. */ while (*p && isspace((int) *p)) p++; *ptr = p; /* we got SOME form of output string, even if it is empty */ 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; } /* * Read a "word" - this means we don't honor * tokens as delimiters. */ int getword(char **ptr, char *buf, int buflen) { return getthing(ptr, buf, buflen, 0, tokens) == T_EOL ? 0 : 1; } /* * Read a bare "word" - this means we don't honor * tokens as delimiters. */ int getbareword(char **ptr, char *buf, int buflen) { LRAD_TOKEN token; token = getthing(ptr, buf, buflen, 0, NULL); if (token != T_BARE_WORD) { return 0; } return 1; } /* * Read the next word, use tokens as delimiters. */ LRAD_TOKEN gettoken(char **ptr, char *buf, int buflen) { return getthing(ptr, buf, buflen, 1, tokens); } /* * Convert a string to an integer */ int lrad_str2int(const LRAD_NAME_NUMBER *table, const char *name, int def) { const LRAD_NAME_NUMBER *this; for (this = table; this->name != NULL; this++) { if (strcasecmp(this->name, name) == 0) { return this->number; } } return def; } /* * Convert an integer to a string. */ const char *lrad_int2str(const LRAD_NAME_NUMBER *table, int number, const char *def) { const LRAD_NAME_NUMBER *this; for (this = table; this->name != NULL; this++) { if (this->number == number) { return this->name; } } return def; }