484 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			484 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
#ifndef NORSCID
 | 
						|
static char rcs_lex[] = "$Header$" ;
 | 
						|
#endif
 | 
						|
 | 
						|
/* This file contains the new lexical analizer */
 | 
						|
typedef struct {
 | 
						|
	char *name; 
 | 
						|
	int token, classvalue,length;
 | 
						|
} Key;
 | 
						|
 | 
						|
Key keywords [] ={
 | 
						|
"abs",		FUNCTION,	ABSSYM,		0,
 | 
						|
"and",		BOOLOP,		ANDSYM,		0,
 | 
						|
"asc",		FUNCTION,	ASCSYM,		0,
 | 
						|
"as",		 ASSYM,		0,	0,
 | 
						|
"atn",		FUNCTION,	ATNSYM,		0,
 | 
						|
"auto",		ILLEGAL,	0,	0,
 | 
						|
"base",		BASESYM,	0,	0,
 | 
						|
"call",		CALLSYM,	0,	0,
 | 
						|
"cdbl",		FUNCTION,	CDBLSYM,	0,
 | 
						|
"chain",	ILLEGAL,	0,	0,
 | 
						|
"chr",		FUNCTION,	CHRSYM,		0,
 | 
						|
"cint",		FUNCTION,	CINTSYM,	0,
 | 
						|
"clear",	CLEARSYM,	0,	0,
 | 
						|
"cload",	ILLEGAL,	0,	0,
 | 
						|
"close",	ILLEGAL,	0,	0,
 | 
						|
"common",	ILLEGAL,	0,	0,
 | 
						|
"cont",		ILLEGAL,	0,	0,
 | 
						|
"cos",		FUNCTION,	COSSYM,		0,
 | 
						|
"csng",		FUNCTION,	CSNGSYM,	0,
 | 
						|
"csave",	ILLEGAL,	0,	0,
 | 
						|
"cvi",		FUNCTION,	CVISYM,		0,
 | 
						|
"cvs",		FUNCTION,	CVSSYM,		0,
 | 
						|
"cvd",		FUNCTION,	CVDSYM,		0,
 | 
						|
"data",		DATASYM,	0,	0,
 | 
						|
"defint",	DEFINTSYM,	0,	0,
 | 
						|
"defsng",	DEFSNGSYM,	0,	0,
 | 
						|
"defdbl",	DEFDBLSYM,	0,	0,
 | 
						|
"defstr",	DEFSTRSYM,	0,	0,
 | 
						|
"def",		DEFSYM,		0,	0,
 | 
						|
"delete",	ILLEGAL,	0,	0,
 | 
						|
"dim",		DIMSYM,		0,	0,
 | 
						|
"edit",		ILLEGAL,	0,	0,
 | 
						|
"else",		ELSESYM,	0,	0,
 | 
						|
"end",		ENDSYM,		0,	0,
 | 
						|
"eof",		FUNCTION,	EOFSYM,		0,
 | 
						|
"eqv",		BOOLOP,		EQVSYM,	0,
 | 
						|
"erase",	ILLEGAL,	0,	0,
 | 
						|
"error",	ERRORSYM,	0,	0,
 | 
						|
"err",		ERRSYM,		0,	0,
 | 
						|
"erl",		ERLSYM,		0,	0,
 | 
						|
"exp",		FUNCTION,	EXPSYM,		0,
 | 
						|
"field",	FIELDSYM,	0,	0,
 | 
						|
"fix",		FUNCTION,	FIXSYM,		0,
 | 
						|
"for",		FORSYM,		0,	0,
 | 
						|
"fre",		FUNCTION,	FRESYM,		0,
 | 
						|
"get",		GETSYM,		0,	0,
 | 
						|
"gosub",	GOSUBSYM,	0,	0,
 | 
						|
"goto",		GOTOSYM,	0,	0,
 | 
						|
"hex",		FUNCTION,	HEXSYM,		0,
 | 
						|
"if",		IFSYM,		0,	0,
 | 
						|
"imp",		BOOLOP,		IMPSYM,	0,
 | 
						|
"inkey",	INKEYSYM,	0,	0,
 | 
						|
"input",	INPUTSYM,	0,	0,
 | 
						|
"inp",		FUNCTION,	INPSYM,		0,
 | 
						|
"instr",	FUNCTION,	INSTRSYM,	0,
 | 
						|
"int",		FUNCTION,	INTSYM,		0,
 | 
						|
"kill",		ILLEGAL,	0,	0,
 | 
						|
"left",		FUNCTION,	LEFTSYM,	0,
 | 
						|
"len",		FUNCTION,	LENSYM,		0,
 | 
						|
"let",		LETSYM,		0,	0,
 | 
						|
"line",		LINESYM,	0,	0,
 | 
						|
"list",		LISTSYM,	0,	0,
 | 
						|
"llist",	ILLEGAL,	0,	0,
 | 
						|
"load",		LOADSYM,	0,	0,
 | 
						|
"loc",		FUNCTION,	LOCSYM,		0,
 | 
						|
"log",		FUNCTION,	LOGSYM,		0,
 | 
						|
"lpos",		FUNCTION,	LPOSSYM,	0,
 | 
						|
"lprint",	ILLEGAL,	0,	0,
 | 
						|
"lset",		LSETSYM,	0,	0,
 | 
						|
"merge",	MERGESYM,	0,	0,
 | 
						|
"mid",		MIDSYM,		0,		0,
 | 
						|
"mki",		FUNCTION,	MKISYM,		0,
 | 
						|
"mks",		FUNCTION,	MKSSYM,		0,
 | 
						|
"mkd",		FUNCTION,	MKDSYM,		0,
 | 
						|
"mod",		MODSYM,		0,	0,
 | 
						|
"name",		ILLEGAL,	0,	0,
 | 
						|
"new",		ILLEGAL,	0,	0,
 | 
						|
"next",		NEXTSYM,	0,	0,
 | 
						|
"not",			NOTSYM,	0,	0,
 | 
						|
"null",		ILLEGAL,	0,	0,
 | 
						|
"on",		ONSYM,		0,	0,
 | 
						|
"oct",		FUNCTION,	OCTSYM,		0,
 | 
						|
"open",		OPENSYM,	0,	0,
 | 
						|
"option",	OPTIONSYM,	0,	0,
 | 
						|
"or",		BOOLOP,		ORSYM,	0,
 | 
						|
"out",		FUNCTION,	OUTSYM,	0,
 | 
						|
"peek",		PEEKSYM,	0,	0,
 | 
						|
"poke",		POKESYM,	0,	0,
 | 
						|
"print",	PRINTSYM,	0,	0,
 | 
						|
"pos",		FUNCTION,	POSSYM,		0,
 | 
						|
"put",		PUTSYM,		0,	0,
 | 
						|
"randomi",	RANDOMIZESYM,	0,	0,
 | 
						|
"read",		READSYM,	0,	0,
 | 
						|
"rem",		REMSYM,		0,	0,
 | 
						|
"renum",	ILLEGAL,	0,	0,
 | 
						|
"ren",		ILLEGAL,	0,	0,
 | 
						|
"restore",	RESTORESYM,	0,	0,
 | 
						|
"resume",	ILLEGAL,	0,	0,
 | 
						|
"return",	RETURNSYM,	0,	0,
 | 
						|
"right",	FUNCTION,	RIGHTSYM,	0,
 | 
						|
"rnd",		FUNCTION,	RNDSYM,		0,
 | 
						|
"run",		ILLEGAL,	0,	0,
 | 
						|
"save",		ILLEGAL,	0,	0,
 | 
						|
"step",		STEPSYM,	0,	0,
 | 
						|
"sgn",		FUNCTION,	SGNSYM,		0,
 | 
						|
"sin",		FUNCTION,	SINSYM,		0,
 | 
						|
"space",	FUNCTION,	SPACESYM,	0,
 | 
						|
"spc",		FUNCTION,	SPCSYM,		0,
 | 
						|
"sqr",		FUNCTION,	SQRSYM,		0,
 | 
						|
"stop",		STOPSYM,	0,	0,
 | 
						|
"string",	FUNCTION,	STRINGSYM,	0,
 | 
						|
"str",		FUNCTION,	STRSYM,		0,
 | 
						|
"swap",		SWAPSYM,	0,	0,
 | 
						|
"tab",		FUNCTION,	TABSYM,		0,
 | 
						|
"tan",		FUNCTION,	TANSYM,		0,
 | 
						|
"then",		THENSYM,	0,	0,
 | 
						|
"to",		TOSYM,		0,		0,
 | 
						|
"tron",		TRONOFFSYM,	TRONSYM,	0,
 | 
						|
"troff",	TRONOFFSYM,	TROFFSYM,	0,
 | 
						|
"using",	USINGSYM,	0,	0,
 | 
						|
"usr",		FUNCTION,	USRSYM,		0,
 | 
						|
"val",		FUNCTION,	VALSYM,		0,
 | 
						|
"varptr",	FUNCTION,	VARPTRSYM,	0,
 | 
						|
"wait",		ILLEGAL,	0,	0,
 | 
						|
"while",	WHILESYM,	0,	0,
 | 
						|
"wend",		WENDSYM,	0,	0,
 | 
						|
"width",	ILLEGAL,	0,	0,
 | 
						|
"write",	WRITESYM,	0,	0,
 | 
						|
"xor",		BOOLOP,		XORSYM,	0,
 | 
						|
0,	0,	0,	0
 | 
						|
};
 | 
						|
 | 
						|
