/* 
   Copyright 1994-2003 Free Software Foundation, Inc.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   02111-1307, USA.  

   You may contact the author at:

   mailto::camille@bluegrass.net

   or by snail mail at:

   David Lindauer
   850 Washburn Ave Apt 99
   Louisville, KY 40222
*/
/*
 * keyword module
 */
#include        <stdio.h>
#include				<malloc.h>
#include				<string.h>
#include        "lists.h"
#include        "expr.h"
#include        "c.h"

#define KWHASHSIZE 253

extern int prm_ansi;
extern int asmline;
extern ASMNAME oplst[];
extern ASMREG reglst[];
extern char lastid[];
extern enum e_sym lastst;
extern int prm_cplusplus,prm_cmangle;
extern KEYWORDS prockeywords[];
extern ASMNAME *keyimage;

static HASHREC **hashtable=0;
	
KEYWORDS keywords[] = {
 
        {0,"int", kw_int}, {0,"char", kw_char}, {0,"long", kw_long},
        {0,"float", kw_float}, {0,"double", kw_double}, {0,"return", kw_return},
        {0,"struct", kw_struct}, {0,"union", kw_union}, {0,"typedef", kw_typedef},
        {0,"enum", kw_enum}, {0,"static", kw_static}, {0,"auto", kw_auto},
        {0,"sizeof", kw_sizeof}, {0,"do", kw_do}, {0,"if", kw_if},
        {0,"else", kw_else}, {0,"for", kw_for},{0,"switch", kw_switch},
        {0,"while", kw_while},{0,"short", kw_short}, {0,"extern", kw_extern},
        {0,"case", kw_case}, {0,"goto", kw_goto}, {0,"default", kw_default},
        {0,"register", kw_register}, {0,"unsigned", kw_unsigned},
   {0,"signed", kw_signed }, {0,"__func__",kw___func__ } ,
        {0,"break", kw_break}, {0,"continue", kw_continue}, {0,"void", kw_void},
				{0,"volatile", kw_volatile}, {0,"const", kw_const},
        {0,"inline",kw_inline},{0,"restrict",kw_restrict},
        {0,"_Bool", kw_bool}, {0,"_Complex", kw__Complex},
#ifdef CPLUSPLUS
				{0,"virtual",kw_virtual,1},
				{0,"public",kw_public,1}, {0,"private",kw_private,1},
				{0,"protected",kw_protected,1}, { 0, "class", kw_class,1 },
				{0,"friend",kw_friend,1}, {0,"this",kw_this,1}, {0,"operator",kw_operator,1},
            {0,"new",kw_new,1}, {0,"delete",kw_delete,1},
				{0,"try",kw_try,1}, {0,"catch",kw_catch,1}, {0,"template",kw_template,1},
            {0,"throw",kw_throw,1}, {0,"namespace",kw_namespace,1}, {0,"using",kw_using,1 },
				{0,"bool",kw_bool,1}, {0,"true",kw_true,1}, {0,"false", kw_false, 1 },
            {0,"wchar_t",kw_wchar_t,1},
#endif
				{0,"asm",kw_asm,0},
        {0, 0, 0} };

void kwini(void) 
/*
 * create a keyword hash table
 */
{
	struct kwblk *q = keywords;
	ASMNAME *r;
	ASMREG *s;
	if (!hashtable) {
  	hashtable = (HASHREC *)malloc(KWHASHSIZE * sizeof(HASHREC *));
  	memset(hashtable,0,KWHASHSIZE * sizeof(HASHREC *));
		while (q->word) {
			if (prm_cplusplus || !q->flags)
				AddHash(q,hashtable,KWHASHSIZE);
			q++;
		}
		q = prockeywords;
		while (q->word) {
			if (!q->flags || (prm_cplusplus && (q->flags & 1)) || ((q->flags & 4) && !prm_ansi))
				AddHash(q,hashtable,KWHASHSIZE);
			q++;
		}
#ifndef ICODE
		r = oplst;
		while (r->word) {
			if (r->atype) {
				q = malloc(sizeof(struct kwblk));
				q->next=0;
				q->word=r->word;
				q->stype = kw_asminst;
				q->flags=KW_INLINEASM;
				q->data = r;
				AddHash(q,hashtable,KWHASHSIZE);
			}
			r++;
		}
		s = reglst;
		while (s->word) {
			if (s->regtype ) {
				q = malloc(sizeof(struct kwblk));
				q->next=0;
				q->word=s->word;
				q->stype = kw_asmreg;
				q->flags=KW_INLINEASM;
				q->data = s;
				AddHash(q,hashtable,KWHASHSIZE);
			}
			s++;
		}
#endif
	}
}
int searchkw(void)
/*
 * see if the current symbol is a keyword
 */
{
	char *ident = lastid;
	struct kwblk    **kwbp;
	if (lastst != id)
		return 0;
	if (prm_cmangle)
		ident++;
	kwbp = LookupHash(ident,hashtable,KWHASHSIZE);
	
	if (kwbp) {
#ifndef ICODE
		if (((*kwbp)->flags==KW_INLINEASM) && !asmline)
			return 0;
		keyimage = (*kwbp)->data;
#endif 
		return lastst = (*kwbp)->stype;
	}
  return(0);
}