File:  [Research Unix] / researchv10no / cmd / ccom / common / scan.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:21:35 2018 UTC (8 years, 1 month ago) by root
Branches: belllabs, MAIN
CVS tags: researchv10, HEAD
researchv10 Norman

/* @(#) scan.c: 1.2 2/27/84				*/

# include "mfile1.h"
# include <ctype.h>
/* temporarily */

/* character-set translation */
# ifndef CCTRANS
# define CCTRANS(x) (x)
# endif

int flflag = 0, Oflag;
# ifndef FLOATCVT
double atof();
# define FLOATCVT(x) atof(x)
# endif

# ifndef ASMBUF
# define ASMBUF 200
# endif
char asmbuf[ASMBUF];
char *asmp;
int asm_esc = 0; /* asm escaped used in file */
/* lexical actions */

# define A_ERR 0		/* illegal character */
# define A_LET 1		/* saw a letter */
# define A_DIG 2		/* saw a digit */
# define A_1C 3			/* return a single character */
# define A_STR 4		/* string */
# define A_CC 5			/* character constant */
# define A_BCD 6		/* GCOS BCD constant */
# define A_SL 7			/* saw a / */
# define A_DOT 8		/* saw a . */
# define A_PL 9		/* + */
# define A_MI 10		/* - */
# define A_EQ 11		/* = */
# define A_NOT 12		/* ! */
# define A_LT 13		/* < */
# define A_GT 14		/* > */
# define A_AND 16		/* & */
# define A_OR 17		/* | */
# define A_WS 18		/* whitespace (not \n) */
# define A_NL 19		/* \n */

/* character classes */

# define LEXLET 01
# define LEXDIG 02
# define LEXOCT 04
# define LEXHEX 010
# define LEXWS 020
# define LEXDOT 040

/* reserved word actions */

# define AR_TY 0		/* type word */
# define AR_RW 1		/* simple reserved word */
# define AR_CL 2		/* storage class word */
# define AR_S 3		/* struct */
# define AR_U 4		/* union */
# define AR_E 5		/* enum */
# define AR_A 6		/* asm */

/* text buffer */
# define LXTSZ BUFSIZ		/* lots of room for FLEXNAMES */
char yytext[LXTSZ];
char * lxgcp;
/* If TRUNCATE is undefined, let -T determine whether symbols are truncated.
** Otherwise, forcibly truncate all names.
*/

static int truncate_flag =
#ifndef	TRUNCATE
0;		/* truncate based on -T (non-zero to truncate */
#else
1;		/* force all names <= NCHNAM chars */
#endif

int zflag = 0;


/* ARGSUSED */
mainp1( argc, argv )
int argc;
char *argv[];
{
	/* control multiple files */

	register i;
	register char *cp;
	extern int idebug, bdebug, tdebug, edebug, ddebug, xdebug, opdebug;
	extern int asdebug, nowarn, proflag, bothdebug, syncstdio, Pflag;
	extern int onlywarn;
	extern unsigned int maxoffset;
	int fdef = 0;

	unsigned int temp = 1;
	i = 0;
	do {
		temp <<= 1;
		++i;
	} while ( temp != 0 );
	maxoffset = 1 << (i-1);

	for( i=1; i<argc; ++i ) {
		if( *(cp=argv[i]) == '-' && *++cp == 'X' ) {
			while( *++cp ) switch(++syncstdio, *cp) {
			case 'P': ++Pflag; break;
			case 'W': onlywarn=1; break;	/* some fatal is not */
			case 'B':
				++bothdebug; break;
			case 'O':
				Oflag++; break;
			case 'd':
				++ddebug; break;
			case 'i':
				++idebug; break;
			case 'b':
				++bdebug; break;
			case 't':
				++tdebug; break;
			case 'e':
				++edebug; break;
			case 'x':
				++xdebug; break;
			case 'o':
				++opdebug; break;
			case 'p':
				++proflag; break;
			case 's':
				++asdebug; --syncstdio; break;
			case 'w':
				++nowarn; --syncstdio; break;
			case 'z':	/* stin file debug info */
				++zflag; break;
			case 'T':	/* truncate names */
				++truncate_flag; break;
			default:
				cerror( "bad option: X%c", *cp );
			}
		} else {
			if( *(argv[i]) != '-' ) switch( fdef++ ) {
			case 0:
				close(0);
				if (open(argv[i], 0) == 0) break;
				fprintf(stderr, "ccom: can't open %s\n", argv[i]);
				exit(1);

			case 1:
				if (freopen(argv[i], "w", stdout)) break;
				fprintf(stderr, "ccom: can't open %s\n", argv[i]);
				exit(1);

			default:
				;
			}
		}
	}
	if (isatty(1)) ++syncstdio;

	p2init( argc, argv );

	for( i=0; i<SYMTSZ; ++i ) stab[i].stype = TNULL;

	lxinit();
	tinit();
	mkdope();

	/* dimension table initialization */
	allodimtab();
	dimtab[NULL] = 0;
	dimtab[VOID] = 0;
	dimtab[CHAR] = SZCHAR;
	dimtab[INT] = SZINT;
	dimtab[FLOAT] = SZFLOAT;
	dimtab[DOUBLE] = SZDOUBLE;
	dimtab[LONG] = SZLONG;
	dimtab[SHORT] = SZSHORT;
	dimtab[UCHAR] = SZCHAR;
	dimtab[USHORT] = SZSHORT;
	dimtab[UNSIGNED] = SZINT;
	dimtab[ULONG] = SZLONG;
	/* starts past any of the above */
	curdim = 16;
	reached = 1;

	yyparse();
	yyaccpt();

# ifdef GDEBUG
	ejsdb();
# endif
# ifdef ENDJOB
	ENDJOB(nerrors?1:0);
# endif
	return(nerrors?1:0);

}

