#ifndef lint
static char rcsid[] = "$Header:asscan1.c 12.0$";
#endif
/* $Source: /ibm/acis/usr/src/bin/as_ca/RCS/asscan1.c,v $ */
/*
 *	Copyright (c) 1982 Regents of the University of California
 */
#ifndef lint
static char sccsid[] = "@(#)asscan1.c 4.6 7/6/83";
#endif not lint

#include "asscanl.h"

inittokfile()
{
	if (passno == 1){
		if (useVM){
			bufstart = &tokbuf[0];
			buftail = &tokbuf[1];
			bufstart->tok_next = buftail;
			buftail->tok_next = 0;
		}
		tokbuf[0].tok_count = -1;
		tokbuf[1].tok_count = -1;
	}
	tok_temp = 0;
	tok_free = 0;
	bufno = 0;
	emptybuf = &tokbuf[bufno];
	tokptr = 0;
	tokub = 0;
}

closetokfile()
{
	if (passno == 1){
		if (useVM){
			emptybuf->toks[emptybuf->tok_count++] = PARSEEOF;
		} else {
			/*
			 *	Clean up the buffers that haven't been
			 *	written out yet
			 */
			if (tokbuf[bufno ^ 1].tok_count >= 0){
				if (writeTEST((char *)&tokbuf[bufno ^ 1], sizeof *emptybuf, 1, tokfile)){
				  badwrite:
					yyerror("Unexpected end of file writing the interpass tmp file");
				exit(2);
				}
			}
			/*
			 *	Ensure that we will read an End of file,
			 *	if there are more than one file names
			 *	in the argument list
			 */
			tokbuf[bufno].toks[tokbuf[bufno].tok_count++] = PARSEEOF;
			if (writeTEST((char *)&tokbuf[bufno], sizeof *emptybuf, 1, tokfile))
				goto badwrite;
		}
	}	/*end of being pass 1*/
}

inttoktype yylex()
{
	register	ptrall	bufptr;	
	register	inttoktype		val;	
	register	struct	exp	*locxp;
	/*
	 *	No local variables to be allocated; this saves
	 *	one piddling instruction..
	 */
	static	int	Lastjxxx;

	bufptr = tokptr;		/*copy in the global value*/
   top:
	if (bufptr < tokub){
		gtoken(val, bufptr);
		switch(yylval = val){
		case	PARSEEOF:
				yylval = val = PARSEEOF;
				break;
		case	BFINT:
		case	INT:
				if (xp >= &explist[NEXP])
				     yyerror("Too many expressions; try simplyfing");
				else
				    locxp = xp++;
				locxp->e_number = Znumber;
				locxp->e_number.num_tag = TYPL;
				glong(locxp->e_xvalue, bufptr);
			  makevalue:
				locxp->e_xtype = XABS;
				locxp->e_xloc = 0;
				locxp->e_xname = NULL;
				yylval = (int)locxp;
				break;
		case	BIGNUM:	
				if (xp >= &explist[NEXP])
				     yyerror("Too many expressions; try simplyfing");
				else
				    locxp = xp++;
				gnumber(locxp->e_number, bufptr);
				goto makevalue;
		case	NAME:
				gptr(yylval, bufptr);
				lastnam = (struct symtab *)yylval;
				break;
		case	SIZESPEC:
		case 	REG:
				gchar(yylval, bufptr);
				break;
		case	ISPEC:
		case	INSTn:
		case	INST0:
				gopcode(yyopcode, bufptr);
				break;
		case	IJXXX:
				gopcode(yyopcode, bufptr);
				/* We can't cast Lastjxxx into (int *) here.. */
				gptr(Lastjxxx, bufptr);
				lastjxxx = (struct symtab *)Lastjxxx;
				break;
		case	ILINESKIP:
				gint(yylval, bufptr);
				lineno += yylval;
				goto top;
		case	SKIP:	
				eatskiplg(bufptr);
				goto top;
		case	VOID:	
				goto top;
		case 	STRING:
		case 	ISTAB:
		case	ISTABSTR:
		case	ISTABNONE:
		case	ISTABDOT:
		case	ILTORG:		
		case	IALIGN:
		case	IORG:
				gptr(yylval, bufptr);
				break;
		} 
#ifdef DEBUG
		if (toktrace){
		char	*tok_to_name();
		printf("P: %d T#: %4d, %s ",
			passno, bufptr -  firsttoken, tok_to_name(val));
		switch(val){
		case 	INT:	printf("val %d",
					((struct exp *)yylval)->e_xvalue);
				break;
		case	BFINT:	printf("val %d",
					((struct exp *)yylval)->e_xvalue);
				break;
		case 	BIGNUM: bignumprint(((struct exp*)yylval)->e_number);
				break;
		case	NAME:	printf("\"%.8s\"",
					FETCHNAME((struct symtab *)yylval));
				break;
		case	REG:	printf(" r%d",
					yylval);
				break;
		case	ISPEC:
		case	IJXXX:
		case	INST0:	
		case	INSTn:	if (ITABCHECK(yyopcode))
					printf("%.8s",
						FETCHNAME(ITABFETCH(yyopcode)));
				else
					printf("ISPEC or IJXXX or INST0 or INSTn can't get into the itab\n");
				break;
		case	STRING:
			printf("length %d, seekoffset %d, place 0%o ",
				((struct strdesc *)yylval)->sd_strlen,
				((struct strdesc *)yylval)->sd_stroff,
				((struct strdesc *)yylval)->sd_place
				);
			if (((struct strdesc *)yylval)->sd_place & STR_CORE)
				printf("value\"%*s\"",
					((struct strdesc *)yylval)->sd_strlen,
					((struct strdesc *)yylval)->sd_string);
			break;
		}  		/*end of the debug switch*/
		printf("\n");
		}
#endif DEBUG

	} else {	/* start a new buffer */
	    if (useVM){
		if (passno == 2){
			tok_temp = emptybuf->tok_next;
			emptybuf->tok_next = tok_free;
			tok_free = emptybuf;
			emptybuf = tok_temp;
		} else {
			emptybuf = emptybuf->tok_next;
		}
		bufno += 1;
		if (emptybuf == 0){
			struct	tokbufdesc *newdallop;
			int	i;
			if (passno == 2)
				goto badread;
			emptybuf = newdallop = (struct tokbufdesc *)
			  Calloc(TOKDALLOP, sizeof (struct tokbufdesc));
			for (i=0; i < TOKDALLOP; i++){
				buftail->tok_next = newdallop;
				buftail = newdallop;
				newdallop += 1;
			}
			buftail->tok_next = 0;
		}	/*end of need to get more buffers*/
		bufptr = (ptrall)&(emptybuf->toks[0]);
		if (passno == 1)
			scan_dot_s(emptybuf);
	    } else {	/*don't use VM*/
		bufno ^= 1;
		emptybuf = &tokbuf[bufno];
		bufptr = (ptrall)&(emptybuf->toks[0]);
		if (passno == 1){
			/*
			 *	First check if there are things to write
			 *	out at all
			 */
			if (emptybuf->tok_count >= 0){
			    if (writeTEST((char *)emptybuf, sizeof *emptybuf, 1, tokfile)){
				yyerror("Unexpected end of file writing the interpass tmp file");
				exit(2);
			    }
			}
			scan_dot_s(emptybuf);
		} else {	/*pass 2*/
		    if (readTEST((char *)emptybuf, sizeof *emptybuf, 1, tokfile)){
			 badread:
			     yyerror("Unexpected end of file while reading the interpass tmp file");
			     exit(1);
		    }
		}
	    }	/*end of using a real live file*/
	    tokub = bufptr + emptybuf->tok_count;
#ifdef DEBUG
	    firsttoken = bufptr;
	    if (debug)
		printf("created buffernumber %d with %d tokens\n",
			bufno, emptybuf->tok_count);
#endif DEBUG
	    goto top;
	}	/*end of reading/creating a new buffer*/
	tokptr = bufptr;		/*copy back the global value*/
	return(val);
}	/*end of yylex*/


