/*
 *   Copyright (C) 1988-2006 Lucent Technologies Inc. and others.
 *   All Rights Reserved.
 */

/*	cscope - interactive C symbol cross-reference
 *
 *	Lex interface for various symbol scanners
 */

#ifdef MULTILINGUAL

#include "global.h"

int	first;			/* buffer index for first char of symbol */
int	last;			/* buffer index for last char of symbol */
int	lineno;			/* symbol line number */
FILE	*yyin;			/* input file descriptor */
int	yyleng;			/* input line length */
int	yylineno;		/* input line number */
char	lyytext[YYLMAX]="";		/* Dummy input line text */
char	*yytext = lyytext;

#if defined( __STDC__ ) || defined( __BORLANDC__ )
int	hash(char *s);
#endif

static	BOOL	cscanner;	/* C scanner */
static	BOOL	jscanner;	/* Java scanner */
static	BOOL	sscanner;	/* SDL Scanner */

yylex()
{
	int	result;

	if (cscanner == YES) {
		/* Update variables from crossref.c changes */
		cyyin = yyin;
		clineno = lineno;
		cfirst = first;
		clast = last;

		result = cyylex();
		first = cfirst;
		last = clast;
		lineno = clineno;
		yytext = cyytext;
		yyleng = cyyleng;
		yylineno = cmyylineno;
		return(result);
	}
	else if (jscanner == YES) {
		/* Update variables from crossref.c changes */
		jyyin = yyin;
		jlineno = lineno;
		jfirst = first;
		jlast = last;

		result = jyylex();
		first = jfirst;
		last = jlast;
		lineno = jlineno;
		yytext = jyytext;
		yyleng = jyyleng;
		yylineno = jmyylineno;
		return(result);
	}
	else if (sscanner == YES) {
		/* Update variables from crossref.c changes */
		syyin = yyin;
		slineno = lineno;
		sfirst = first;
		slast = last;

		result = syylex();
		first = sfirst;
		last = slast;
		lineno = slineno;
		yytext = syytext;
		yyleng = syyleng;
		yylineno = smyylineno;
		return(result);
	}
	else {
		return(LEXEOF);
	}
}

void
setscanner(srcfile)
char *srcfile;
{
	char	*s;

	cscanner = NO;
	jscanner = NO;
	sscanner = NO;

	/* is there a multi-lingual language set */
	if (multilingual != NULL) {
		s = multilingual;
		switch (*s) {
		case 'c':	/* C, C++ */
				cscanner = YES;
				break;
		case 'j':	/* Java */
				jscanner = YES;
				break;
		case 's':	/* SDL */
				sscanner = YES;
				break;
		default:	/* Try to parse with C scanner */
				cscanner = YES;
				break;
		}
	} else
	/* if there is a file suffix */
	if ((s = strrchr(srcfile, '.')) != NULL && *++s != '\0') {
		
		if (s[1] == '\0') {	/* 1 character suffix */
			switch (*s) {
			case 'c':
			case 'h':
			case 'i':
			case 'l':
			case 'y':
			case 'C':
			case 'G':
			case 'H':
			case 'L':
#ifdef __BORLANDC__
			case 'Y':	/* letters are all upper case in DOS */
#endif
				cscanner = YES;
				break;
			case 'm':	/* SDL */
				sscanner = YES;
				break;
			default:
				/* try to parse with c scanner */
				cscanner = YES;
				break;
			}
		}
		else if (s[2] == '\0') {	/* 2 character suffix */
			if (*s == 'b' && s[1] == 'p' ||	/* breakpoint listing */
			    *s == 'q' &&
				(s[1] == 'c' || s[1] == 'h')) { /* Ingres */
				cscanner = YES;
			}
			else
			if (*s == 'l' && s[1] == 'h' || /* SDL */
			    *s == 'p' && s[1] == 'r' ||	/* SDL */
			    *s == 's' && s[1] == 'd') {	/* SDL */
				sscanner = YES;
			}
			else {
				/* try to parse with c scanner */
				cscanner = YES;
			}
		}
		else if (strcmp(s,"cpp") == 0 || strcmp(s,"CPP") == 0) {
			/* MS visual C++ */
			cscanner = YES;
		}
		else if (strcmp(s,"hpp") == 0 || strcmp(s,"HPP") == 0) {
			/* MS visual C++ */
			cscanner = YES;
		}
		else if (strcmp(s,"java") == 0 || strcmp(s,"JAVA") == 0) {
			/* Java */
			jscanner = YES;
		}
		else {
			/* try to parse with c scanner */
			cscanner = YES;
		}
	} else {
		/* try to parse with c scanner */
		cscanner = YES;
	}
}

void
initscanner(srcfile)
char	*srcfile;
{
	setscanner(srcfile);

	if (cscanner == YES) {
		cinitscanner(srcfile);
		first = cfirst;
		last = clast;
		lineno = clineno;
		yytext = lyytext;
		yyleng = 0;
		yylineno = cmyylineno;
	}
	else if (jscanner == YES) {
		jinitscanner(srcfile);
		first = jfirst;
		last = jlast;
		lineno = jlineno;
		yytext = lyytext;
		yyleng = 0;
		yylineno = jmyylineno;
	}
	else if (sscanner == YES) {
		sinitscanner(srcfile);
		first = sfirst;
		last = slast;
		lineno = slineno;
		yytext = lyytext;
		yyleng = 0;
		yylineno = smyylineno;
	}
	return;
}

/* put the keywords into the symbol table */

void
initsymtab()
{
	cinitsymtab();
	jinitsymtab();
	sinitsymtab();
}

/* save the symbol in the list */

void
csavesymbol(token)
int	token;
{
	first = cfirst;
	last = clast;
	yyleng = cyyleng;

	savesymbol(token);
}

/* save the symbol in the list */

void
jsavesymbol(token)
int	token;
{
	first = jfirst;
	last = jlast;
	yyleng = jyyleng;

	savesymbol(token);
}

/* save the symbol in the list */
void
ssavesymbol(token)
int	token;
{
	first = jfirst;
	last = jlast;
	yyleng = jyyleng;

	savesymbol(token);
}

/* return keyword structure */

struct	keystruct *
keyword(c)
register unsigned c;
{
	if (cscanner == YES) {
		return(&ckeyword[c]);
	} else if (jscanner == YES) {
		return(&jkeyword[c]);
	} else if (sscanner == YES) {
		return(&skeyword[c]);
	} else {
		return(NULL);
	}
}

/* see if this identifier is a keyword */

struct	keystruct *
lookup(ident)
register char	*ident;
{
	if (cscanner == YES) {
		return(clookup(ident));
	} else if (jscanner == YES) {
		return(jlookup(ident));
	} else if (sscanner == YES) {
		return(slookup(ident));
	} else {
		return(NULL);
	}
}

/* form hash value for string */

hash(s)
register char	*s;
{
	register unsigned i;
	
	for (i = 0; *s != '\0'; )
		i += *s++;	/* += is faster than <<= for cscope */
	return(i);
}
#endif