# ifdef ibm

# define CSMASK 0377
# define CSSZ 256

# else

# define CSMASK 0177
# define CSSZ 128

# endif

/*
*	We buffer the input on a line by line basis
*	so that we can output the ``C'' source as comments
*	in the assembly language
*/
int	asdebug = 0;
static	char	linebuf[BUFSIZ+1];
static	char	*linecp = &linebuf[0], *endcp = &linebuf[0];
#undef	ungetc
#undef	getchar

#define	getchar()	(*linecp ? *linecp++ : eatline() )
#define	ungetchar()	--linecp
#define	ungetc(c)	*--linecp=(c)

eatline()
{
	static int savechar; char *index(), *memcpy();
	register n; register char *cp;
	if (asdebug) for (*linecp = savechar, n = 0;;) {
		if ((cp = index(linecp, '\n')) || (cp = endcp-1, n)) {
			savechar = *++cp;
			*cp = '\0';
			spitline(linecp);
			return *linecp++;
		}
		linecp = memcpy(linebuf, linecp, n = endcp - linecp);
		if ((n = read(0, endcp = linebuf + n, BUFSIZ - n)) <= 0) {
			*(endcp = linebuf) = '\0';
			return EOF;
		}
		*(endcp += n) = '\0';
	} else {
		if ((n = read(0, linebuf, BUFSIZ)) <= 0) {
			(linecp = linebuf)[0] = 0;
			return EOF;
		} else {
			(linecp = linebuf)[n] = 0;
			return *linecp++;
		}
	}
}

/*
** add the original C line to the assembler output as comment,
** unless it is empty.
*/
#define	MARKERCNT	20	/* how often to spit out line markers */
spitline(l)
register char *l;
{
	extern int lineno;

	if( !(lineno%MARKERCNT) )
		printx( "%s -- line %d %s\n", COMMENTSTR, lineno, ftitle );
				/* line marker */
	while( isspace( *l ) )
		l++;
	if( *l )
		printx( "%s %s", COMMENTSTR, l );
}

short lxmask[CSSZ+1];

lxenter( s, m )
register char *s;
register short m;
{
	/* enter a mask into lxmask */
	register c;

	while( c= *s++ ) lxmask[c+1] |= m;

}


# define lxget(c,m) (lxgcp=yytext,lxmore(c,m))

lxmore( c, m )
register c, m;
{
	register char *cp;

	*(cp = lxgcp) = c;
	while ((c = getchar()), lxmask[c+1]&m) {
		if( cp < &yytext[LXTSZ-1])
			*++cp = c;
	}
	ungetchar();
	*(lxgcp = cp+1) = '\0';
}