buildskip(from, to)
	register	ptrall	from, to;
{
	int	diff;
	register	struct	tokbufdesc *middlebuf;
	/*
	 *	check if from and to are in the same buffer
	 *	from and to DIFFER BY AT MOST 1 buffer and to is
	 *	always ahead of from, with to being in the buffer emptybuf
	 *	points to.
	 *	The hard part here is accounting for the case where the
	 *	skip is to cross a buffer boundary; we must construct
	 *	two skips.
	 *
	 *	Figure out where the buffer boundary between from and to is
	 *	It's easy in VM, as buffers increase to high memory, but
	 *	w/o VM, we alternate between two buffers, and want
	 *	to look at the exact middle of the contiguous buffer region.
	 */
	middlebuf = useVM ? emptybuf : &tokbuf[1];
	if (  ( (bytetoktype *)from > (bytetoktype *)middlebuf)
	    ^ ( (bytetoktype *)to > (bytetoktype *)middlebuf)
	   ){	/*split across a buffer boundary*/
		ptoken(from, SKIP);
		/*
		 *	Set the skip so it lands someplace beyond
		 *	the end of this buffer.
		 *	When we pull this skip out in the second pass,
		 *	we will temporarily move the current pointer
		 *	out beyond the end of the buffer, but immediately
		 *	do a compare and fail the compare, and then reset
		 *	all the pointers correctly to point into the next buffer.
		 */
		bskiplg(from,  MAX_SKIPLG );
		/*
		 *	Now, force from to be in the same buffer as to
		 */
		from = (ptrall)&(emptybuf->toks[0]);
	}
	/*
	 *	Now, to and from are in the same buffer
	 */
	if (from > to)
		yyerror("Internal error: bad skip construction");
	else {
		if ( (diff = (bytetoktype *)to - (bytetoktype *)from) >= 
			(sizeof(bytetoktype) + sizeof(lgtype) + 1)) {
				ptoken(from, SKIP);
				bskipfromto(from, to);
		} else {
			for ( ; diff > 0; --diff)
				ptoken(from, VOID);
		}
	}
}

movestr(to, from, lg)
	char	*to;	/* 4(ap) */ 
	char	*from;	/* 8(ap) */
	int	lg;	/* 12(ap) */
{
	if (lg <= 0)
		return;
#ifdef vax
	;
	asm("movc3	12(ap),*8(ap),*4(ap)");
	;
#else
	bcopy (from, to, lg);
#endif
}

new_dot_s(namep)
	char	*namep;
{
	newfflag = 1;
	newfname = namep;
	dotsname = namep;
	lineno = 1;
	scanlineno = 1;
}

min(a, b)
{
	return(a < b ? a : b);
}
