/* SDB - token scanning routines */

#include "bdscio.h"
#include "dbqdefs.h"

#define STDIN 0		/* Maybe - check up */

db_sinit()
{
	atbol = TRUE;
	lptr = NULL;
	savech = EOS;
	savetkn = NULL;
	dbv_ifp = NULL;
	dbv_lfp = NULL;
	dbv_macros = NULL;
	dbv_verify = FALSE;
	dbv_total = FALSE;
	dbv_fold = TRUE;
	dbv_auto = FALSE;
	dbv_logging = FALSE;
	dbv_pgln = 32000;	/* equivalent to no paging */
}

db_prompt(ip,cp)
	char *ip,*cp;
{
	iprompt = ip;
	cprompt = cp;
}

#ifdef DBPI
db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
{
	sprintf(cmdline,fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10);

	lptr = cmdline;
	iprompt = NULL;
	dbv_ifp = NULL;

	savech = EOS;
	savetkn = NULL;
	dbv_fold = TRUE;
}
#endif

int db_flush(range)
int range;
	/* range = 1 to flush out anything on line, else NULL to check */
{
	while (savech != '\n')
		if (savech > ' ' && range == NULL)
			{ RETERR(SYNTAX) }
		else
			savech = getchx();

	savech = EOS;
	atbol = TRUE;
	return (TRUE);
}

char *db_gline(buf)
	char *buf;
{
	int ch,i;

	for (i = 0; (ch = getch()) != '\n' && ch != -1; )
		if (i < LINEMAX)
			buf[i++] = ch;
		else {
			printf("### Maximum line length is %d ###\nRe-enter> ",LINEMAX);
			i = 0;
		}
	buf[i] = EOS;

	return (buf);
}

int db_ifile(fname)
	char *fname;
{
	struct ifile *new_ifp;

	if ((new_ifp = CALLOC(IFSIZE)) == NULL)
		{ RETERR(INSMEM) }
	else if ((new_ifp->if_fp = CALLOC(BUFSIZ)) == NULL)
		{ CFREE(new_ifp);
		RETERR(INSMEM) }
	else if (fopen(fname,new_ifp->if_fp) == -1) {
		CFREE(new_ifp->if_fp);
		CFREE(new_ifp);
		RETERR(INDFNF)
	}
	new_ifp->if_mtext = NULL;
	new_ifp->if_savech = savech;
	new_ifp->if_lptr = lptr;
	new_ifp->if_next = dbv_ifp;
	dbv_ifp = new_ifp;

	return (TRUE);
}

db_kill()
{
	struct ifile *old_ifp;

	while ((old_ifp = dbv_ifp) != NULL) {
		dbv_ifp = old_ifp->if_next;
		if (old_ifp->if_fp != NULL)
			{ fclose(old_ifp->if_fp);
			  CFREE(old_ifp->if_fp); }
		savech = old_ifp->if_savech;
		lptr = old_ifp->if_lptr;
		CFREE(old_ifp);
	}

	while (savech != '\n')
		savech = getchx();
	savech = EOS;
	savetkn = NULL;
	atbol = TRUE;
}

int db_token()
{
	struct macro *mptr;
	struct ifile *new_ifp;
	while (db_xtoken() == ID) {
	  for (mptr = dbv_macros; mptr != NULL; mptr = mptr->mc_next)
		if (db_scmp(dbv_tstring,mptr->mc_name) == 0) {
		   if ((new_ifp = CALLOC(IFSIZE)) == NULL)
			printf("### Out of memory using %s ###",dbv_tstring);
		   else {
			new_ifp->if_fp = NULL;
			new_ifp->if_mtext = mptr->mc_mtext->mt_next;
			new_ifp->if_lptr = lptr; lptr = mptr->mc_mtext->mt_text;
			new_ifp->if_savech = savech; savech = EOS;
			new_ifp->if_next = dbv_ifp;
			dbv_ifp = new_ifp;
		   }
		   savetkn = NULL;
		   break;
		}

	  if (mptr == NULL)
		break;

	}

	return (dbv_token);
}