struct lxdope
{
	short lxch;	/* the character */
	short lxact;	/* the action to be performed */
	short lxtok;	/* the token number to be returned */
	short lxval;	/* the value to be returned */
} lxdope[] =
{
	'$',	A_ERR,	0,	0,	/* illegal characters go here... */
	'_',	A_LET,	0,	0,	/* letters point here */
	'0',	A_DIG,	0,	0,	/* digits point here */
	' ',	A_WS,	0,	0,	/* whitespace goes here */
	'\n',	A_NL,	0,	0,
	'"',	A_STR,	0,	0,	/* character string */
	'\'',	A_CC,	0,	0,	/* character constant */
	'`',	A_BCD,	0,	0,	/* GCOS BCD constant */
	'(',	A_1C,	LP,	0,
	')',	A_1C,	RP,	0,
	'{',	A_1C,	LC,	0,
	'}',	A_1C,	RC,	0,
	'[',	A_1C,	LB,	0,
	']',	A_1C,	RB,	0,
	'*',	A_1C,	MUL,	MUL,
	'?',	A_1C,	QUEST,	0,
	':',	A_1C,	COLON,	0,
	'+',	A_PL,	PLUS,	PLUS,
	'-',	A_MI,	MINUS,	MINUS,
	'/',	A_SL,	DIVOP,	DIV,
	'%',	A_1C,	DIVOP,	MOD,
	'&',	A_AND,	AND,	AND,
	'|',	A_OR,	OR,	OR,
	'^',	A_1C,	ER,	ER,
	'!',	A_NOT,	UNOP,	NOT,
	'~',	A_1C,	UNOP,	COMPL,
	',',	A_1C,	CM,	CM,
	';',	A_1C,	SM,	0,
	'.',	A_DOT,	STROP,	DOT,
	'<',	A_LT,	RELOP,	LT,
	'>',	A_GT,	RELOP,	GT,
	'=',	A_EQ,	ASSIGN,	ASSIGN,
	-1,	A_1C,	0,	0,
};

struct lxdope *lxcp[CSSZ+1];

