/*
* Copyright (c) 2003 - 2006, Nils R. Weller
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* This module contains a keyword and an operator table and two
* functions to initialize the LOOKUP_* macros exported by defs.h
*/
#include "defs.h"
#include <string.h>
#include "token.h"
#include "n_libc.h"
char key_lookup[256];
/*
* Initializes lookup table for keywords. Note that you must extend
* key_chars appropriately any time a new keyword is added that is not
* yet covered by those characters
*/
void
init_keylookup(void) {
static char key_chars[] = {
'c', 'd', 'e', 'f', 'i', 'v', 'r', 's',
'u', 'l', 'a', 'w', 'b', 'g', 't', '_',
0
};
unsigned int i;
unsigned int j;
memset(key_lookup, 0, sizeof key_lookup);
for (i = 0; i < sizeof key_chars; ++i) {
for (j = 0; keywords[j].name != NULL; ++j) {
if (keywords[j].name[0] == key_chars[i]) {
key_lookup[ (unsigned)key_chars[i] ] = j;
break;
}
}
}
}
/*
* NOTE: These keywords are ordered by their first character to make
* lookup faster.
* A LOOKUP_KEY macro in defs.h returns the index of the first keyword
* with a matching character in the table. init_keylookup() must be
* called before that can be used
*/
struct keyword keywords[] = {
{ "!dummy!", 0, 0, 0 },
{ "case", TOK_KEY_CASE, 0, C89 },
{ "char", TOK_KEY_CHAR, TY_CHAR, C89 },
{ "const", TOK_KEY_CONST, 0, C89 },
{ "continue", TOK_KEY_CONTINUE, 0, C89 },
{ "do", TOK_KEY_DO, 0, C89 },
{ "double", TOK_KEY_DOUBLE, TY_DOUBLE, C89 },
{ "default", TOK_KEY_DEFAULT, 0, C89 },
{ "extern", TOK_KEY_EXTERN, 0, C89 },
{ "enum", TOK_KEY_ENUM, 0, C89 },
{ "else", TOK_KEY_ELSE, 0, C89 },
{ "float", TOK_KEY_FLOAT, TY_FLOAT, C89 },
{ "for", TOK_KEY_FOR, 0, C89 },
{ "inline", TOK_KEY_INLINE, 0, C99 },
{ "int", TOK_KEY_INT, TY_INT, C89 },
{ "if", TOK_KEY_IF, 0, C89 },
{ "void", TOK_KEY_VOID, TY_VOID, C89 },
{ "volatile", TOK_KEY_VOLATILE, 0, C89 },
{ "register", TOK_KEY_REGISTER, 0, C89 },
{ "restrict", TOK_KEY_RESTRICT, 0, C99 },
{ "return", TOK_KEY_RETURN, 0, C89 },
{ "short", TOK_KEY_SHORT, TY_SHORT, C89 },
{ "static", TOK_KEY_STATIC, 0, C89 },
{ "signed", TOK_KEY_SIGNED, 0, C89 },
{ "switch", TOK_KEY_SWITCH, 0, C89 },
{ "struct", TOK_KEY_STRUCT, 0, C89 },
{ "sizeof", TOK_KEY_SIZEOF, 0, C89 },
{ "unsigned", TOK_KEY_UNSIGNED, 0, C89 },
{ "union", TOK_KEY_UNION, 0, C89 },
{ "long", TOK_KEY_LONG, TY_LONG, C89 },
{ "auto", TOK_KEY_AUTO, 0, C89 },
{ "while", TOK_KEY_WHILE, 0, C89 },
{ "break", TOK_KEY_BREAK, 0, C89 },
{ "goto", TOK_KEY_GOTO, 0, C89 },
{ "typedef", TOK_KEY_TYPEDEF, 0, C89 },
{ "typeof", TOK_KEY_TYPEOF, 0, C89 },
{ "__asm__", TOK_KEY_ASM, 0, C89 },
{ "__asm", TOK_KEY_ASM, 0, C89 },
{ "__attribute__", TOK_KEY_ATTRIBUTE, 0, C89 },
{ "__attribute", TOK_KEY_ATTRIBUTE, 0, C89 },
/*
* The following are for GNU C compatibility
*/
{ "__restrict__", TOK_KEY_RESTRICT, 0, C99 },
{ "__restrict", TOK_KEY_RESTRICT, 0, C99 },
{ "__extension__", TOK_KEY_EXTENSION, 0, 0 },
{ "__extension", TOK_KEY_EXTENSION, 0, 0 },
{ "__const", TOK_KEY_CONST, 0, C89 },
{ "__signed", TOK_KEY_SIGNED, 0, C89 },
{ "__signed__", TOK_KEY_SIGNED, 0, C89 },
{ "__typeof__", TOK_KEY_TYPEOF, 0, C89 },
{ "__typeof", TOK_KEY_TYPEOF, 0, C89 },
{ "__alignof__", TOK_KEY_ALIGNOF, 0, C89 },
{ "__alignof", TOK_KEY_ALIGNOF, 0, C89 },
{ "__volatile__", TOK_KEY_VOLATILE, 0, C89 },
{ "__volatile", TOK_KEY_VOLATILE, 0, C89 },
{ "__inline", TOK_KEY_INLINE, 0, C99 },
{ "__inline__", TOK_KEY_INLINE, 0, C99 },
{ "_Bool", TOK_KEY_BOOL, 0, C99 },
#if 0
/* Perhaps later .... */
{ "_Complex", TOK_KEY_COMPLEX, 0, C99 },
{ "_Imaginary", TOK_KEY_IMAGINARY, 0, C99 },
#endif
/*
* This last element is used, because one otherwise would have
* to check for operators[x].name != NULL when traversing the
* list. If a last entry with a different first character is
* present, the test is eliminated and one can do
* while (operators[x].name[0] == first_char) { ... ++x; }
*/
{ "ZORG", 0, 0, 0 },
{ NULL, 0, 0, 0 }
};
/*
* Keyword lookup function that maps the ``name'' argument to its
* respective index in the keyword table on success, else -1.
* This should be relatively fast now...
*/
int
lookup_key(const char *name) {
int i;
char c = *name;
if ((i = LOOKUP_KEY((unsigned)c)) == 0) {
return -1;
}
for (; keywords[i].name[0] == c; ++i) {
if (strcmp(keywords[i].name, name) == 0) {
return i;
}
}
return -1;
}
/*
* Refer to the keywords table comment - This one works the same except
* that LOOKUP_OP() and init_oplookup() are used
*/
struct operator operators[] = {
{ "dummy", 0, 0, 0, 0, 0, 0 },
/* unary minus */
{ "-", TOK_OP_UMINUS, TOK_OP_AMB_MINUS,
OP_CLASS_PRE, 15, OP_ASSOC_RIGHT, 0 },
/* compound minus assignment */
{ "-=", TOK_OP_COMINUS, 0,
OP_CLASS_BIN, 2, OP_ASSOC_RIGHT, 0 },
/* prefix decrement */
{ "--", TOK_OP_DECPRE, TOK_OP_AMB_DECR,
OP_CLASS_PRE, 15, OP_ASSOC_RIGHT, 0 },
/* access s. / u. m. through pointer */
{ "->", TOK_OP_STRUPMEMB, 0,
OP_CLASS_POST, 16, OP_ASSOC_LEFT, 0 },
/* substract */
{ "-", TOK_OP_MINUS, TOK_OP_AMB_MINUS,
OP_CLASS_BIN, 12, OP_ASSOC_LEFT, 0 },
/* postfix decrement */
{ "--", TOK_OP_DECPOST, TOK_OP_AMB_DECR,
OP_CLASS_POST, 16, OP_ASSOC_LEFT, 0 },
/* unary plus */
{ "+", TOK_OP_UPLUS, TOK_OP_AMB_PLUS,
OP_CLASS_PRE, 15, OP_ASSOC_RIGHT, 0 },
/* prefix increment */
{ "++", TOK_OP_INCPRE, TOK_OP_AMB_INCR,
OP_CLASS_PRE, 15, OP_ASSOC_RIGHT, 0 },
/* add */
{ "+", TOK_OP_PLUS, TOK_OP_AMB_PLUS,
OP_CLASS_BIN, 12, OP_ASSOC_LEFT, 0 },
/* compound plus assignemnt */
{ "+=", TOK_OP_COPLUS, 0,
OP_CLASS_BIN, 2, OP_ASSOC_RIGHT, 0 },
/* postfix increment */
{ "++", TOK_OP_INCPOST, TOK_OP_AMB_INCR,
OP_CLASS_POST, 16, OP_ASSOC_LEFT, 0 },
/* divide */
{ "/", TOK_OP_DIVIDE, 0,
OP_CLASS_BIN, 13, OP_ASSOC_LEFT, 0 },
/* compound divide assignment */
{ "/=", TOK_OP_CODIVIDE, 0,
OP_CLASS_BIN, 2, OP_ASSOC_RIGHT, 0 },
/* multiply */
{ "*", TOK_OP_MULTI, TOK_OP_AMB_MULTI,
OP_CLASS_BIN, 13, OP_ASSOC_LEFT, 0 },
/* compound multiply assignment */
{ "*=", TOK_OP_COMULTI, 0,
OP_CLASS_BIN, 2, OP_ASSOC_RIGHT, 0 },
/* dereference pointer */
{ "*", TOK_OP_DEREF, TOK_OP_AMB_MULTI,
OP_CLASS_PRE, 15, OP_ASSOC_RIGHT, 0 },
/* modulo */
{ "%", TOK_OP_MOD, 0,
OP_CLASS_BIN, 13, OP_ASSOC_LEFT, 0 },
/* compound modulo assignment */
{ "%=", TOK_OP_COMOD, 0,
OP_CLASS_BIN , 2, OP_ASSOC_RIGHT, 0 },
/* bitwise and */
{ "&", TOK_OP_BAND, TOK_OP_AMB_BAND,
OP_CLASS_BIN, 8, OP_ASSOC_LEFT, 0 },
/* compound bitwise and assignment */
{ "&=", TOK_OP_COBAND, 0,
OP_CLASS_BIN, 2, OP_ASSOC_RIGHT, 0 },
/* logical and */
{ "&&", TOK_OP_LAND, 0,
OP_CLASS_BIN, 5, OP_ASSOC_LEFT, 1 },
/* address-of */
{ "&", TOK_OP_ADDR, TOK_OP_AMB_BAND,
OP_CLASS_BIN, 15, OP_ASSOC_RIGHT, 0 },
/* bitwise or */
{ "|", TOK_OP_BOR, 0,
OP_CLASS_BIN, 6, OP_ASSOC_LEFT, 0 },
/* compound bitwise or assignment */
{ "|=", TOK_OP_COBOR, 0,
OP_CLASS_BIN, 2, OP_ASSOC_RIGHT, 0 },
/* logical or */
{ "||", TOK_OP_LOR, 0,
OP_CLASS_BIN, 4, OP_ASSOC_LEFT, 1 },
/* bitwise xor */
{ "^", TOK_OP_BXOR, 0,
OP_CLASS_BIN, 7, OP_ASSOC_LEFT, 0 },
/* compound bitwise xor assignment */
{ "^=", TOK_OP_COBXOR, 0,
OP_CLASS_BIN, 2, OP_ASSOC_RIGHT, 0 },
/* bitwise negation */
{ "~", TOK_OP_BNEG, 0,
OP_CLASS_PRE, 15, OP_ASSOC_RIGHT, 0 },
/* smaller than */
{ "<", TOK_OP_SMALL, 0,
OP_CLASS_BIN, 10, OP_ASSOC_LEFT, 0 },
/* smaller than or equal */
{ "<=", TOK_OP_SMALLEQ, 0,
OP_CLASS_BIN, 10, OP_ASSOC_LEFT, 0 },
/* bitwise shift left */
{ "<<", TOK_OP_BSHL, 0,
OP_CLASS_BIN, 11, OP_ASSOC_LEFT, 0 },
/* compound bitwise shift left assignment */
{ "<<=", TOK_OP_COBSHL, 0,
OP_CLASS_BIN, 2, OP_ASSOC_RIGHT, 0 },
/* greater than */
{ ">", TOK_OP_GREAT, 0,
OP_CLASS_BIN, 10, OP_ASSOC_LEFT, 0 },
/* greater than or equal */
{ ">=", TOK_OP_GREATEQ, 0,
OP_CLASS_BIN, 10, OP_ASSOC_LEFT, 0 },
/* bitwise shift right */
{ ">>", TOK_OP_BSHR, 0,
OP_CLASS_BIN, 11, OP_ASSOC_LEFT, 0 },
/* compound bitwise shift right assignment */
{ ">>=", TOK_OP_COBSHR, 0,
OP_CLASS_BIN, 2, OP_ASSOC_RIGHT, 0 },
/* assignment */
{ "=", TOK_OP_ASSIGN, 0,
OP_CLASS_BIN, 2, OP_ASSOC_RIGHT, 0 },
/* logical equality */
{ "==", TOK_OP_LEQU, 0,
OP_CLASS_BIN, 9, OP_ASSOC_LEFT, 0 },
/* logical negation */
{ "!", TOK_OP_LNEG, 0,
OP_CLASS_PRE, 15, OP_ASSOC_RIGHT, 0 },
/* logical inequality */
{ "!=", TOK_OP_LNEQU, 0,
OP_CLASS_BIN, 9, OP_ASSOC_LEFT, 0 },
/* access structure / union member */
{ ".", TOK_OP_STRUMEMB, 0,
OP_CLASS_POST, 16, OP_ASSOC_LEFT, 0 },
/* comma operator */
{ ",", TOK_OP_COMMA, 0,
OP_CLASS_BIN, 1, OP_ASSOC_LEFT, 1 },
/* conditional operator 1 */
{ "?", TOK_OP_COND, 0,
OP_CLASS_TER, 3, OP_ASSOC_RIGHT, 1 },
/* conditional operator 2 */
{ ":", TOK_OP_COND2,
TOK_OP_AMB_COND2, OP_CLASS_TER, 3,
OP_ASSOC_RIGHT, 0 },
{ "ZORG", 0, 0, 0, 0, 0, 0 },
{ NULL, 0, 0, 0, 0, 0, 0 }
};
char op_lookup[256];
char op_lookup2[256];
/*
* Initializes operator lookup table. Refer to init_keylookup()
*/
void
init_oplookup(void) {
static char op_chars[] = {
'-', '+', '/', '*', '%', '&', '|', '^',
'~', '<', '>', '=', '!', '.', ',', '?',
':', 0
};
unsigned int i;
unsigned int j;
memset(op_lookup, 0, sizeof op_lookup);
for (i = 0; i < sizeof op_chars; ++i) {
for (j = 0; operators[j].name != NULL; ++j) {
if (operators[j].name[0] == op_chars[i]) {
op_lookup[ (unsigned)op_chars[i] ] = j;
break;
}
}
}
memset(op_lookup2, 0, sizeof op_lookup2);
for (i = 0; i <= TOK_OP_MAX - TOK_OP_MIN; ++i) {
for (j = 0; operators[j].name != NULL; ++j) {
if ((unsigned)operators[j].value == (i + TOK_OP_MIN)) {
op_lookup2[i] = j;
break;
}
}
}
}
/*
* Maps operator in ascii specified by ``name'' to according index in
* operator table. Returns index on success, else -1
*/
int
lookup_op(const char *name) {
int i;
char c = *name;
if ((i = LOOKUP_OP((unsigned)c)) == 0) {
return -1;
}
for (; operators[i].name[i] == c; ++i) {
if (strcmp(operators[i].name, name) == 0) {
return i;
}
}
return -1;
}
/*
* Maps numeric operator code to operator name in ascii and returns a
* pointer to that on success, else NULL
*/
char *
lookup_operator(int value) {
int i;
for (i = 0; operators[i].name != NULL; ++i) {
if (value == operators[i].value ||
value == operators[i].is_ambig) {
return operators[i].name;
}
}
return NULL;
}
/*
* Gets index for operator ``value'' in operator table - using the
* first character of its ascii representation as starting point to
* search
*/
int
get_opind_by_value(char firstch, int value) {
int i;
if ((i = LOOKUP_OP((unsigned)firstch)) == 0) {
return -1;
}
do {
if (operators[i].value == value) {
return i;
}
} while (operators[++i].name[0] == firstch);
return -1;
}
syntax highlighted by Code2HTML, v. 0.9.1