int db_xtoken()
{
	int ch;
	if ((dbv_token = savetkn) != NULL)
		return (dbv_token);

	ch = nextch();

	if (isalpha(ch))
		get_id();
	else if ((isdigit(ch)) || (ch == '-'))
		get_number();
	else if (ch == '"')
		get_string();
	else if (get_rel())
		;
	else
		dbv_token = getch();

	savetkn = dbv_token;
	return (dbv_token);
}

int db_ntoken()
{
	db_token();

	savetkn = NULL;

	return (dbv_token);
}

int db_xntoken()
{
	db_xtoken();
	savetkn = NULL;
	return (dbv_token);
}

int db_scmp(str1,str2)
	char *str1,*str2;
{
	if (dbv_fold)
		return (scmp(str1,str2));
	else
		return (strcmp(str1,str2));
}

int db_sncmp(str1,str2,len)
	char *str1,*str2; int len;
{
	if (dbv_fold)
		return (sncmp(str1,str2,len));
	else
		return (strncmp(str1,str2,len));
}

int scmp(str1,str2)
	char *str1,*str2;
{
	int ch1,ch2;

	while (*str1 && *str2) {

		ch1 = tolower(*str1++);
		ch2 = tolower(*str2++);

		if (ch1 != ch2)
			if (ch1 < ch2)
				return (-1);
			else
				return (1);
	}

	if (*str1 == *str2)
		return (0);
	else if (*str1 == 0)
		return (-1);
	else
		return (1);
}


int sncmp(str1,str2,len)
	char *str1,*str2; int len;
{
	int ch1,ch2;

	while (*str1 && *str2 && len > 0) {

		ch1 = tolower(*str1++);

		ch2 = tolower(*str2++);

		if (ch1 != ch2)
			if (ch1 < ch2)
				return (-1);
			else
				return (1);
		len--;
	}

	if (len == 0 || *str1 == *str2)
		return (0);
	else if (*str1 == 0)
		return (-1);
	else
		return (1);
}

#define KEYMATCH(kmword,kmtoken) if (db_scmp(dbv_tstring,kmword) == 0) dbv_token = kmtoken

get_id()
{
	int ch,nchars,i;

	ch = nextch();
	nchars = 0;

/*	if alphanumeric or underscore or colon	*/

	while (isalpha(ch) || isdigit(ch) || ch == 95 || ch == 58) {
		if (nchars < KEYWORDMAX)
			dbv_tstring[nchars++] = ch;
		getch(); ch = thisch();
	}

	dbv_tstring[nchars] = EOS;

	dbv_token = ID;

/*	keywords - most popular ones first	*/

	KEYMATCH("print",PRINT);
	KEYMATCH("with",WHERE);
	KEYMATCH("define",DEFYNE);
	KEYMATCH("enter",PROMPT);
	KEYMATCH("delete",DELETE);
	KEYMATCH("of",FROM);
	KEYMATCH("insert",INSERT);
	KEYMATCH("find",SELECT);
	KEYMATCH("update",UPDATE);
	KEYMATCH("using",USING);
	KEYMATCH("show",SHOW);
	KEYMATCH("into",INTO);
/* character keywords */
	KEYMATCH("help",HELP);
	KEYMATCH("and",CHAND);
	KEYMATCH("or",CHOR);
	KEYMATCH("not",CHNOT);
	KEYMATCH("all",CHALL);

/*	keywords for DBA	*/

	KEYMATCH("asc",ASCENDING);
	KEYMATCH("by",BY);
	KEYMATCH("char",CHARR);
	KEYMATCH("compress",COMPRESS);
	KEYMATCH("create",CREATE);
	KEYMATCH("desc",DESCENDING);
	KEYMATCH("export",EXPORT);
	KEYMATCH("extract",EXTRACT);
	KEYMATCH("import",IMPORT);
	KEYMATCH("num",NUM);
	KEYMATCH("sort",SORT);
	KEYMATCH("erase",ERASE);
	KEYMATCH("rename",RENAME);

/*	common keywords		*/

	KEYMATCH("exit",EXXIT);
	KEYMATCH("set",SET);

}

get_number()