lxinit()
{
	register struct lxdope *p;
	register i;
	register char *cp;
	/* set up character classes */

	lxenter( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_", LEXLET );
	lxenter( "0123456789", LEXDIG );
	lxenter( "0123456789abcdefABCDEF", LEXHEX );
	/* \013 should become \v someday; \013 is OK for ASCII and EBCDIC */
	lxenter( " \t\r\b\f\013", LEXWS );
	lxenter( "01234567", LEXOCT );
	lxmask['.'+1] |= LEXDOT;
	lxhinit();

	/* make lxcp point to appropriate lxdope entry for each character */

	/* initialize error entries */

	for( i= 0; i<=CSSZ; ++i ) lxcp[i] = lxdope;

	/* make unique entries */

	for( p=lxdope; ; ++p )
	{
		lxcp[p->lxch+1] = p;
		if( p->lxch < 0 ) break;
	}

	/* handle letters, digits, and whitespace */
	/* by convention, first, second, and third places */

	cp = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
	while( *cp ) lxcp[*cp++ + 1] = &lxdope[1];
	cp = "123456789";
	while( *cp ) lxcp[*cp++ + 1] = &lxdope[2];
	cp = "\t\b\r\f\013";
	while( *cp ) lxcp[*cp++ + 1] = &lxdope[3];

	/* first line might have title */
	lineno = 1;
	lxtitle();

}

int lxmatch;  /* character to be matched in char or string constant */

lxstr(ct)
register ct;
{
	/* match a string or character constant, up to lxmatch */

	register c, val, i = 0;

	while ((c = getchar()) != lxmatch) {
		switch( c ) {

		case EOF:
			uerror( "lxstr() unexpected EOF" );
			break;

		case '\n':
			uerror( "newline in string or char constant" );
			++lineno;
			break;

		case '\\':
			switch (c = getchar()) {
			case '\n':
				++lineno; continue;
			default:
				val = c; goto mkcc;
			case 'n':
				val = '\n'; goto mkcc;
			case 'r':
				val = '\r'; goto mkcc;
			case 'b':
				val = '\b'; goto mkcc;
			case 't':
				val = '\t'; goto mkcc;
			case 'f':
				val = '\f'; goto mkcc;
			case 'v':
				val = '\013'; goto mkcc;
			case '0': case '1': case '2': case '3':
			case '4': case '5': case '6': case '7':
				val = c-'0';
				c = getchar();  /* try for 2 */
				if (lxmask[c+1] & LEXOCT) {
					val = (val<<3) | (c-'0');
					c = getchar();  /* try for 3 */
					if (lxmask[c+1] & LEXOCT)
						val = (val<<3) | (c-'0');
					else
						ungetchar();
				} else
					ungetchar();
				goto mkcc1;
			}
		default:
			val =c;
mkcc:
			val = CCTRANS(val);
mkcc1:
			if (lxmatch == '\'') {
				/* it is, after all, a "character" constant */
				val = ccast((CONSZ)val,CHAR);
				if (i == 0)
					lastcon = val;
				else {
# ifdef MAKECC
					MAKECC( val, i );
# else
# ifdef RTOLBYTES
					lastcon <<= SZCHAR;
					lastcon |= (val&BITMASK(SZCHAR));
# else
					lastcon &= BITMASK(SZCHAR*i);
					lastcon |= val << (SZCHAR*i);
# endif
# endif
				}
			} else {
				 /* stash the byte into the string */
				if (strflg) {
					if (ct==0 || i<ct)
						putbyte( val );
					else
						if( i == ct )
							werror(
				"non-null byte ignored in string initializer" );
				} else
					bycode( val, i );
			}
			++i;
			continue;
		}
		break;
	}
	/* end of string or char constant */

	if (lxmatch == '"') {
		if (strflg) {	/* end the string */
			if (ct==0 || i<ct)
				putbyte( 0 );  /* the null at the end */
		} else {	/* the initializer gets a null byte */
			bycode( 0, i++ );
			bycode( -1, i );
			dimtab[curdim] = i;  /* in case of later sizeof ... */
		}
	} else {	/* end the character constant */
		if (i == 0)
			uerror( "empty character constant" );
		if (i>(SZINT/SZCHAR) || ((pflag||hflag)&&i>1))
			uerror( "too many characters in character constant" );
	}
}

lxcom()
{
	register c;
	/* saw a /*: process a comment */

	for (;;) {
		switch (c = getchar()) {

		case EOF:
			uerror( "lxcom() unexpected EOF" );
			return;

		case '\n':
			++lineno;

		default:
			continue;

		case '*':
			if( (c = getchar()) == '/' ) return;
			else ungetchar();
			continue;

		}
	}
}

#define Return(e)	return(yylval.lineno = lineno, (e))

yylex()
{
	for(;;)
	{

		register lxchar;
		register struct lxdope *p;
		register struct symtab *sp;
		register char *cp;
		register id;

		switch( (p = lxcp[(lxchar = getchar())+1])->lxact )
		{

onechar:
			ungetc( lxchar );

		case A_1C:
			/* eat up a single character, and return an opcode */

			yylval.intval = p->lxval;
			Return( p->lxtok );

		case A_ERR:
			uerror( "illegal character: %03o (octal)", lxchar );
			break;

		case A_LET:
			/* collect an identifier, and check for reserved word */
			lxget( lxchar, LEXLET|LEXDIG );

			/* 0 means some kind of low level error, >0 reserved,
			** <0 means id
			*/
			if( (lxchar=lxres()) > 0 ) Return( lxchar );
			if( lxchar== 0 ) continue;

			if (truncate_flag )
				yytext[NCHNAM] = '\0';	/* truncate name */
			id = lookup( hash(yytext),
					/* tag name for struct/union/enum */
				(stwart&TAGNAME)? STAG:
					/* member name for struct/union */
				(stwart&(INSTRUCT|INUNION|FUNNYNAME))?SMOS:0 );
			sp = &stab[id];
			if( sp->sclass == TYPEDEF && !stwart )
			{
				stwart = instruct;
				yylval.nodep = mkty( sp->stype, sp->dimoff,
				sp->sizoff );
				Return( TYPE );
			}
			stwart = (stwart&SEENAME) ? instruct : 0;
			yylval.intval = id;
			Return( NAME );

		case A_DIG:
			/* collect a digit string, then look at last one... */
			lastcon = 0;
			lxget( lxchar, LEXDIG );
			switch( lxchar = getchar() )
			{

			case 'x':
			case 'X':
				if( yytext[0] != '0' && !yytext[1] )
					uerror( "illegal hex constant" );
				lxmore( lxchar, LEXHEX );
				/* convert the value */
				{
					for( cp = yytext+2; *cp; ++cp )
					{
						/* this code won't work for all character sets,
						** but seems ok for ascii and ebcdic
						*/
						lastcon <<= 4;
						if( isdigit( *cp ) )
							lastcon += *cp-'0';
						else if( isupper( *cp ) )
							lastcon += *cp - 'A'+ 10;
						else
							lastcon += *cp - 'a'+ 10;
					}
				}

hexlong:
				/* hex and octal constants are long if they
				** fit within 0177777
				*/
				if( lastcon & ~0177777L ) yylval.intval = 1;
				else yylval.intval = 0;

				goto islong;

			case '.':
				lxmore( lxchar, LEXDIG );

getfp:
				if( (lxchar = getchar()) == 'e' || lxchar == 'E' )
				{
					 /* exponent */
				case 'e':
				case 'E':
					if( (lxchar = getchar()) == '+' ||
					    lxchar == '-' )
					{
						*lxgcp++ = 'e';
					}
					else
					{
						ungetc(lxchar);
						lxchar = 'e';
					}
					lxmore( lxchar, LEXDIG );
					/* now have the whole thing... */
				}
				else
				{
					  /* no exponent */
					ungetc( lxchar );
				}
# ifdef NOFLOAT
				if( !flflag )
				{
					flflag = 1;
					werror( "sorry, no floating point" );
				}
				for( cp = yytext; *cp; ++cp )
				{
					if( *cp == 'e' || *cp == 'E' ||
					    *cp == '.' )
					{
						*cp = '\0';
						break;
					}
				}
				goto conv10;
# else
				flflag = 1;
				dcon = FLOATCVT(yytext);
				Return( FCON );
# endif

			default:
				ungetc( lxchar );
				if( yytext[0] == '0' )
				{
					/* convert in octal */
					for( cp = yytext+1; *cp; ++cp )
					{
						lastcon <<= 3;
						lastcon += *cp - '0';
					}
					goto hexlong;
				}
				else
				{
					/* convert in decimal */
# ifdef NOFLOAT
conv10:
# endif
					for( cp = yytext; *cp; ++cp )
					{
						lastcon = lastcon*10 + *cp - '0';
					}
				}

				/* decide if it is long or not (decimal case) */

				/* if it is positive and fits in 15 bits,
				** or negative and and fits in 15 bits
				** with an extended sign, it is int;
				** otherwise long
				*/
				/* if there is an l or L following,
				** all bets are off...
				*/

				{
					register CONSZ v;
					v = lastcon & ~077777L;
					if( v == 0 || v == ~077777L )
						yylval.intval = 0;
					else yylval.intval = 1;
				}

islong:
				/* finally, look for trailing L or l */
				if( (lxchar=getchar()) == 'L' || lxchar == 'l' )
						yylval.intval = 1;
				else ungetc( lxchar );
				Return( ICON );
			}

		case A_DOT:
			/* a dot: if followed by a digit, floating point */
			lxchar = getchar();
			if( lxmask[lxchar+1] & LEXDIG )
			{
				ungetc(lxchar);
				lxget( '.', LEXDIG );
				goto getfp;
			}
			stwart = FUNNYNAME;
			goto onechar;

		case A_STR:
			/* string constant */
			lxmatch = '"';
			Return( STRING );

		case A_CC:
			/* character constant */
			lxmatch = '\'';
			lastcon = 0;
			lxstr(0);
			yylval.intval = 0;
			Return( ICON );

		case A_SL:
			/* / */
			if( (lxchar = getchar()) != '*' ) goto onechar;
			lxcom();
		case A_WS:
			continue;

		case A_NL:
			++lineno;
			lxtitle();
			continue;

		case A_NOT:
			/* ! */
			if( (lxchar = getchar()) != '=' ) goto onechar;
			yylval.intval = NE;
			Return( EQUOP );

		case A_MI:
			/* - */
			if( (lxchar = getchar()) == '-' )
			{
				yylval.intval = DECR;
				Return( INCOP );
			}
			if( lxchar != '>' ) goto onechar;
			stwart = FUNNYNAME;
			yylval.intval=STREF;
			Return( STROP );

		case A_PL:
			/* + */
			if( (lxchar = getchar()) != '+' ) goto onechar;
			yylval.intval = INCR;
			Return( INCOP );

		case A_AND:
			/* & */
			if( (lxchar = getchar()) != '&' ) goto onechar;
			Return( yylval.intval = ANDAND );

		case A_OR:
			/* | */
			if( (lxchar = getchar()) != '|' ) goto onechar;
			Return( yylval.intval = OROR );

		case A_LT:
			/* < */
			if( (lxchar = getchar()) == '<' )
			{
				yylval.intval = LS;
				Return( SHIFTOP );
			}
			if( lxchar != '=' ) goto onechar;
			yylval.intval = LE;
			Return( RELOP );

		case A_GT:
			/* > */
			if( (lxchar = getchar()) == '>' )
			{
				yylval.intval = RS;
				Return(SHIFTOP );
			}
			if( lxchar != '=' ) goto onechar;
			yylval.intval = GE;
			Return( RELOP );

		case A_EQ:
			/* = */
			switch( lxchar = getchar() )
			{

			case '=':
				yylval.intval = EQ;
				Return( EQUOP );

			default:
				goto onechar;

			}


		default:
			cerror( "yylex error, character %03o (octal)", lxchar );

		}

		/* ordinarily, repeat here... */
		cerror( "out of switch in yylex" );

	}

}

struct lxrdope
{
	/* dope for reserved, in alphabetical order */

	char *lxrch;	/* name of reserved word */
	short lxhash;
	short lxract;	/* reserved word action */
	short lxrval;	/* value to be returned */
} lxrdope[] =
{
	"asm",		0,	AR_A,	0,
	"auto",		0,	AR_CL,	AUTO,
	"break",	0,	AR_RW,	BREAK,
	"case",		0,	AR_RW,	CASE,
	"char",		0,	AR_TY,	CHAR,
	"continue",	0,	AR_RW,	CONTINUE,
	"default",	0,	AR_RW,	DEFAULT,
	"do",		0,	AR_RW,	DO,
	"double",	0,	AR_TY,	DOUBLE,
	"else",		0,	AR_RW,	ELSE,
	"enum",		0,	AR_E,	ENUM,
	"extern",	0,	AR_CL,	EXTERN,
#ifdef ONEFLOAT
	"float",	0,	AR_TY,	DOUBLE,
#else
	"float",	0,	AR_TY,	FLOAT,
#endif
	"for",		0,	AR_RW,	FOR,
	"fortran",	0,	AR_CL,	FORTRAN,
	"goto",		0,	AR_RW,	GOTO,
	"if",		0,	AR_RW,	IF,
	"int",		0,	AR_TY,	INT,
	"long",		0,	AR_TY,	LONG,
	"register",	0,	AR_CL,	REGISTER,
	"return",	0,	AR_RW,	RETURN,
	"short",	0,	AR_TY,	SHORT,
	"sizeof",	0,	AR_RW,	SIZEOF,
	"static",	0,	AR_CL,	STATIC,
	"struct",	0,	AR_S,	0,
	"switch",	0,	AR_RW,	SWITCH,
	"typedef",	0,	AR_CL,	TYPEDEF,
	"union",	0,	AR_U,	0,
	"unsigned",	0,	AR_TY,	UNSIGNED,
	"void",		0,	AR_TY,	VOID,
	"while",	0,	AR_RW,	WHILE,
	0,		0,	0,	0,
};

#define HASH(s)	(((lxrch0[(s)[0]&037]<<4) | lxrch2[(s)[2]&037]) & 0377)

unsigned char lxrch0[040], lxrch2[040], lxrindx[0400];

lxhinit()
{
	register struct lxrdope *lp; struct lxrdope dptemp;
	register char *s; register j;
	int k0, k2;
	for (lp = lxrdope; s = lp->lxrch; ++lp) {
		++lxrch0[s[0] & 037];
		++lxrch2[s[2] & 037];
	}
	for (k0=k2=j=0; j<040; j++) {
		if (lxrch0[j]) lxrch0[j] = ++k0;
		if (lxrch2[j]) lxrch2[j] = ++k2;
	}
	for (lp = lxrdope; s = lp->lxrch; ++lp)
		lp->lxhash = HASH(s);
	do {
		j = 0;
		for (lp = lxrdope+1; lp->lxrch; ++lp)
			if (lp->lxhash < (lp-1)->lxhash) {
				dptemp = *lp;
				*lp = *(lp-1);
				*(lp-1) = dptemp;
				++j;
			}
	} while (j);
	for (k0 = 1, lp = lxrdope; s = lp->lxrch; ++lp, ++k0)
		if (lxrindx[j = lp->lxhash] == 0)
			lxrindx[j] = k0;
/*
	for (lp = lxrdope; lp->lxrch; ++lp)
		printf("%d %d %s\n", lxrindx[lp->lxhash], lp->lxhash, lp->lxrch);
*/
}

lxres()
{
	/*
	** check to see of yytext is reserved; if so,
	** do the appropriate action and return
	** otherwise, return -1
	*/
	register c;
	register struct lxrdope *p;

	if (yytext[1] == 0) return -1;

	if ((c = HASH(yytext)) == 0 || (c = lxrindx[c]) == 0) return -1;

	p = lxrdope + c - 1;
	do if (strcmp(yytext, p->lxrch) == 0) switch (p->lxract) {

	case AR_TY:	/* type word */
		stwart = instruct;
		yylval.nodep = mkty( (TWORD)p->lxrval, 0, p->lxrval );
		if (p->lxrval==FLOAT || p->lxrval==DOUBLE) {
# ifdef NOFLOAT
			if (!flflag)
				werror( "sorry, no floating point" );
			yylval.nodep->tn.type = LONG;
# endif
			flflag = 1;
		}
		return( TYPE );

	case AR_RW:	/* ordinary reserved word */
		return( yylval.intval = p->lxrval );

	case AR_CL:	/* class word */
		yylval.intval = p->lxrval;
		return( CLASS );

	case AR_S:	/* struct */
		stwart = INSTRUCT|SEENAME|TAGNAME;
		yylval.intval = INSTRUCT;
		return( STRUCT );

	case AR_U:	/* union */
		stwart = INUNION|SEENAME|TAGNAME;
		yylval.intval = INUNION;
		return( STRUCT );

	case AR_E:	/* enums */
		stwart = SEENAME|TAGNAME;
		return( yylval.intval = ENUM );

	case AR_A:	/* asm */
		asm_esc = 1; /* warn the world! */
		lxget(' ', LEXWS);
		if (getchar() != '(') goto badasm;
		lxget(' ', LEXWS);
		if (getchar() != '"') goto badasm;
		asmp = asmbuf;
		while ((c = getchar()) != '"') {
			if (c=='\n' || c==EOF) goto badasm;
			*asmp++ = c;
			if (asmp >= &asmbuf[ASMBUF-1])
				uerror( "asm > %d chars", ASMBUF);
		}
		lxget(' ', LEXWS);
		if( getchar() != ')' ) goto badasm;
		*asmp++ = '\0';
		return( ASM );
badasm:
		uerror( "bad asm construction" );
		return( 0 );

	default:
		cerror("bad AR_?? action");
	} while ((++p)->lxhash == c);
	return -1;
}

lxtitle()
{
	/* called after a newline; set linenumber and file name */

	register c, val; register char *cp;

	/*for(;;)*/ {	/* might be several such lines in a row */
			/* but we really want the very first one */
		if ((c = getchar()) != '#') {
			if (c != EOF) ungetchar();
			return;
		}
		lxget( ' ', LEXWS);
		val = 0;
		for (c = getchar(); isdigit(c); c = getchar())
			val = val*10+ c - '0';
		ungetchar();
		lineno = val-1;
		lxget(' ', LEXWS);
		if ((c = getchar()) != '\n') {
			cp = ftitle; *cp++ = c;
			while ((c=getchar()) != '\n')
				*cp++ = c;
			*cp = '\0';
			if (c != EOF) ungetchar();
		}
	}
}

# ifndef MYASMOUT
asmout()
{
#ifdef GDEBUG
	dbline();
#endif
	printx("%s\n%s\n%s\n", ASM_COMMENT, asmbuf, ASM_END);
}
# endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.