char *index();
 | 
						|
 | 
						|
/* Keyword index table */
 | 
						|
 | 
						|
int	kex[27];
 | 
						|
 | 
						|
/* Initialize the keyword table */
 | 
						|
fillkex()
 | 
						|
{
 | 
						|
	Key *k;
 | 
						|
	int i;
 | 
						|
	for(k=keywords;k->name;k++)
 | 
						|
		k->length= strlen(k->name);
 | 
						|
	k=keywords;
 | 
						|
	for(i=0;k->name && i<='z'-'a';i++)
 | 
						|
	{
 | 
						|
		for(;k->name && *k->name<i+'a';k++);
 | 
						|
		if( *k->name!=i+'a') continue;
 | 
						|
		kex[*k->name-'a']=k-keywords;
 | 
						|
		for(;k->name && *k->name==i+'a';k++);
 | 
						|
		kex[*(k-1)->name-'a'+1]=k-keywords;
 | 
						|
	}
 | 
						|
	if(debug)
 | 
						|
	{
 | 
						|
		for(i=0;i<27;i++)
 | 
						|
		printf("%c:%d\n",'a'+i,kex[i]);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
#include <ctype.h>
 | 
						|
 | 
						|
/* Get each line separately into the buffer */
 | 
						|
/* Lines too long are terminated and flagged illegal */
 | 
						|
 | 
						|
#define MAXLINELENGTH	1024
 | 
						|
 | 
						|
char	inputline[MAXLINELENGTH];	/* current source line */
 | 
						|
char	*cptr;				/* next character to decode */
 | 
						|
int	yylineno=0;			/* source line counter */
 | 
						|
 | 
						|
getline()
 | 
						|
{
 | 
						|
	/* get next input line */
 | 
						|
 | 
						|
	if( fgets(inputline,MAXLINELENGTH,yyin) == NULL)
 | 
						|
		return(FALSE);
 | 
						|
	yylineno ++;
 | 
						|
	if( index(inputline,'\n') == 0)
 | 
						|
		error("source line too long");
 | 
						|
	inputline[MAXLINELENGTH-1]=0;
 | 
						|
	if( listing)
 | 
						|
		fputs(inputline,stdout);
 | 
						|
	cptr= inputline;
 | 
						|
	return(TRUE);
 | 
						|
}
 | 
						|
yyerror(str)
 | 
						|
char *str;
 | 
						|
{
 | 
						|
	error("Syntax error");
 | 
						|
}
 | 
						|
 | 
						|
typechar()
 | 
						|
{
 | 
						|
	switch(*cptr)
 | 
						|
	{
 | 
						|
	case '$':
 | 
						|
		cptr++; return( STRINGTYPE);
 | 
						|
	case '%':
 | 
						|
		cptr++; return( INTTYPE);
 | 
						|
	case '!':
 | 
						|
		cptr++; return( FLOATTYPE);
 | 
						|
	case '#':
 | 
						|
		cptr++; return( DOUBLETYPE);
 | 
						|
	}
 | 
						|
	return(0);
 | 
						|
}
 | 
						|
 | 
						|
/* symbols in Microsoft are significant for the first 40 characters */
 | 
						|
#define SIGNIFICANT 40
 | 
						|
char name[SIGNIFICANT+1];
 | 
						|
 | 
						|
lookup()
 | 
						|
{
 | 
						|
	Key *k;
 | 
						|
	Symbol *Sym;
 | 
						|
	char *c;
 | 
						|
	int i, typech;
 | 
						|
 | 
						|
	sval= name;
 | 
						|
	for(c=cptr; *c && isalnum(*c);c++) 
 | 
						|
	if( isupper(*c) )
 | 
						|
		*c= tolower((*c));
 | 
						|
	for(k= keywords+kex[*cptr-'a']; k->name != 0 && *(k->name)== *cptr;k++)
 | 
						|
	if( strncmp(cptr,k->name,k->length)==0)
 | 
						|
	{
 | 
						|
		/* check functions first*/
 | 
						|
		if( isalnum( *(cptr+k->length) ) &&
 | 
						|
		    k->token==FUNCTION) continue;
 | 
						|
		cptr += k->length;
 | 
						|
		yylval.integer= k->classvalue;
 | 
						|
		if(debug) printf("lookup:%d %d\n",
 | 
						|
				 k->classvalue,k->token);
 | 
						|
		if( k->token == FUNCTION)
 | 
						|
		{
 | 
						|
			/* stripp type character */
 | 
						|
			typech=typechar();
 | 
						|
		}
 | 
						|
			/* illegals + rem */
 | 
						|
			if( k->token == REMSYM || k->token==ILLEGAL)
 | 
						|
				while( *cptr && *cptr!=':' && *cptr!='\n')
 | 
						|
					cptr++;
 | 
						|
			return( k->token);
 | 
						|
		}
 | 
						|
	/* Is it  a function  name ? */
 | 
						|
	c=cptr;
 | 
						|
	/* Identifier found, update the symbol table */
 | 
						|
	i=0;
 | 
						|
	while( isalnum(*c) || *c == '.')
 | 
						|
		if( i<SIGNIFICANT) name[i++]= *c++;
 | 
						|
	name[i]=0;
 | 
						|
	cptr=c;
 | 
						|
	Sym= srchsymbol(name);
 | 
						|
	yylval.Sptr = Sym;
 | 
						|
	typech= typechar();
 | 
						|
	if(Sym->symtype!=DEFAULTTYPE) 
 | 
						|
	{
 | 
						|
		if(typech && typech!=Sym->symtype && wflag)
 | 
						|
			warning("type re-declared,ignored");
 | 
						|
	}
 | 
						|
	if( typech)
 | 
						|
		Sym->symtype=typech;
 | 
						|
	if(debug) printf("lookup:%d Identifier\n",Sym);
 | 
						|
	if( (name[0]=='f' || name[0]=='F') &&
 | 
						|
	    (name[1]=='n' || name[1]=='N') )
 | 
						|
		return(FUNCTID);
 | 
						|
	return(IDENTIFIER);
 | 
						|
}
 | 
						|
 | 
						|
/* Parsing unsigned numbers */
 | 
						|
readconstant()
 | 
						|
{
 | 
						|
	/* read HEX and OCTAL numbers */
 | 
						|
	char *c;
 | 
						|
	cptr++;
 | 
						|
	if( *cptr == 'H' || *cptr=='h')
 | 
						|
	{
 | 
						|
		/* HEX */
 | 
						|
		cptr++;
 | 
						|
		c=cptr;
 | 
						|
		while(  isdigit(*cptr) || 
 | 
						|
			(*cptr>='a' && *cptr<='f' ) ||
 | 
						|
			(*cptr>='A' && *cptr<='F' ) )cptr++;
 | 
						|
		sscanf(c,"%x",&ival);
 | 
						|
	} else 
 | 
						|
	if( *cptr == 'O' || *cptr == 'o')
 | 
						|
	{
 | 
						|
		/* OCTAL */
 | 
						|
		cptr++;
 | 
						|
		c=cptr;
 | 
						|
		while( isdigit(*cptr) ) cptr++;
 | 
						|
		sscanf(c,"%o",&ival);
 | 
						|
	} else
 | 
						|
	error("H or O expected");
 | 
						|
	return(INTVALUE);
 | 
						|
}
 | 
						|
 | 
						|
number()
 | 
						|
{
 | 
						|
	long	i1;
 | 
						|
	double	atof();
 | 
						|
	register char *c;
 | 
						|
	int overflow = 0;
 | 
						|
	char cx;
 | 
						|
 | 
						|
	i1=0;
 | 
						|
	c=cptr;
 | 
						|
	while(isdigit(*c)){
 | 
						|
		i1= i1*10 + *c-'0';
 | 
						|
		if (i1 < 0) overflow = 1;
 | 
						|
		c++;
 | 
						|
	}
 | 
						|
	if( *c != '.'){
 | 
						|
		if( i1> MAXINT || i1<MININT || overflow) {
 | 
						|
			cx = *c;
 | 
						|
			*c = 0;
 | 
						|
			/*NOSTRICT*/ dval= atof(cptr);
 | 
						|
			cptr=c;
 | 
						|
			*c = cx;
 | 
						|
			return(FLTVALUE);
 | 
						|
		}
 | 
						|
		/*NOSTRICT*/ ival= i1;
 | 
						|
		cptr = c;
 | 
						|
#ifdef YYDEBUG
 | 
						|
		if(yydebug) printf("number:INTVALUE %d",i1);
 | 
						|
#endif
 | 
						|
		return(INTVALUE);
 | 
						|
	}
 | 
						|
	/* handle floats */
 | 
						|
	/*NOSTRICT*/
 | 
						|
	c++;
 | 
						|
	while( isdigit(*c)){
 | 
						|
		c++;
 | 
						|
	}
 | 
						|
	/* handle exponential part */
 | 
						|
	if( *c =='e' || *c == 'E'){
 | 
						|
		c++;
 | 
						|
		while(isdigit(*c)){
 | 
						|
			c++;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	cx = *c; *c = 0;
 | 
						|
	dval = atof(cptr);
 | 
						|
	*c = cx; cptr=c;
 | 
						|
#ifdef YYDEBUG
 | 
						|
	if(yydebug) printf("number:FLTVALUE %f",dval);
 | 
						|
#endif
 | 
						|
	return(FLTVALUE);
 | 
						|
}
 | 
						|
scanstring()
 | 
						|
{
 | 
						|
	int i,length;
 | 
						|
	char firstchar;
 | 
						|
	/* skip this string value, you might as well copy it to
 | 
						|
	   the EM file as well, because it is not used internally
 | 
						|
	*/
 | 
						|
	/* generate label here */
 | 
						|
	yylval.integer= genrom();
 | 
						|
	length=0;
 | 
						|
	if( fputc('"',emfile) == EOF) fatal("scanstring");
 | 
						|
	sval= cptr;
 | 
						|
	firstchar = *cptr;
 | 
						|
	if( *cptr== '"') cptr++;
 | 
						|
	while( *cptr !='"')
 | 
						|
	{
 | 
						|
		switch(*cptr)
 | 
						|
		{
 | 
						|
		case 0:
 | 
						|
		case '\n': 
 | 
						|
#ifdef YYDEBUG
 | 
						|
			if(yydebug) printf("STRVALUE\n");
 | 
						|
#endif
 | 
						|
			if( firstchar == '"')
 | 
						|
				error("non-terminated string");
 | 
						|
			return(STRVALUE);
 | 
						|
		case '\'':
 | 
						|
		case '\\':
 | 
						|
			putc('\\', emfile);
 | 
						|
		default:
 | 
						|
			fputc(*cptr,emfile);
 | 
						|
		}
 | 
						|
		cptr++;
 | 
						|
		length++;
 | 
						|
	}
 | 
						|
	*cptr=0;
 | 
						|
	cptr++;
 | 
						|
	fprintf(emfile,"\\000\"\n");
 | 
						|
	i=yylval.integer;
 | 
						|
	yylval.integer= genrom();
 | 
						|
	fprintf(emfile,"l%d,9999,%d\n",i,length);
 | 
						|
#ifdef YYDEBUG
 | 
						|
	if(yydebug) printf("STRVALUE found\n");
 | 
						|
#endif
 | 
						|
	return(STRVALUE);
 | 
						|
}
 | 
						|
yylex()
 | 
						|
{
 | 
						|
	char *c;
 | 
						|
 | 
						|
	/* Here is the big switch */
 | 
						|
	c= cptr;
 | 
						|
	switch(*c){
 | 
						|
	case 'a': case 'b': case 'c': case 'd': case 'e':
 | 
						|
	case 'f': case 'g': case 'h': case 'i': case 'j':
 | 
						|
	case 'k': case 'l': case 'm': case 'n': case 'o':
 | 
						|
	case 'p': case 'q': case 'r': case 's': case 't':
 | 
						|
	case 'u': case 'v': case 'w': case 'x': case 'y':
 | 
						|
	case 'z': case 'A': case 'B': case 'C': case 'D':
 | 
						|
	case 'E': case 'F': case 'G': case 'H': case 'I':
 | 
						|
	case 'J': case 'K': case 'L': case 'M': case 'N':
 | 
						|
	case 'O': case 'P': case 'Q': case 'R': case 'S':
 | 
						|
	case 'T': case 'U': case 'V': case 'W': case 'X':
 | 
						|
	case 'Y': case 'Z': case '_': 
 | 
						|
		return(lookup());
 | 
						|
 | 
						|
	case '0': case '1': case '2': case '3': case '4':
 | 
						|
	case '5': case '6': case '7': case '8': case '9':
 | 
						|
	case '.':
 | 
						|
		return(number());
 | 
						|
	case '\'':
 | 
						|
		/* comment at end of line */
 | 
						|
		while( *cptr != '\n' && *cptr) cptr++;
 | 
						|
	case '\n':
 | 
						|
		cptr++;
 | 
						|
		return(EOLN);
 | 
						|
	case 0:
 | 
						|
#ifdef YYDEBUG
 | 
						|
		if( yydebug) printf("end of buffer");
 | 
						|
#endif
 | 
						|
		return(0);
 | 
						|
	case '"':
 | 
						|
		return(scanstring());
 | 
						|
	/* handle double operators */
 | 
						|
	case ' ':
 | 
						|
	case '\t':
 | 
						|
		cptr++;
 | 
						|
		return(yylex());
 | 
						|
	case '&':
 | 
						|
		return(readconstant());
 | 
						|
	case '?': 
 | 
						|
		cptr++;
 | 
						|
		return(PRINTSYM);
 | 
						|
	case '>':
 | 
						|
		if( *(c+1)=='='){
 | 
						|
			c++;c++;cptr=c; yylval.integer= GESYM;return(RELOP);
 | 
						|
		}
 | 
						|
		yylval.integer= '>';
 | 
						|
		cptr++;
 | 
						|
		return(RELOP);
 | 
						|
	case '<':
 | 
						|
		if( *(c+1)=='='){
 | 
						|
			c++; c++; cptr=c; yylval.integer=LESYM; return(RELOP);
 | 
						|
		} else
 | 
						|
		if( *(c+1)=='>'){
 | 
						|
			c++; c++; cptr=c; yylval.integer=NESYM; return(RELOP);
 | 
						|
		} 
 | 
						|
		yylval.integer= '<';
 | 
						|
		cptr++;
 | 
						|
		return(RELOP);
 | 
						|
	}
 | 
						|
	return(*cptr++);
 | 
						|
}
 | 
						|
 | 
						|
char *
 | 
						|
index(s, c)
 | 
						|
	register char *s, c;
 | 
						|
{
 | 
						|
	while (*s)
 | 
						|
		if (*s++ == c)
 | 
						|
			return --s;
 | 
						|
	return (char *)0;
 | 
						|
}
 |