{
	int ch,ndigits,nodot;

	ch = nextch();
	ndigits = 0; nodot = TRUE;
	while (isdigit(ch) || (ch == '-') || (nodot && ch == '.')) {
		if (ch == '.')
			nodot = FALSE;
		if (ndigits < NUMBERMAX)
			dbv_tstring[ndigits++] = ch;
		getch(); ch = thisch();
	}

	dbv_tstring[ndigits] = EOS;

	sscanf(dbv_tstring,"%d",&dbv_tvalue);

	dbv_token = NUMBER;
}

get_string()
{
	int ch,nchars;

	getch();

	ch = thisch();
	nchars = 0;
	while (ch && ch != '"') {
		if (nchars < STRINGMAX)
			dbv_tstring[nchars++] = ch;
		getch(); ch = thisch();
	}

	dbv_tstring[nchars] = EOS;
	getch();
	dbv_token = STRING;
}

int get_rel()
{
	int ch;

	switch (ch = nextch()) {
	case '=':
		getch();
		dbv_token = EQL;
		return (TRUE);;
	case '<':
		getch(); ch = nextch();
		if (ch == '>') {
			getch();
			dbv_token = NEQ;
		}
		else if (ch == '=') {
			getch();
			dbv_token = LEQ;
		}
		else
			dbv_token = LSS;
		return (TRUE);;
	case '>':
		getch(); ch = nextch();
		if (ch == '=') {
			getch();
			dbv_token = GEQ;
		}
		else
			dbv_token = GTR;
		return (TRUE);;
	case '}':
		getch();
		dbv_token = CONT;
		return (TRUE);;
	default:
		return (FALSE);
	}
}

int getch()
{
	char fname[STRINGMAX+1];
	int ch,i;
	if (savech != EOS) {
		ch = savech;
		savech = EOS;
		return (ch);
	}

	ch = getchx();

	if (atbol && iprompt != NULL)
		while (ch <= ' ')
			ch = getchx();
	iprompt = NULL;

	while (ch == '@') {
		for (i = 0; (savech = getchx()) > ' '; )
			if (i < STRINGMAX)
				fname[i++] = savech;
		fname[i] = 0;
		if (db_ifile(fname) != TRUE)
			printf("### Error opening ICF %s ###\n",fname);
		ch = getchx();
	}

	return (ch);
}	

int getchx()
{
	struct ifile *old_ifp;
	int ch;

	if (lptr != NULL) {
		while (*lptr == EOS)

		/* some stuff for ICFs */
		 if (dbv_ifp != NULL)
		  if (dbv_ifp->if_mtext == NULL) {
			old_ifp = dbv_ifp;
			ch = dbv_ifp->if_savech; savech = EOS;
			lptr = dbv_ifp->if_lptr;
			dbv_ifp = dbv_ifp->if_next;
			if (old_ifp->if_fp != NULL)
				CFREE(old_ifp->if_fp);
			CFREE(old_ifp);
			if (ch != EOS)
				return (ch);
			if (lptr == NULL)
				break;
		}
		else {
			lptr = dbv_ifp->if_mtext->mt_text;
			dbv_ifp->if_mtext = dbv_ifp->if_mtext->mt_next;
		}
	else
		return (EOS);

		if (lptr != NULL)
			return (*lptr++);
	}

	if (atbol && dbv_ifp == NULL) {
		if (iprompt != NULL)
			printf("%s",iprompt);
		else if (cprompt != NULL)
			printf("%s",cprompt);
	}

	if (dbv_ifp == NULL)
		if ((ch = getcx(STDIN)) == '\n')
			atbol = TRUE;
		else
			atbol = FALSE;
	    else {
		if (((ch = getcx(dbv_ifp->if_fp)) == ERROR) || (ch == CPMEOF)) {
			old_ifp = dbv_ifp;
			ch = dbv_ifp->if_savech; savech = EOS;
			lptr = dbv_ifp->if_lptr;
			dbv_ifp = dbv_ifp->if_next;
			fclose(old_ifp->if_fp);
			CFREE(old_ifp->if_fp);
			CFREE(old_ifp);
		}
	}
	return (ch);
}

int thisch()
{
	if (savech == EOS)
		savech = getch();

	return (savech);
}

int nextch()
{
	int ch;

	while ((ch = thisch()) <= ' ' && ch != EOS)
		getch();

	return (ch);
}

n (