/* do binary search on a set of strings to find matching string */

#include <stdlib.h>
#include <stddef.h>

enum token_t { Auto, Break, Case, Char, Const, Continue, Default, Do, Double,
       Else, Enum, Extern, Float, For, Goto, If, Int, Long, Register,
       Return, Short, Signed, Sizeof, Static, Struct, Switch, Typedef,
       Union, Unsigned, Void_Kw, Volatile, While };

static int find_keyword( char *, int * );
    
struct cdb_kwd_token
{
	const char * const keyword;
	const enum token_t token;
};

/* the following keywords MUST remain in alphabetical order */
static struct cdb_kwd_token key_toks[] = { 
	{ "auto", Auto },
	{ "break", Break },
	{ "case", Case },
	{ "char", Char },
	{ "const", Const },
	{ "continue", Continue },
	{ "default", Default },
	{ "do", Do },
	{ "double", Double },
	{ "else", Else },
	{ "enum", Enum },
	{ "extern", Extern },
	{ "float", Float },
	{ "for", For },
	{ "goto", Goto },
	{ "if", If },
	{ "int", Int },
	{ "long", Long },
	{ "register", Register },
	{ "return", Return },
	{ "short", Short },
	{ "signed", Signed },
	{ "sizeof", Sizeof },
	{ "static", Static },
	{ "struct", Struct },
	{ "switch", Switch },
	{ "typedef", Typedef },
	{ "union", Union },
	{ "unsigned", Unsigned },
	{ "void", Void_Kw },
	{ "volatile", Volatile },
	{ "while", While }
};

/* binary search for keywords, count number of iterations */
static int
find_keyword( char *name, int *compares )
{
    int low, med, high, cmp;

    *compares = 1;
    low = 0;
    high = sizeof( key_toks ) / sizeof( key_toks[0] ) - 1;

    while ( low <= high )
    {
	med = (low+high)/2;
        
	cmp = strcmp( name, key_toks[ med ].keyword );
       
	if ( cmp < 0 )
        {
	    high = med - 1;
        }
	else if ( cmp > 0 )
        {
	    low = med + 1;
        }
	else
        {
	    return med;
        }

        (*compares)++; /* we have to return to do another compare */
    }

    return -1;
}

/* binary search for tokens, count number of iterations */
static const char *
find_token_return_keyword( enum token_t token, int *compares )
{
    int low, med, high;

    *compares = 1;
    low = 0;
    high = sizeof( key_toks ) / sizeof( key_toks[0] ) - 1;

    while ( low <= high )
    {
	med = (low+high)/2;
        
	if ( token < key_toks[ med ].token )
        {
	    high = med - 1;
        }
	else if ( token > key_toks[ med ].token )
        {
	    low = med + 1;
        }
	else
        {
	    return key_toks[ med ].keyword;
        }

        (*compares)++; /* we have to return to do another compare */
    }

    return NULL;
}
    

int
main()
{
    int indx;
    int comps;
    const char *keyword;
    
    indx = find_keyword("typedef", &comps);
    indx = find_keyword("while", &comps);
    indx = find_keyword("case", &comps);
    keyword = find_token_return_keyword( Switch, &comps );
    keyword = find_token_return_keyword( Return, &comps );
    keyword = find_token_return_keyword( Long, &comps );

    exit( 0 );
    return 0;
}
