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;
 | |
| }
 |