READ.ME                                                                                                444      26      12         7010  3227667731   5027                                                                                                                                                                                                                                                                                                                                                                      Directory setup:
  c86:		C-compiler source
  a86:		assembler, loader, and .com file builder
  lib86:	C run-time library and include directory

You should install the following files into some directory on your
search path (on our system we use /usr/local):

	cc86		; shell script implements "cc" but for 8086/8088
	a86/a86		; the assembler
	a86/ld86	; the loader
	a86/cvt86	; .ld output to .com file conversion
	c86/c86		; the C compiler (8087 version)
	c86/nc86	; the C compiler (non-8087 version)

Regular 4.1BSD programs used:

	ar		; used for preparing loader libraries
	/lib/cpp	; C preprocessor

The cc86 script expects to find the include directory, libc.a and crt files in
/src/Machines/8086/lib86 -- if you don't put them there, you'll
have to update the value of the LIB variable in cc86.

cc86 is a shell script that implements a cc command similar to the
regular UNIX cc.  It's options are:

  -8087		use the 8087 version of the compiler and run-time
		library.  By default, the non-8087 versions are used.

  -P		run only the C preprocessor (cpp) and leave the result
		in foo.i, where foo.c was the input file.

  -S		do not run the assembler, leaving the assembly language
		output file in foo.a86, where foo.c was the input file.

  -c		compile, assemble, but do not create a .com file, leaving
		binary file in foo.b, where foo.c was the input file.

		If this option is not specified, "a.com" is created from
		the specified files (uses crt0.b and libc.a to create a program
		that will emulate the Unix environment -- to the extent
		possible -- under MSDOS).  "a.ld" is also created; it is a
		Berkeley-format load module from which a symbol table can be
		extracted using nm.

  -o name	changes the name of the generated .com file to "name.com"

  -Ilib		specifies a directory to be searched when processing #include
		statements during preprocessor stage.

  -Dsymbol	Defines "symbol" to have the value 1 during preprocessing.
		By default, the symbols "ibm" and "IBMDOS" are defined.

  -Usymbol	Undefines "symbol" during preprocessing.

Source files with .c suffixes are assumed to be C source files and are
processed by the compiler, source files with .a86 suffixes are assumed to
be assembly language source files and are fed to the assembler.

The compiler produces assembly language output suitable for a86 (but
it's not compatible with IBM/Microsoft assembly language).
It is a 16-bit compiler; output code does not touch the segment
regs, so it is possible to have separate instruction and data
segments (see lib86/csu/crt0.a86 for the start up routine we use
on our IBM Personal computer to set up the segment regs, etc. from
info in the .com file).  The code does use ES, which it assumes
is set to the same value as the DS register.

The floating-point version of the compiler produces code that uses
the 8087; the code is serviceable but not the most efficient, support
for "floats" (32-bit floating-point quantities) may be a little shaky.
The non-8087 version of the compiler does not support floating-point
at all, ie, if you don't have an 8087, you can't do floating-point
(hopefully, this will get fixed in the future...).

Although the assembler produces ".b" files, they have exactly the
same format as ".o" files under 4.1BSD -- things like nm and size will
work, and, most importantly, ld.  Using ld with the -N, -X and -r
options (see cc86 for an example) will produce a file that cvt86 can
convert into an IBM DOS format .com file for the IBM Personal Computer.
The ld86 program is a slightly modified version of the Berkeley loader
for the VAX.

7, you can't do floating-point
(hopefully, this will get fixed in the future...).

Although the assembler produces ".b" files, they have exactly the
same format as ".o" files under 4.1BSD -- things like nm and size will
work, and, most importantly, ld.  Using ld with the -N, -X and -r
options (see cc86 for an example) will produce a file that cvt86 can
convert into an IBM DOS format .com file for the IBM Personal Computer.
The ld86 program is a slightly modified version of the Berkeley loader
for thcc86                                                                                                   555      26      12         2317  3227670176   4564                                                                                                                                                                                                                                                                                                                                                                      o=a.com P= Q= S= C= O="-DIBMDOS -Uvax -Dibm"
CC=nc86 LIBC=nlibc.a
LIB=/src/Machines/8086/lib86
X= Y=crt0.b Z=
trap "rm -f $T.i $T.a86; exit 1" 1 2 15

for A in $*
do
	if test $o
	then
	case $A in
	-8087)	CC=c86 LIBC=libc.a ;;
	-P)	P=XXX; set O="$O -P" ;;
	-S)	S=XXX ;;
	-O)	Q=XXX ;;
	-c)	C=XXX ;;
	-p)	X="-Xp" Y=mcrt0.b ;;
	-o)	o= ;;
	-[IDU]*)        O="$O $A" ;;
	-*)     echo >&2 "bad cc86 option: $A"; exit 1;;
	*.b)	Z="$Z $A" ;;
	*.a86)	T=`basename $A .a86`
		a86 $T
		Z="$Z $T.b";;
	*.c)	T=`basename $A .c`
		if /lib/cpp -I$LIB/include $O $A >$T.i
		then	if test $P
			then :
			else	if $CC $X <$T.i >$T.a86
				then	if test $Q
					then	mv $T.a86 $T.o
						o86 <$T.o >$T.a86
						rm -f $T.o
					fi
					if test $S
					then :
					else	a86 $T; rm -f $T.a86
					 	Z="$Z $T.b"
					fi
				else rm -f $T.a86
				fi
				rm -f $T.i
			fi
		else	rm -f $T.i
		fi;;
	*)	echo >&2 "bad cc86 argument: $A"; rm -f $T.i $T.a86; exit 1
	esac
	else o=$A.com
	fi
done

if test $o
then	:
else	echo >&2 "cc86: filename expected following -o"
	exit 1
fi

if test x$C != x -o x$S != x -o x$P != x
then	:
else	oo=`basename $o .com`.ld
	if ld86 -X -N -r -o $oo $LIB/$Y $Z $LIB/$LIBC &&\
	   cvt86 $oo $o
	then :
	else rm -f $oo; exit 1
	fi
fi
 $S
					then :
					else	a86 $T; rm -f $T.a86
					 	Z="$Z $T.b"
					fi
				else rm -f $T.a86
				fi
				rm -f $T.i
			fi
		else	rm -f $T.i
		fi;;
	*)	echo >&2 "bad cc86 argument: $A"; rm -f $T.i $T.a86; exit 1
	esac
	else o=$A.com
	fi
done

if test $o
then	:
else	echo >&2 "cc86: filename expected follc86/Makefile                                                                                           644      26      12         1256  3061503772   6127                                                                                                                                                                                                                                                                                                                                                                      CFLAGS=-O

OBJ0 = trees.o optim.o pftn.o code.o local.o scan.o xdefs.o cgram.o
OBJ1 = reader.o order.o match.o allo.o

c86:	$(OBJ0) $(OBJ1) comm1.o local2.o table.o
	cc -o c86 $(OBJ0) $(OBJ1) comm1.o local2.o table.o

local2.o: local2.c
	cc -c -O -DX8087 local2.c

table.o: table.c
	cc -c -O -DX8087 table.c

nc86:	$(OBJ0) $(OBJ1) comm1.o nlocal2.o ntable.o
	cc -o nc86 $(OBJ0) $(OBJ1) comm1.o nlocal2.o ntable.o

nlocal2.o: local2.c
	cc -c -O local2.c
	mv local2.o nlocal2.o

ntable.o: table.c
	cc -c -O table.c
	mv table.o ntable.o

comm1.o: manifest mfile1 common macdefs
$(OBJ0): manifest macdefs mfile1
$(OBJ1) local2.o nlocal2.o table.o ntable.o: manifest mfile2 mac2defs macdefs
6 $(OBJ0) $(OBJ1) comm1.o local2.o table.o

local2.o: local2.c
	cc -c -O -DX8087 local2.c

table.o: table.c
	cc -c -O -DX8087 table.c

nc86:	$(OBJ0) $(OBJ1) comm1.o nlocal2.o ntable.o
	cc -o nc86 $(OBJ0) $(OBJ1) comm1.o nlocal2.o ntable.o

nlocal2.o: local2.c
	cc -c -O local2.c
	mv local2.o nlocal2.o

ntable.o: table.c
	cc -c -O table.cc86/allo.c                                                                                             444      26      12        23156  2672745545   5620                                                                                                                                                                                                                                                                                                                                                                      # include "mfile2"

NODE resc[3];

int busy[REGSZ];

int maxa, mina, maxb, minb;

allo0(){ /* free everything */

	register i;

	maxa = maxb = -1;
	mina = minb = 0;

	REGLOOP(i){
		busy[i] = 0;
		if( rstatus[i] & STAREG ){
			if( maxa<0 ) mina = i;
			maxa = i;
			}
		if( rstatus[i] & STBREG ){
			if( maxb<0 ) minb = i;
			maxb = i;
			}
		}
	}

# define TBUSY 01000

allo( p, q ) NODE *p; struct optab *q; {

	register n, i, j;

	n = q->needs;
	i = 0;

	while( n & NACOUNT ){
		resc[i].in.op = REG;
		resc[i].tn.rval = freereg( p, n&NAMASK );
		resc[i].tn.lval = 0;
		resc[i].in.name[0] = '\0';
		n -= NAREG;
		++i;
		}

	while( n & NBCOUNT ){
		resc[i].in.op = REG;
		resc[i].tn.rval = freereg( p, n&NBMASK );
		resc[i].tn.lval = 0;
		resc[i].in.name[0] = '\0';
		n -= NBREG;
		++i;
		}

	if( n & NTMASK ){
		resc[i].in.op = OREG;
		resc[i].tn.rval = TMPREG;
		if( p->in.op == STCALL || p->in.op == STARG || p->in.op == UNARY STCALL || p->in.op == STASG ){
			resc[i].tn.lval = freetemp( (SZCHAR*p->stn.stsize + (SZINT-1))/SZINT );
			}
		else {
			resc[i].tn.lval = freetemp( (n&NTMASK)/NTEMP );
			}
		resc[i].in.name[0] = '\0';
		resc[i].tn.lval = BITOOR(resc[i].tn.lval);
		++i;
		}

	/* turn off "temporarily busy" bit */

	REGLOOP(j){
		busy[j] &= ~TBUSY;
		}

	for( j=0; j<i; ++j ) if( resc[j].tn.rval < 0 ) return(0);
	return(1);

	}

freetemp( k ){ /* allocate k integers worth of temp space */
	/* we also make the convention that, if the number of words is more than 1,
	/* it must be aligned for storing doubles... */

# ifndef BACKTEMP
	int t;

	if( k>1 ){
		SETOFF( tmpoff, ALDOUBLE );
		}

	t = tmpoff;
	tmpoff += k*SZINT;
	if( tmpoff > maxoff ) maxoff = tmpoff;
	if( tmpoff-baseoff > maxtemp ) maxtemp = tmpoff-baseoff;
	return(t);

# else
	tmpoff += k*SZINT;
	if( k>1 ) {
		SETOFF( tmpoff, ALDOUBLE );
		}
	if( tmpoff > maxoff ) maxoff = tmpoff;
	if( tmpoff-baseoff > maxtemp ) maxtemp = tmpoff-baseoff;
	return( -tmpoff );
# endif
	}

freereg( p, n ) NODE *p; {
	/* allocate a register of type n */
	/* p gives the type, if floating */

	register j;

	/* not general; means that only one register (the result) OK for call */
	if( callop(p->in.op) ){
		j = callreg(p);
		if( usable( p, n, j ) ) return( j );
		/* have allocated callreg first */
		}
	j = p->in.rall & ~MUSTDO;
	if( j!=NOPREF && usable(p,n,j) ){ /* needed and not allocated */
		return( j );
		}
	if( n&NAMASK ){
		for( j=mina; j<=maxa; ++j ) if( rstatus[j]&STAREG ){
			if( usable(p,n,j) ){
				return( j );
				}
			}
		}
	else if( n &NBMASK ){
		for( j=minb; j<=maxb; ++j ) if( rstatus[j]&STBREG ){
			if( usable(p,n,j) ){
				return(j);
				}
			}
		}

	return( -1 );
	}

usable( p, n, r ) NODE *p; {
	/* decide if register r is usable in tree p to satisfy need n */

	/* checks, for the moment */
	if( !istreg(r) ) cerror( "usable asked about nontemp register" );

	if( busy[r] > 1 ) return(0);

	if( (n & NBMASK) && !isbreg(r)) return(0);
/*	if( isbreg(r) ){
		if( n&NAMASK ) return(0);
		}
	else {
		if( n & NBMASK ) return(0);
		}
*/
	if( (n&NAMASK) && (szty(p->in.type) == 2) ){ /* only do the pairing for real regs */
		if( r&01 ) return(0);
		if( !istreg(r+1) ) return( 0 );
		if( busy[r+1] > 1 ) return( 0 );
		if( busy[r] == 0 && busy[r+1] == 0  ||
		    busy[r+1] == 0 && shareit( p, r, n ) ||
		    busy[r] == 0 && shareit( p, r+1, n ) ){
			busy[r] |= TBUSY;
			busy[r+1] |= TBUSY;
			return(1);
			}
		else return(0);
		}
	if( busy[r] == 0 ) {
		busy[r] |= TBUSY;
		return(1);
		}

	/* busy[r] is 1: is there chance for sharing */
	return( shareit( p, r, n ) );

	}

shareit( p, r, n ) NODE *p; {
	/* can we make register r available by sharing from p
	   given that the need is n */
	if( (n&(NASL|NBSL)) && ushare( p, 'L', r ) ) return(1);
	if( (n&(NASR|NBSR)) && ushare( p, 'R', r ) ) return(1);
	return(0);
	}

ushare( p, f, r ) NODE *p; {
	/* can we find a register r to share on the left or right
		(as f=='L' or 'R', respectively) of p */
	p = getlr( p, f );
	if( p->in.op == UNARY MUL ) p = p->in.left;
	if( p->in.op == OREG ){
		if( R2TEST(p->tn.rval) ){
			return( r==R2UPK1(p->tn.rval) || r==R2UPK2(p->tn.rval) );
			}
		else return( r == p->tn.rval );
		}
	if( p->in.op == REG ){
		return( r == p->tn.rval || ( szty(p->in.type) == 2 && r==p->tn.rval+1 ) );
		}
	return(0);
	}

recl2( p ) register NODE *p; {
	register r = p->tn.rval;
	if( p->in.op == REG ) rfree( r, p->in.type );
	else if( p->in.op == OREG ) {
		if( R2TEST( r ) ) {
			rfree( R2UPK1( r ), PTR+INT );
			rfree( R2UPK2( r ), INT );
			}
		else {
			rfree( r, PTR+INT );
			}
		}
	}

int rdebug = 0;

rfree( r, t ) TWORD t; {
	/* mark register r free, if it is legal to do so */
	/* t is the type */

	if( rdebug ){
		printf( "rfree( %s ), size %d\n", rnames[r], szty(t) );
		}

	if( istreg(r) ){
		if( --busy[r] < 0 ) cerror( "register overfreed");
		if( szty(t) == 2 ){
			if( (r&01) || (istreg(r)^istreg(r+1)) ) cerror( "illegal free" );
			if( --busy[r+1] < 0 ) cerror( "register overfreed" );
			}
		}
	}

rbusy(r,t) TWORD t; {
	/* mark register r busy */
	/* t is the type */

	if( rdebug ){
		printf( "rbusy( %s ), size %d\n", rnames[r], szty(t) );
		}

	if( istreg(r) ) ++busy[r];
	if( szty(t) == 2 ){
		if( istreg(r+1) ) ++busy[r+1];
		if( (r&01) || (istreg(r)^istreg(r+1)) ) cerror( "illegal register pair freed" );
		}
	}

rwprint( rw ){ /* print rewriting rule */
	register i, flag;
	static char * rwnames[] = {

		"RLEFT",
		"RRIGHT",
		"RESC1",
		"RESC2",
		"RESC3",
		0,
		};

	if( rw == RNULL ){
		printf( "RNULL" );
		return;
		}

	if( rw == RNOP ){
		printf( "RNOP" );
		return;
		}

	flag = 0;
	for( i=0; rwnames[i]; ++i ){
		if( rw & (1<<i) ){
			if( flag ) printf( "|" );
			++flag;
			printf( rwnames[i] );
			}
		}
	}

reclaim( p, rw, cookie ) NODE *p; {
	register NODE **qq;
	register NODE *q;
	register i;
	NODE *recres[5];
	struct respref *r;

	/* get back stuff */

	if( rdebug ){
		printf( "reclaim( %o, ", p );
		rwprint( rw );
		printf( ", " );
		prcook( cookie );
		printf( " )\n" );
		}

	if( rw == RNOP || ( p->in.op==FREE && rw==RNULL ) ) return;  /* do nothing */

	walkf( p, recl2 );

	if( callop(p->in.op) ){
		/* check that all scratch regs are free */
		callchk(p);  /* ordinarily, this is the same as allchk() */
		}

	if( rw == RNULL || (cookie&FOREFF) ){ /* totally clobber, leaving nothing */
		tfree(p);
		return;
		}

	/* handle condition codes specially */

	if( (cookie & FORCC) && (rw&RESCC)) {
		/* result is CC register */
		tfree(p);
		p->in.op = CCODES;
		p->tn.lval = 0;
		p->tn.rval = 0;
		return;
		}

	/* locate results */

	qq = recres;

	if( rw&RLEFT) *qq++ = getlr( p, 'L' );;
	if( rw&RRIGHT ) *qq++ = getlr( p, 'R' );
	if( rw&RESC1 ) *qq++ = &resc[0];
	if( rw&RESC2 ) *qq++ = &resc[1];
	if( rw&RESC3 ) *qq++ = &resc[2];

	if( qq == recres ){
		cerror( "illegal reclaim");
		}

	*qq = NIL;

	/* now, select the best result, based on the cookie */

	for( r=respref; r->cform; ++r ){
		if( cookie & r->cform ){
			for( qq=recres; (q= *qq) != NIL; ++qq ){
				if( tshape( q, r->mform ) ) goto gotit;
				}
			}
		}

	/* we can't do it; die */
	cerror( "cannot reclaim");

	gotit:

	if( p->in.op == STARG ) p = p->in.left;  /* STARGs are still STARGS */

	q->in.type = p->in.type;  /* to make multi-register allocations work */
		/* maybe there is a better way! */
	q = tcopy(q);

	tfree(p);

	p->in.op = q->in.op;
	p->tn.lval = q->tn.lval;
	p->tn.rval = q->tn.rval;
	for( i=0; i<NCHNAM; ++i )
		p->in.name[i] = q->in.name[i];

	q->in.op = FREE;

	/* if the thing is in a register, adjust the type */

	switch( p->in.op ){

	case REG:
		if( !rtyflg ){
			/* the C language requires intermediate results to change type */
			/* this is inefficient or impossible on some machines */
			/* the "T" command in match supresses this type changing */
			if( p->in.type == CHAR || p->in.type == SHORT ) p->in.type = INT;
			else if( p->in.type == UCHAR || p->in.type == USHORT ) p->in.type = UNSIGNED;
			else if( p->in.type == FLOAT ) p->in.type = DOUBLE;
			}
		if( ! (p->in.rall & MUSTDO ) ) return;  /* unless necessary, ignore it */
		i = p->in.rall & ~MUSTDO;
		if( i & NOPREF ) return;
		if( i != p->tn.rval ){
			if( busy[i] || ( szty(p->in.type)==2 && busy[i+1] ) ){
				cerror( "faulty register move" );
				}
			rbusy( i, p->in.type );
			rfree( p->tn.rval, p->in.type );
			rmove( i, p->tn.rval, p->in.type );
			p->tn.rval = i;
			}

	case OREG:
		if( R2TEST(p->tn.rval) ){
			int r1, r2;
			r1 = R2UPK1(p->tn.rval);
			r2 = R2UPK2(p->tn.rval);
			if( (busy[r1]>1 && istreg(r1)) || (busy[r2]>1 && istreg(r2)) ){
				cerror( "potential register overwrite" );
				}
			}
		else if( (busy[p->tn.rval]>1) && istreg(p->tn.rval) ) cerror( "potential register overwrite");
		}

	}

ncopy( q, p ) NODE *p, *q; {
	/* copy the contents of p into q, without any feeling for
	   the contents */
	/* this code assume that copying rval and lval does the job;
	   in general, it might be necessary to special case the
	   operator types */
	register i;

	q->in.op = p->in.op;
	q->in.rall = p->in.rall;
	q->in.type = p->in.type;
	q->tn.lval = p->tn.lval;
	q->tn.rval = p->tn.rval;
	for( i=0; i<NCHNAM; ++i ) q->in.name[i]  = p->in.name[i];

	}

NODE *
tcopy( p ) register NODE *p; {
	/* make a fresh copy of p */

	register NODE *q;
	register r;

	ncopy( q=talloc(), p );

	r = p->tn.rval;
	if( p->in.op == REG ) rbusy( r, p->in.type );
	else if( p->in.op == OREG ) {
		if( R2TEST(r) ){
			rbusy( R2UPK1(r), PTR+INT );
			rbusy( R2UPK2(r), INT );
			}
		else {
			rbusy( r, PTR+INT );
			}
		}

	switch( optype(q->in.op) ){

	case BITYPE:
		q->in.right = tcopy(p->in.right);
	case UTYPE:
		q->in.left = tcopy(p->in.left);
		}

	return(q);
	}

allchk(){
	/* check to ensure that all register are free */

	register i;

	REGLOOP(i){
		if( istreg(i) && busy[i] ){
			cerror( "register allocation error");
			}
		}

	}
 == REG ) rbusy( r, p->in.type );
	else if( p->in.op == OREG ) {
		if( R2TEST(r) ){
			rbusy( R2UPK1(r), PTR+INT );
			rbusy( R2UPK2(r), INT );
			}
		else {
			rbusy( r, PTR+INT );
			}
		}

	switch( optype(q->in.op) ){

	case BITYPE:
		q->in.right = tcopy(p->in.right);
	case UTYPE:
		q->in.left = tcopy(p->in.left);
		}

	return(q);
	}

allchk(){
	/* check to ensure that all register are free */

	c86/cgram.c                                                                                            666      26      12       114101  3227133601   5754                                                                                                                                                                                                                                                                                                                                                                      # define NAME 2
# define STRING 3
# define ICON 4
# define FCON 5
# define PLUS 6
# define MINUS 8
# define MUL 11
# define AND 14
# define OR 17
# define ER 19
# define QUEST 21
# define COLON 22
# define ANDAND 23
# define OROR 24
# define ASOP 25
# define RELOP 26
# define EQUOP 27
# define DIVOP 28
# define SHIFTOP 29
# define INCOP 30
# define UNOP 31
# define STROP 32
# define TYPE 33
# define CLASS 34
# define STRUCT 35
# define RETURN 36
# define GOTO 37
# define IF 38
# define ELSE 39
# define SWITCH 40
# define BREAK 41
# define CONTINUE 42
# define WHILE 43
# define DO 44
# define FOR 45
# define DEFAULT 46
# define CASE 47
# define SIZEOF 48
# define ENUM 49
# define LP 50
# define RP 51
# define LC 52
# define RC 53
# define LB 54
# define RB 55
# define CM 56
# define SM 57
# define ASSIGN 58

# line 108 "cgram.y"
# include "mfile1"
#define yyclearin yychar = -1
#define yyerrok yyerrflag = 0
extern int yychar;
extern short yyerrflag;
#ifndef YYMAXDEPTH
#define YYMAXDEPTH 150
#endif
YYSTYPE yylval, yyval;

# line 127 "cgram.y"
	static int fake = 0;
	static char fakename[NCHNAM+1];
# define YYERRCODE 256

# line 794 "cgram.y"


NODE *
mkty( t, d, s ) unsigned t; {
	return( block( TYPE, NIL, NIL, t, d, s ) );
	}

NODE *
bdty( op, p, v ) NODE *p; {
	register NODE *q;

	q = block( op, p, NIL, INT, 0, INT );

	switch( op ){

	case UNARY MUL:
	case UNARY CALL:
		break;

	case LB:
		q->in.right = bcon(v);
		break;

	case NAME:
		q->tn.rval = v;
		break;

	default:
		cerror( "bad bdty" );
		}

	return( q );
	}

dstash( n ){ /* put n into the dimension table */
	if( curdim >= DIMTABSZ-1 ){
		cerror( "dimension table overflow");
		}
	dimtab[ curdim++ ] = n;
	}

savebc() {
	if( psavbc > & asavbc[BCSZ-4 ] ){
		cerror( "whiles, fors, etc. too deeply nested");
		}
	*psavbc++ = brklab;
	*psavbc++ = contlab;
	*psavbc++ = flostat;
	*psavbc++ = swx;
	flostat = 0;
	}

resetbc(mask){

	swx = *--psavbc;
	flostat = *--psavbc | (flostat&mask);
	contlab = *--psavbc;
	brklab = *--psavbc;

	}

addcase(p) NODE *p; { /* add case to switch */

	p = optim( p );  /* change enum to ints */
	if( p->in.op != ICON ){
		uerror( "non-constant case expression");
		return;
		}
	if( swp == swtab ){
		uerror( "case not in switch");
		return;
		}
	if( swp >= &swtab[SWITSZ] ){
		cerror( "switch table overflow");
		}
	swp->sval = p->tn.lval;
	deflab( swp->slab = getlab() );
	++swp;
	tfree(p);
	}

adddef(){ /* add default case to switch */
	if( swtab[swx].slab >= 0 ){
		uerror( "duplicate default in switch");
		return;
		}
	if( swp == swtab ){
		uerror( "default not inside switch");
		return;
		}
	deflab( swtab[swx].slab = getlab() );
	}

swstart(){
	/* begin a switch block */
	if( swp >= &swtab[SWITSZ] ){
		cerror( "switch table overflow");
		}
	swx = swp - swtab;
	swp->slab = -1;
	++swp;
	}

swend(){ /* end a switch block */

	register struct sw *swbeg, *p, *q, *r, *r1;
	CONSZ temp;
	int tempi;

	swbeg = &swtab[swx+1];

	/* sort */

	r1 = swbeg;
	r = swp-1;

	while( swbeg < r ){
		/* bubble largest to end */
		for( q=swbeg; q<r; ++q ){
			if( q->sval > (q+1)->sval ){
				/* swap */
				r1 = q+1;
				temp = q->sval;
				q->sval = r1->sval;
				r1->sval = temp;
				tempi = q->slab;
				q->slab = r1->slab;
				r1->slab = tempi;
				}
			}
		r = r1;
		r1 = swbeg;
		}

	/* it is now sorted */

	for( p = swbeg+1; p<swp; ++p ){
		if( p->sval == (p-1)->sval ){
			uerror( "duplicate case in switch, %d", tempi=p->sval );
			return;
			}
		}

	genswitch( swbeg-1, swp-swbeg );
	swp = swbeg-1;
	}
short yyexca[] ={
-1, 1,
	0, -1,
	2, 21,
	11, 21,
	50, 21,
	57, 21,
	-2, 0,
-1, 19,
	56, 80,
	57, 80,
	-2, 7,
-1, 24,
	56, 79,
	57, 79,
	-2, 77,
-1, 26,
	56, 83,
	57, 83,
	-2, 78,
-1, 32,
	52, 44,
	-2, 42,
-1, 34,
	52, 36,
	-2, 34,
	};
# define YYNPROD 182
# define YYLAST 1180
short yyact[]={

 231,  18, 265, 196,  93,  98, 129, 145, 130,  56,
 229,  59,   6,  27, 251,  89,  87,  88,  27, 100,
  80,  46,  21,  78, 232,  51,  79,  21,  10,   9,
  14,  27,  27,  96,  92, 274,  27,  20,  96, 273,
  21,  21,  82,  81,  16,  21, 306, 108, 241, 242,
 246,  75, 250, 239, 240, 247, 248, 249, 253, 252,
  83,  22,  84, 305, 108, 230,  22,  77, 110, 243,
  45, 300,  94, 162,  36, 259, 106, 131,  19,  22,
  22,  10,   9,  14,  22, 146, 150, 227, 103, 154,
 205,  17,  66, 289,  41,  43, 269,  16, 268, 101,
 200, 153,  36,  35, 163, 199, 283,  91,  70,  24,
 189, 158, 154,  71, 164, 165, 166, 168, 170, 172,
 174, 176, 177, 179, 181, 183, 184, 185, 186, 187,
  99,  40,  42, 131, 102, 188, 191, 155, 134, 190,
 136, 161,  74, 256, 112, 146, 138, 139, 140, 141,
 142, 143, 193,  38,  69,  48,  68,  39, 137,  49,
 258, 109, 135, 221, 221,  48,  73,  95, 206,  49,
 207,  38, 208, 203, 209,  39, 210,  65,  48, 211,
 255, 212,  49, 213, 215, 251,  89,  87,  88, 156,
 131,  80, 157, 159,  78, 152, 217,  79, 216,  33,
 225, 223, 224,  31,   8, 228, 226, 295, 287, 280,
 219, 198,  28,  82,  81, 254,  95, 194, 198, 241,
 242, 246,  72, 250, 239, 240, 247, 248, 249, 253,
 252,  83,  64,  84,  53, 108,  57, 151, 266,  10,
 243,  14, 271,  27, 261, 262, 263, 264, 202, 267,
 197, 107,  21, 281, 296,  16, 275, 197, 222, 284,
 279, 278, 220, 277, 276, 151,  52,  97, 244, 286,
 285,   9,  97,  54, 282,  47, 102, 290, 291, 266,
 293, 292,  30, 119, 272,  26,  26, 220, 192, 147,
  26,  22,  10,   9,  14,  60,  57, 302, 297, 111,
 115, 266,  34, 303,   4, 116,   7, 117,  16,  32,
 119,  95,  67, 121, 257,  29, 122, 245, 123, 105,
 126, 132, 124, 125, 127, 113, 120, 115, 118,  50,
 116,  25, 117,  61,  44, 119, 201, 116,  90, 117,
  55,  58, 119, 116, 160, 117, 204, 104, 119, 147,
 304, 121, 115, 118, 122, 114, 123, 128, 126, 115,
 124, 125, 127, 113, 120, 115, 118,  63,  62,  37,
   3,   2, 149,  85,  11,  12,   5,  23,  13, 116,
  15, 117, 238, 236, 119, 237, 235, 121, 301, 233,
 122, 234, 123, 114, 126, 128, 124, 125, 127, 113,
 120, 115, 118,   1,   0,   0,   0,   0,   0,   0,
   0,   0,   0,   0,   0, 116,   0, 117,   0,   0,
 119,   0,   0, 121, 299,   0, 122,   0, 123, 114,
 126, 128, 124, 125, 127, 113, 120, 115, 118, 244,
   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
   0,   0,   0, 116,   0, 117,   0,   0, 119,   0,
 298, 121,   0,   0, 122, 114, 123, 128, 126, 294,
 124, 125, 127, 113, 120, 115, 118, 116,   0, 117,
   0,   0, 119,   0,   0, 121,   0,   0, 122,   0,
 123,   0, 126,   0, 124, 125, 127, 113, 120, 115,
 118,   0, 116, 114, 117, 128,   0, 119,   0,   0,
 121,   0,   0, 122,   0, 123,   0, 126,   0, 124,
 125, 127, 113, 120, 115, 118,   0, 114, 288, 128,
   0,   0,   0,   0,   0,   0, 116,   0, 117,   0,
   0, 119,   0,   0,   0,   0,   0,   0,   0,   0,
   0,   0, 114, 260, 128, 116, 113, 117, 115, 118,
 119,   0,   0, 121,   0,   0, 122,   0, 123,   0,
 126,   0, 124, 125, 127, 113, 120, 115, 118, 116,
   0, 117,   0,   0, 119,   0,   0, 121,   0,   0,
 122,   0, 123,   0, 126, 214, 124, 125, 127, 113,
 120, 115, 118,   0, 218, 114,   0, 128,   0,   0,
   0,   0,   0,   0,   0, 116,   0, 117,   0, 116,
 119, 117,   0, 121, 119,   0, 122, 121, 123, 114,
 126, 128, 124, 125, 127, 113, 120, 115, 118, 113,
 120, 115, 118,   0,   0,   0,   0,   0,   0,   0,
   0, 116,   0, 117,   0,   0, 119,   0,   0, 121,
 195,   0, 122,   0, 123, 114, 126, 128, 124, 125,
 127, 113, 120, 115, 118, 116,   0, 117,   0,   0,
 119,   0,   0, 121,   0,   0, 122,   0, 123,   0,
 126,   0, 124, 125, 127, 113, 120, 115, 118,   0,
   0, 114,   0, 128,  86,  89,  87,  88,   0,   0,
  80,   0,   0,  78,   0,   0,  79,  86,  89,  87,
  88,   0,   0,  80,   0,   0,  78, 128,   0,  79,
   0,   0,  82,  81,   0,   0,   0,   0,   0,   0,
   0,   0,   0,   0,   0,  82,  81,   0,   0,   0,
  83,   0,  84,   0,   0,  86,  89,  87,  88,   0,
 182,  80,   0,  83,  78,  84,   0,  79,  86,  89,
  87,  88,   0, 180,  80,   0,   0,  78,   0,   0,
  79,   0,   0,  82,  81,   0,   0,   0,   0,   0,
   0,   0,   0,   0,   0,   0,  82,  81,   0,   0,
   0,  83,   0,  84,   0,   0,  86,  89,  87,  88,
   0, 178,  80,   0,  83,  78,  84,   0,  79,  86,
  89,  87,  88,   0, 175,  80,   0,   0,  78,   0,
   0,  79,   0,   0,  82,  81,   0,   0,   0,   0,
   0,   0,   0,   0,   0,   0,   0,  82,  81,   0,
   0,   0,  83,   0,  84,   0,   0,  86,  89,  87,
  88,   0, 173,  80,   0,  83,  78,  84,   0,  79,
  86,  89,  87,  88,   0, 171,  80,   0,   0,  78,
   0,   0,  79,   0,   0,  82,  81,   0,   0,   0,
   0,   0,   0,   0,   0,   0,   0,   0,  82,  81,
   0,   0,   0,  83,   0,  84,   0,   0,  86,  89,
  87,  88,   0, 169,  80,   0,  83,  78,  84,   0,
  79,  86,  89,  87,  88,   0, 167,  80,   0,   0,
  78,   0,   0,  79,   0,   0,  82,  81, 116,   0,
 117,   0,   0, 119,   0,   0, 121,   0,   0,  82,
  81, 123,   0,   0,  83,   0,  84,   0, 113, 120,
 115, 118,   0, 270,   0,   0,   0,  83,   0,  84,
   0, 133,  86,  89,  87,  88,   0,   0,  80,   0,
   0,  78,   0,   0,  79,  86,  89,  87,  88,   0,
   0,  80,   0,   0,  78,   0,   0,  79,   0,   0,
  82,  81,   0,  10,   0,  14,   0,   0,   0,   0,
   0,   0,   0,  82,  81,   0,   0,   0,  83,  16,
  84,   0,   0,   0,   0,  86,  89,  87,  88,   0,
   0,  83,   0,  84,   0,  76,  86,  89,  87,  88,
   0,   0,  80,   0,   0,  78,   0,   0,  79,  86,
  89,  87,  88,  82,  81,  80,   0,   0,  78,   0,
   0,  79,   0,   0,  82,  81,   0,   0,   0,   0,
   0,  83,   0,  84,   0,   0,   0,  82,  81,   0,
   0, 116,  83, 117,  84, 148, 119,  86,  89,  87,
  88,   0,   0,  80,   0,  83,  78,  84,   0,  79,
   0, 113, 120, 115, 118,   0, 116,   0, 117,   0,
   0, 119,   0,   0, 121,  82,  81, 122,   0, 123,
   0, 126,   0, 124, 125,   0, 113, 120, 115, 118,
   0,   0, 116,  83, 117, 144,   0, 119,   0,   0,
 121,   0,   0, 122,   0, 123,   0,   0,   0, 124,
   0,   0, 113, 120, 115, 118, 116,   0, 117,   0,
   0, 119,   0,   0, 121,   0,   0, 122,   0, 123,
   0,   0,   0,   0,   0,   0, 113, 120, 115, 118 };
short yypact[]={

-1000,  48,-1000,-1000,-1000,  34,-1000, 206, 237,-1000,
 249,-1000,-1000, 151, 307, 147, 300,-1000,  46, 121,
-1000, 241, 241,  19, 128, -33,-1000, 216,-1000, 206,
 240, 206,-1000, 293,-1000,-1000,-1000,-1000, 181, 122,
 128, 121, 105, 103,  57,-1000,-1000,-1000, 171, 111,
 983,-1000,-1000,-1000,-1000,  50,-1000,  11,  74,-1000,
 -39,  29,-1000,  -5,-1000,-1000, 106,1047,-1000,-1000,
-1000, 297,-1000,-1000,  89, 669, 919, 108,1047,1047,
1047,1047,1047,1085, 970,1034, 215,-1000,-1000,-1000,
 142, 206,  56,-1000, 121, 115,-1000,-1000, 139, 293,
-1000,-1000, 121,-1000,-1000,-1000,  16,  47,-1000,-1000,
 669,-1000,-1000,1047,1047, 868, 855, 817, 804, 766,
1047, 753, 715, 702,1047,1047,1047,1047,1047,  54,
-1000, 669, 919,-1000,-1000,1047, 286,-1000, 108, 108,
 108, 108, 108, 108, 970, 166, 609, 200,-1000,  49,
 669,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,
 259,  33,-1000,-1000, 324, 669,-1000,1047, 272,1047,
 272,1047, 331,1047,-1000,1047, 530,1075,1047, 932,
1047, 613,1047,1150,1126, 573, 669, 669, 131, 919,
  54, 549,-1000, 159,1047,-1000, 110, 207, 200,1047,
-1000,  11,-1000,  30,  12,-1000, 669, 669, 669, 669,
 669, 669, 669, 669,1047,-1000,-1000, 127,-1000,1023,
 108,  88,-1000, 109, 110, 669,-1000,-1000,  18,-1000,
-1000, 496,-1000, 183, 183, 183, 183,1047, 183,  41,
  39, 906, 282,-1000, -18, 183, 214, 213,-1000, 211,
 210, 187,1047, 252,1100,-1000,-1000,  51, 209,-1000,
-1000, 231,-1000,-1000, 226, 157, 645,-1000,-1000,-1000,
-1000, 471,  36,-1000,-1000,-1000,1047,1047,1047,1047,
-1000, 447,-1000,-1000, 156,-1000, 204, 183,-1000,-1000,
 409, 373,  14, 337,-1000,-1000,1047,-1000,-1000,-1000,
1047,-1000, 299,   6, -11,-1000,-1000 };
short yypgo[]={

   0, 403,  92, 391, 389, 386, 385, 383, 382, 380,
 378, 377,   0,   2,  67,  12, 376, 204, 375, 374,
   7,   3, 373,   4,  72, 109, 372, 371, 370,   1,
 369, 368, 367,  24, 347, 346,  10, 344,  34, 306,
 341,   5,  11, 340, 338,   9, 336, 334,  37, 333,
 331, 329,   6,   8, 321, 319, 317, 312 };
short yyr1[]={

   0,   1,   1,  27,  27,  28,  28,  30,  28,  31,
  32,  32,  35,  35,  37,  37,  37,  34,  34,  34,
  16,  16,  15,  15,  15,  15,  15,  39,  17,  17,
  17,  17,  17,  18,  18,   9,   9,  40,  40,  42,
  42,  19,  19,  10,  10,  43,  43,  45,  45,  38,
  46,  38,  23,  23,  23,  23,  23,  25,  25,  25,
  25,  25,  25,  24,  24,  24,  24,  24,  24,  24,
  11,  47,  47,  47,  29,  49,  29,  50,  50,  48,
  48,  48,  48,  48,  52,  52,  53,  53,  41,  41,
  44,  44,  51,  51,  54,  33,  55,  36,  36,  36,
  36,  36,  36,  36,  36,  36,  36,  36,  36,  36,
  36,  36,  36,  36,  56,  56,  56,   7,   4,   3,
   5,   6,   8,  57,   2,  13,  13,  26,  26,  12,
  12,  12,  12,  12,  12,  12,  12,  12,  12,  12,
  12,  12,  12,  12,  12,  12,  12,  12,  12,  12,
  12,  12,  12,  12,  14,  14,  14,  14,  14,  14,
  14,  14,  14,  14,  14,  14,  14,  14,  14,  14,
  14,  14,  20,  21,  21,  21,  21,  21,  21,  21,
  22,  22 };
short yyr2[]={

   0,   2,   0,   1,   1,   2,   3,   0,   4,   2,
   2,   0,   2,   0,   3,   4,   0,   3,   2,   2,
   1,   0,   2,   2,   1,   1,   3,   1,   1,   2,
   3,   1,   1,   5,   2,   1,   2,   1,   3,   1,
   3,   5,   2,   1,   2,   1,   3,   2,   1,   1,
   0,   4,   1,   1,   3,   2,   1,   2,   3,   3,
   4,   1,   3,   2,   3,   3,   4,   3,   3,   2,
   2,   1,   3,   1,   1,   0,   4,   1,   1,   1,
   1,   3,   6,   1,   1,   3,   1,   4,   0,   1,
   0,   1,   0,   1,   1,   4,   1,   2,   1,   2,
   2,   2,   7,   4,   2,   2,   2,   2,   3,   3,
   1,   2,   2,   2,   2,   3,   2,   1,   4,   3,
   4,   6,   4,   0,   2,   1,   0,   1,   3,   3,
   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,
   3,   3,   4,   4,   4,   4,   4,   4,   4,   4,
   5,   3,   3,   1,   2,   2,   2,   2,   2,   2,
   2,   4,   4,   4,   2,   3,   3,   1,   1,   1,
   1,   3,   2,   0,   2,   5,   2,   3,   4,   3,
   2,   2 };
short yychk[]={

-1000,  -1, -27, -28, 256, -16, -15, -39, -17,  34,
  33, -19, -18, -10,  35,  -9,  49,  57, -29, -24,
 -48,  11,  50, -11, -25, -50, 256,   2, -17, -39,
  33,  52,   2,  52,   2,  57,  56, -30,  50,  54,
 -25, -24, -25, -24, -47,  51,   2, 256,  50,  54,
 -51,  58,  50, -17,  33, -43, -45, -17, -40, -42,
   2, -49, -31, -32,  51,  55,  -2, -57,  51,  51,
  51,  56,  51,  55,  -2, -12,  52, -14,  11,  14,
   8,  31,  30,  48,  50, -22,   2,   4,   5,   3,
 -44,  57, -38, -23, -24, -25,  22, 256, -41,  56,
  58, -48, -24, -33, -34, -55, -15, 256,  52,  55,
 -12,   2,  55,  26,  56,  28,   6,   8,  29,  11,
  27,  14,  17,  19,  23,  24,  21,  25,  58, -52,
 -53, -12, -54,  52,  30,  54,  32,  50, -14, -14,
 -14, -14, -14, -14,  50, -20, -12, -17,  51, -26,
 -12,  50,  53, -45,  56,  22,  -2,  53, -42,  -2,
 -37, -38,  57,  57, -12, -12, -12,  58, -12,  58,
 -12,  58, -12,  58, -12,  58, -12, -12,  58, -12,
  58, -12,  58, -12, -12, -12, -12, -12, -41,  56,
 -52, -12,   2, -20,  51,  51, -21,  50,  11,  56,
  51, -46,  -2, -15, -35,  57, -12, -12, -12, -12,
 -12, -12, -12, -12,  22,  53, -53, -41,  55,  51,
 -14,  54,  51, -21, -21, -12, -23,  57, -29, -36,
  53, -12, -33,  -4,  -3,  -5,  -7,  -6,  -8,  41,
  42,  36,  37,  57, 256, -56,  38,  43,  44,  45,
  40,   2,  47,  46, -12,  53,  55,  -2,  51,  57,
  57, -36, -36, -36, -36, -13, -12, -36,  57,  57,
  57, -12,   2,  57,  53, -36,  50,  50,  50,  50,
  22, -12,  22,  55,  50,  39,  43,  51,  57,  57,
 -12, -12, -13, -12,  22,  51,  50, -36,  51,  51,
  57,  51, -12, -13,  51,  57,  57 };
short yydef[]={

   2,  -2,   1,   3,   4,   0,  20,  24,  25,  27,
  28,  31,  32,   0,  43,   0,  35,   5,   0,  -2,
  74,   0,   0,   0,  -2,  92,  -2,  61,  22,  23,
  29,   0,  -2,   0,  -2,   6,  75,  11,   0, 123,
  57,  63,   0,   0,   0,  69,  71,  73,   0, 123,
   0,  93,  70,  26,  30,  90,  45,  48,  88,  37,
  39,   0,   8,   0,  64,  65,   0,   0,  62,  67,
  68,   0,  58,  59,   0,  81,   0, 153,   0,   0,
   0,   0,   0,   0,   0,   0, 167, 168, 169, 170,
   0,  91,  47,  49,  52,  53, 123,  56,   0,  89,
 123,  76,  80,   9,  10,  16,   0,   0,  96,  66,
 124,  72,  60,   0,   0,   0,   0,   0,   0,   0,
   0,   0,   0,   0,   0,   0,   0,   0,   0,  88,
  84,  86,   0,  94, 154,   0,   0, 181, 155, 156,
 157, 158, 159, 160,   0,   0,   0, 173, 164,   0,
 127, 180,  41,  46,  50, 123,  55,  33,  38,  40,
  13,   0,  18,  19, 129, 130, 131,   0, 132,   0,
 133,   0, 134,   0, 135,   0, 136, 137,   0, 138,
   0, 139,   0, 140, 141,   0, 151, 152,   0,  89,
  88,   0, 166,   0,   0, 171, 172, 173, 173,   0,
 165,   0,  54,   0,   0,  17, 143, 144, 145, 146,
 142, 147, 148, 149,   0,  82,  85,   0, 163, 162,
 161, 123, 174,   0, 176, 128,  51,  14,   0,  12,
  95,   0,  98,   0,   0,   0,   0, 126,   0,   0,
   0,   0,   0, 110,   0,   0,   0,   0, 117,   0,
   0, 167,   0,   0, 150,  87, 177,   0, 179,  15,
  97,  99, 100, 101,   0,   0, 125, 104, 105, 106,
 107,   0,   0, 111, 112, 113,   0,   0, 126,   0,
 114,   0, 116, 178,   0, 119,   0,   0, 108, 109,
   0,   0,   0,   0, 115, 175,   0, 103, 118, 120,
 126, 122,   0,   0,   0, 121, 102 };
#
# define YYFLAG -1000
# define YYERROR goto yyerrlab
# define YYACCEPT return(0)
# define YYABORT return(1)

/*	parser for yacc output	*/

#ifdef YYDEBUG
int yydebug = 0; /* 1 for debugging */
#endif
YYSTYPE yyv[YYMAXDEPTH]; /* where the values are stored */
int yychar = -1; /* current input token number */
int yynerrs = 0;  /* number of errors */
short yyerrflag = 0;  /* error recovery flag */

yyparse() {

	short yys[YYMAXDEPTH];
	short yyj, yym;
	register YYSTYPE *yypvt;
	register short yystate, *yyps, yyn;
	register YYSTYPE *yypv;
	register short *yyxi;

	yystate = 0;
	yychar = -1;
	yynerrs = 0;
	yyerrflag = 0;
	yyps= &yys[-1];
	yypv= &yyv[-1];

 yystack:    /* put a state and value onto the stack */

#ifdef YYDEBUG
	if( yydebug  ) printf( "state %d, char 0%o\n", yystate, yychar );
#endif
		if( ++yyps> &yys[YYMAXDEPTH] ) { yyerror( "yacc stack overflow" ); return(1); }
		*yyps = yystate;
		++yypv;
		*yypv = yyval;

 yynewstate:

	yyn = yypact[yystate];

	if( yyn<= YYFLAG ) goto yydefault; /* simple state */

	if( yychar<0 ) if( (yychar=yylex())<0 ) yychar=0;
	if( (yyn += yychar)<0 || yyn >= YYLAST ) goto yydefault;

	if( yychk[ yyn=yyact[ yyn ] ] == yychar ){ /* valid shift */
		yychar = -1;
		yyval = yylval;
		yystate = yyn;
		if( yyerrflag > 0 ) --yyerrflag;
		goto yystack;
		}

 yydefault:
	/* default state action */

	if( (yyn=yydef[yystate]) == -2 ) {
		if( yychar<0 ) if( (yychar=yylex())<0 ) yychar = 0;
		/* look through exception table */

		for( yyxi=yyexca; (*yyxi!= (-1)) || (yyxi[1]!=yystate) ; yyxi += 2 ) ; /* VOID */

		while( *(yyxi+=2) >= 0 ){
			if( *yyxi == yychar ) break;
			}
		if( (yyn = yyxi[1]) < 0 ) return(0);   /* accept */
		}

	if( yyn == 0 ){ /* error */
		/* error ... attempt to resume parsing */

		switch( yyerrflag ){

		case 0:   /* brand new error */

			yyerror( "syntax error" );
		yyerrlab:
			++yynerrs;

		case 1:
		case 2: /* incompletely recovered error ... try again */

			yyerrflag = 3;

			/* find a state where "error" is a legal shift action */

			while ( yyps >= yys ) {
			   yyn = yypact[*yyps] + YYERRCODE;
			   if( yyn>= 0 && yyn < YYLAST && yychk[yyact[yyn]] == YYERRCODE ){
			      yystate = yyact[yyn];  /* simulate a shift of "error" */
			      goto yystack;
			      }
			   yyn = yypact[*yyps];

			   /* the current yyps has no shift onn "error", pop stack */

#ifdef YYDEBUG
			   if( yydebug ) printf( "error recovery pops state %d, uncovers %d\n", *yyps, yyps[-1] );
#endif
			   --yyps;
			   --yypv;
			   }

			/* there is no state on the stack with an error shift ... abort */

	yyabort:
			return(1);


		case 3:  /* no shift yet; clobber input char */

#ifdef YYDEBUG
			if( yydebug ) printf( "error recovery discards char %d\n", yychar );
#endif

			if( yychar == 0 ) goto yyabort; /* don't discard EOF, quit */
			yychar = -1;
			goto yynewstate;   /* try again in the same state */

			}

		}

	/* reduction by production yyn */

#ifdef YYDEBUG
		if( yydebug ) printf("reduce %d\n",yyn);
#endif
		yyps -= yyr2[yyn];
		yypvt = yypv;
		yypv -= yyr2[yyn];
		yyval = yypv[1];
		yym=yyn;
			/* consult goto table to find next state */
		yyn = yyr1[yyn];
		yyj = yypgo[yyn] + *yyps + 1;
		if( yyj>=YYLAST || yychk[ yystate = yyact[yyj] ] != -yyn ) yystate = yyact[yypgo[yyn]];
		switch(yym){
			
case 2:
# line 133 "cgram.y"
ftnend(); break;
case 3:
# line 136 "cgram.y"
{ curclass = SNULL;  blevel = 0; } break;
case 4:
# line 138 "cgram.y"
{ curclass = SNULL;  blevel = 0; } break;
case 5:
# line 142 "cgram.y"
{  yypvt[-1].nodep->in.op = FREE; } break;
case 6:
# line 144 "cgram.y"
{  yypvt[-2].nodep->in.op = FREE; } break;
case 7:
# line 145 "cgram.y"
{
				defid( tymerge(yypvt[-1].nodep,yypvt[-0].nodep), curclass==STATIC?STATIC:EXTDEF );
				} break;
case 8:
# line 148 "cgram.y"
{  
			    if( blevel ) cerror( "function level error" );
			    if( reached ) retstat |= NRETVAL; 
			    yypvt[-3].nodep->in.op = FREE;
			    ftnend();
			    } break;
case 11:
# line 159 "cgram.y"
{  blevel = 1; } break;
case 13:
# line 164 "cgram.y"
{  bccode();
			    locctr(PROG);
			    } break;
case 14:
# line 170 "cgram.y"
{  yypvt[-1].nodep->in.op = FREE; } break;
case 15:
# line 172 "cgram.y"
{  yypvt[-2].nodep->in.op = FREE; } break;
case 17:
# line 177 "cgram.y"
{ curclass = SNULL;  yypvt[-2].nodep->in.op = FREE; } break;
case 18:
# line 179 "cgram.y"
{ curclass = SNULL;  yypvt[-1].nodep->in.op = FREE; } break;
case 19:
# line 181 "cgram.y"
{  curclass = SNULL; } break;
case 21:
# line 186 "cgram.y"
{  yyval.nodep = mkty(INT,0,INT);  curclass = SNULL; } break;
case 22:
# line 189 "cgram.y"
{  yyval.nodep = yypvt[-0].nodep; } break;
case 24:
# line 192 "cgram.y"
{  yyval.nodep = mkty(INT,0,INT); } break;
case 25:
# line 194 "cgram.y"
{ curclass = SNULL ; } break;
case 26:
# line 196 "cgram.y"
{  yypvt[-2].nodep->in.type = types( yypvt[-2].nodep->in.type, yypvt[-0].nodep->in.type, UNDEF );
 			    yypvt[-0].nodep->in.op = FREE;
 			    } break;
case 27:
# line 203 "cgram.y"
{  curclass = yypvt[-0].intval; } break;
case 29:
# line 208 "cgram.y"
{  yypvt[-1].nodep->in.type = types( yypvt[-1].nodep->in.type, yypvt[-0].nodep->in.type, UNDEF );
			    yypvt[-0].nodep->in.op = FREE;
			    } break;
case 30:
# line 212 "cgram.y"
{  yypvt[-2].nodep->in.type = types( yypvt[-2].nodep->in.type, yypvt[-1].nodep->in.type, yypvt[-0].nodep->in.type );
			    yypvt[-1].nodep->in.op = yypvt[-0].nodep->in.op = FREE;
			    } break;
case 33:
# line 220 "cgram.y"
{ yyval.nodep = dclstruct(yypvt[-4].intval); } break;
case 34:
# line 222 "cgram.y"
{  yyval.nodep = rstruct(yypvt[-0].intval,0);  stwart = instruct; } break;
case 35:
# line 226 "cgram.y"
{  yyval.intval = bstruct(-1,0); stwart = SEENAME; } break;
case 36:
# line 228 "cgram.y"
{  yyval.intval = bstruct(yypvt[-0].intval,0); stwart = SEENAME; } break;
case 39:
# line 236 "cgram.y"
{  moedef( yypvt[-0].intval ); } break;
case 40:
# line 238 "cgram.y"
{  strucoff = yypvt[-0].intval;  moedef( yypvt[-2].intval ); } break;
case 41:
# line 242 "cgram.y"
{ yyval.nodep = dclstruct(yypvt[-4].intval);  } break;
case 42:
# line 244 "cgram.y"
{  yyval.nodep = rstruct(yypvt[-0].intval,yypvt[-1].intval); } break;
case 43:
# line 248 "cgram.y"
{  yyval.intval = bstruct(-1,yypvt[-0].intval);  stwart=0; } break;
case 44:
# line 250 "cgram.y"
{  yyval.intval = bstruct(yypvt[-0].intval,yypvt[-1].intval);  stwart=0;  } break;
case 47:
# line 258 "cgram.y"
{ curclass = SNULL;  stwart=0; yypvt[-1].nodep->in.op = FREE; } break;
case 48:
# line 260 "cgram.y"
{  if( curclass != MOU ){
				curclass = SNULL;
				}
			    else {
				sprintf( fakename, "$%dFAKE", fake++ );
				defid( tymerge(yypvt[-0].nodep, bdty(NAME,NIL,lookup( fakename, SMOS ))), curclass );
				werror("structure typed union member must be named");
				}
			    stwart = 0;
			    yypvt[-0].nodep->in.op = FREE;
			    } break;
case 49:
# line 275 "cgram.y"
{ defid( tymerge(yypvt[-1].nodep,yypvt[-0].nodep), curclass);  stwart = instruct; } break;
case 50:
# line 276 "cgram.y"
{yyval.nodep=yypvt[-2].nodep;} break;
case 51:
# line 277 "cgram.y"
{ defid( tymerge(yypvt[-4].nodep,yypvt[-0].nodep), curclass);  stwart = instruct; } break;
case 54:
# line 283 "cgram.y"
{  if( !(instruct&INSTRUCT) ) uerror( "field outside of structure" );
			    if( yypvt[-0].intval<0 || yypvt[-0].intval >= FIELD ){
				uerror( "illegal field size" );
				yypvt[-0].intval = 1;
				}
			    defid( tymerge(yypvt[-3].nodep,yypvt[-2].nodep), FIELD|yypvt[-0].intval );
			    yyval.nodep = NIL;
			    } break;
case 55:
# line 293 "cgram.y"
{  if( !(instruct&INSTRUCT) ) uerror( "field outside of structure" );
			    falloc( stab, yypvt[-0].intval, -1, yypvt[-2].nodep );  /* alignment or hole */
			    yyval.nodep = NIL;
			    } break;
case 56:
# line 298 "cgram.y"
{  yyval.nodep = NIL; } break;
case 57:
# line 303 "cgram.y"
{  umul:
				yyval.nodep = bdty( UNARY MUL, yypvt[-0].nodep, 0 ); } break;
case 58:
# line 306 "cgram.y"
{  uftn:
				yyval.nodep = bdty( UNARY CALL, yypvt[-2].nodep, 0 );  } break;
case 59:
# line 309 "cgram.y"
{  uary:
				yyval.nodep = bdty( LB, yypvt[-2].nodep, 0 );  } break;
case 60:
# line 312 "cgram.y"
{  bary:
				if( (int)yypvt[-1].intval <= 0 ) werror( "zero or negative subscript" );
				yyval.nodep = bdty( LB, yypvt[-3].nodep, yypvt[-1].intval );  } break;
case 61:
# line 316 "cgram.y"
{  yyval.nodep = bdty( NAME, NIL, yypvt[-0].intval );  } break;
case 62:
# line 318 "cgram.y"
{ yyval.nodep=yypvt[-1].nodep; } break;
case 63:
# line 321 "cgram.y"
{  goto umul; } break;
case 64:
# line 323 "cgram.y"
{  goto uftn; } break;
case 65:
# line 325 "cgram.y"
{  goto uary; } break;
case 66:
# line 327 "cgram.y"
{  goto bary; } break;
case 67:
# line 329 "cgram.y"
{ yyval.nodep = yypvt[-1].nodep; } break;
case 68:
# line 331 "cgram.y"
{
				if( blevel!=0 ) uerror("function declaration in bad context");
				yyval.nodep = bdty( UNARY CALL, bdty(NAME,NIL,yypvt[-2].intval), 0 );
				stwart = 0;
				} break;
case 69:
# line 337 "cgram.y"
{
				yyval.nodep = bdty( UNARY CALL, bdty(NAME,NIL,yypvt[-1].intval), 0 );
				stwart = 0;
				} break;
case 70:
# line 344 "cgram.y"
{
				/* turn off typedefs for argument names */
				stwart = SEENAME;
				if( stab[yypvt[-1].intval].sclass == SNULL )
				    stab[yypvt[-1].intval].stype = FTN;
				} break;
case 71:
# line 353 "cgram.y"
{ ftnarg( yypvt[-0].intval );  stwart = SEENAME; } break;
case 72:
# line 355 "cgram.y"
{ ftnarg( yypvt[-0].intval );  stwart = SEENAME; } break;
case 75:
# line 361 "cgram.y"
{yyval.nodep=yypvt[-2].nodep;} break;
case 77:
# line 365 "cgram.y"
{  defid( yypvt[-0].nodep = tymerge(yypvt[-1].nodep,yypvt[-0].nodep), curclass);
			    beginit(yypvt[-0].nodep->tn.rval);
			    } break;
case 79:
# line 372 "cgram.y"
{  nidcl( tymerge(yypvt[-1].nodep,yypvt[-0].nodep) ); } break;
case 80:
# line 374 "cgram.y"
{  defid( tymerge(yypvt[-1].nodep,yypvt[-0].nodep), uclass(curclass) );
			} break;
case 81:
# line 378 "cgram.y"
{  doinit( yypvt[-0].nodep );
			    endinit(); } break;
case 82:
# line 381 "cgram.y"
{  endinit(); } break;
case 86:
# line 391 "cgram.y"
{  doinit( yypvt[-0].nodep ); } break;
case 87:
# line 393 "cgram.y"
{  irbrace(); } break;
case 92:
# line 405 "cgram.y"
{  werror( "old-fashioned initialization: use =" ); } break;
case 94:
# line 410 "cgram.y"
{  ilbrace(); } break;
case 95:
# line 416 "cgram.y"
{  --blevel;
			    if( blevel == 1 ) blevel = 0;
			    clearst( blevel );
			    checkst( blevel );
			    autooff = *--psavbc;
			    regvar = *--psavbc;
			    } break;
case 96:
# line 426 "cgram.y"
{  if( blevel == 1 ) dclargs();
			    ++blevel;
			    if( psavbc > &asavbc[BCSZ-2] ) cerror( "nesting too deep" );
			    *psavbc++ = regvar;
			    *psavbc++ = autooff;
			    } break;
case 97:
# line 435 "cgram.y"
{ ecomp( yypvt[-1].nodep ); } break;
case 99:
# line 438 "cgram.y"
{ deflab(yypvt[-1].intval);
			   reached = 1;
			   } break;
case 100:
# line 442 "cgram.y"
{  if( yypvt[-1].intval != NOLAB ){
				deflab( yypvt[-1].intval );
				reached = 1;
				}
			    } break;
case 101:
# line 448 "cgram.y"
{  branch(  contlab );
			    deflab( brklab );
			    if( (flostat&FBRK) || !(flostat&FLOOP)) reached = 1;
			    else reached = 0;
			    resetbc(0);
			    } break;
case 102:
# line 455 "cgram.y"
{  deflab( contlab );
			    if( flostat & FCONT ) reached = 1;
			    ecomp( buildtree( CBRANCH, buildtree( NOT, yypvt[-2].nodep, NIL ), bcon( yypvt[-6].intval ) ) );
			    deflab( brklab );
			    reached = 1;
			    resetbc(0);
			    } break;
case 103:
# line 463 "cgram.y"
{  deflab( contlab );
			    if( flostat&FCONT ) reached = 1;
			    if( yypvt[-2].nodep ) ecomp( yypvt[-2].nodep );
			    branch( yypvt[-3].intval );
			    deflab( brklab );
			    if( (flostat&FBRK) || !(flostat&FLOOP) ) reached = 1;
			    else reached = 0;
			    resetbc(0);
			    } break;
case 104:
# line 473 "cgram.y"
{  if( reached ) branch( brklab );
			    deflab( yypvt[-1].intval );
			   swend();
			    deflab(brklab);
			    if( (flostat&FBRK) || !(flostat&FDEF) ) reached = 1;
			    resetbc(FCONT);
			    } break;
case 105:
# line 481 "cgram.y"
{  if( brklab == NOLAB ) uerror( "illegal break");
			    else if(reached) branch( brklab );
			    flostat |= FBRK;
			    if( brkflag ) goto rch;
			    reached = 0;
			    } break;
case 106:
# line 488 "cgram.y"
{  if( contlab == NOLAB ) uerror( "illegal continue");
			    else branch( contlab );
			    flostat |= FCONT;
			    goto rch;
			    } break;
case 107:
# line 494 "cgram.y"
{  retstat |= NRETVAL;
			    branch( retlab );
			rch:
			    if( !reached ) werror( "statement not reached");
			    reached = 0;
			    } break;
case 108:
# line 501 "cgram.y"
{  register NODE *temp;
			    idname = curftn;
			    temp = buildtree( NAME, NIL, NIL );
			    if(temp->in.type == TVOID)
				uerror("void function %s cannot return value",
					stab[idname].sname);
			    temp->in.type = DECREF( temp->in.type );
			    temp = buildtree( RETURN, temp, yypvt[-1].nodep );
			    /* now, we have the type of the RHS correct */
			    tfree(temp->in.left);
			    temp->in.op = FREE;
			    ecomp( buildtree( FORCE, temp->in.right, NIL ) );
			    retstat |= RETVAL;
			    branch( retlab );
			    reached = 0;
			    } break;
case 109:
# line 518 "cgram.y"
{  register NODE *q;
			    q = block( FREE, NIL, NIL, INT|ARY, 0, INT );
			    q->tn.rval = idname = yypvt[-1].intval;
			    defid( q, ULABEL );
			    stab[idname].suse = -lineno;
			    branch( stab[idname].offset );
			    goto rch;
			    } break;
case 114:
# line 532 "cgram.y"
{  register NODE *q;
			    q = block( FREE, NIL, NIL, INT|ARY, 0, LABEL );
			    q->tn.rval = yypvt[-1].intval;
			    defid( q, LABEL );
			    reached = 1;
			    } break;
case 115:
# line 539 "cgram.y"
{  addcase(yypvt[-1].nodep);
			    reached = 1;
			    } break;
case 116:
# line 543 "cgram.y"
{  reached = 1;
			    adddef();
			    flostat |= FDEF;
			    } break;
case 117:
# line 549 "cgram.y"
{  savebc();
			    if( !reached ) werror( "loop not entered at top");
			    brklab = getlab();
			    contlab = getlab();
			    deflab( yyval.intval = getlab() );
			    reached = 1;
			    } break;
case 118:
# line 558 "cgram.y"
{  ecomp( buildtree( CBRANCH, yypvt[-1].nodep, bcon( yyval.intval=getlab()) ) ) ;
			    reached = 1;
			    } break;
case 119:
# line 563 "cgram.y"
{  if( reached ) branch( yyval.intval = getlab() );
			    else yyval.intval = NOLAB;
			    deflab( yypvt[-2].intval );
			    reached = 1;
			    } break;
case 120:
# line 571 "cgram.y"
{  savebc();
			    if( !reached ) werror( "loop not entered at top");
			    if( yypvt[-1].nodep->in.op == ICON && yypvt[-1].nodep->tn.lval != 0 ) flostat = FLOOP;
			    deflab( contlab = getlab() );
			    reached = 1;
			    brklab = getlab();
			    if( flostat == FLOOP ) tfree( yypvt[-1].nodep );
			    else ecomp( buildtree( CBRANCH, yypvt[-1].nodep, bcon( brklab) ) );
			    } break;
case 121:
# line 582 "cgram.y"
{  if( yypvt[-3].nodep ) ecomp( yypvt[-3].nodep );
			    else if( !reached ) werror( "loop not entered at top");
			    savebc();
			    contlab = getlab();
			    brklab = getlab();
			    deflab( yyval.intval = getlab() );
			    reached = 1;
			    if( yypvt[-1].nodep ) ecomp( buildtree( CBRANCH, yypvt[-1].nodep, bcon( brklab) ) );
			    else flostat |= FLOOP;
			    } break;
case 122:
# line 594 "cgram.y"
{  savebc();
			    brklab = getlab();
			    ecomp( buildtree( FORCE, makety(yypvt[-1].nodep,INT,0,INT), NIL ) );
			    branch( yyval.intval = getlab() );
			    swstart();
			    reached = 0;
			    } break;
case 123:
# line 603 "cgram.y"
{ yyval.intval=instruct; stwart=instruct=0; } break;
case 124:
# line 605 "cgram.y"
{  yyval.intval = icons( yypvt[-0].nodep );  instruct=yypvt[-1].intval; } break;
case 126:
# line 609 "cgram.y"
{ yyval.nodep=0; } break;
case 128:
# line 614 "cgram.y"
{  goto bop; } break;
case 129:
# line 618 "cgram.y"
{
			preconf:
			    if( yychar==RELOP||yychar==EQUOP||yychar==AND||yychar==OR||yychar==ER ){
			    precplaint:
				if( hflag ) werror( "precedence confusion possible: parenthesize!" );
				}
			bop:
			    yyval.nodep = buildtree( yypvt[-1].intval, yypvt[-2].nodep, yypvt[-0].nodep );
			    } break;
case 130:
# line 628 "cgram.y"
{  yypvt[-1].intval = COMOP;
			    goto bop;
			    } break;
case 131:
# line 632 "cgram.y"
{  goto bop; } break;
case 132:
# line 634 "cgram.y"
{  if(yychar==SHIFTOP) goto precplaint; else goto bop; } break;
case 133:
# line 636 "cgram.y"
{  if(yychar==SHIFTOP ) goto precplaint; else goto bop; } break;
case 134:
# line 638 "cgram.y"
{  if(yychar==PLUS||yychar==MINUS) goto precplaint; else goto bop; } break;
case 135:
# line 640 "cgram.y"
{  goto bop; } break;
case 136:
# line 642 "cgram.y"
{  goto preconf; } break;
case 137:
# line 644 "cgram.y"
{  if( yychar==RELOP||yychar==EQUOP ) goto preconf;  else goto bop; } break;
case 138:
# line 646 "cgram.y"
{  if(yychar==RELOP||yychar==EQUOP) goto preconf; else goto bop; } break;
case 139:
# line 648 "cgram.y"
{  if(yychar==RELOP||yychar==EQUOP) goto preconf; else goto bop; } break;
case 140:
# line 650 "cgram.y"
{  goto bop; } break;
case 141:
# line 652 "cgram.y"
{  goto bop; } break;
case 142:
# line 654 "cgram.y"
{  abop:
				yyval.nodep = buildtree( ASG yypvt[-2].intval, yypvt[-3].nodep, yypvt[-0].nodep );
				} break;
case 143:
# line 658 "cgram.y"
{  goto abop; } break;
case 144:
# line 660 "cgram.y"
{  goto abop; } break;
case 145:
# line 662 "cgram.y"
{  goto abop; } break;
case 146:
# line 664 "cgram.y"
{  goto abop; } break;
case 147:
# line 666 "cgram.y"
{  goto abop; } break;
case 148:
# line 668 "cgram.y"
{  goto abop; } break;
case 149:
# line 670 "cgram.y"
{  goto abop; } break;
case 150:
# line 672 "cgram.y"
{  yyval.nodep=buildtree(QUEST, yypvt[-4].nodep, buildtree( COLON, yypvt[-2].nodep, yypvt[-0].nodep ) );
			    } break;
case 151:
# line 675 "cgram.y"
{  werror( "old-fashioned assignment operator" );  goto bop; } break;
case 152:
# line 677 "cgram.y"
{  goto bop; } break;
case 154:
# line 681 "cgram.y"
{  yyval.nodep = buildtree( yypvt[-0].intval, yypvt[-1].nodep, bcon(1) ); } break;
case 155:
# line 683 "cgram.y"
{ ubop:
			    yyval.nodep = buildtree( UNARY yypvt[-1].intval, yypvt[-0].nodep, NIL );
			    } break;
case 156:
# line 687 "cgram.y"
{  if( ISFTN(yypvt[-0].nodep->in.type) || ISARY(yypvt[-0].nodep->in.type) ){
				werror( "& before array or function: ignored" );
				yyval.nodep = yypvt[-0].nodep;
				}
			    else goto ubop;
			    } break;
case 157:
# line 694 "cgram.y"
{  goto ubop; } break;
case 158:
# line 696 "cgram.y"
{
			    yyval.nodep = buildtree( yypvt[-1].intval, yypvt[-0].nodep, NIL );
			    } break;
case 159:
# line 700 "cgram.y"
{  yyval.nodep = buildtree( yypvt[-1].intval==INCR ? ASG PLUS : ASG MINUS,
						yypvt[-0].nodep,
						bcon(1)  );
			    } break;
case 160:
# line 705 "cgram.y"
{  yyval.nodep = doszof( yypvt[-0].nodep ); } break;
case 161:
# line 707 "cgram.y"
{  yyval.nodep = buildtree( CAST, yypvt[-2].nodep, yypvt[-0].nodep );
			    yyval.nodep->in.left->in.op = FREE;
			    yyval.nodep->in.op = FREE;
			    yyval.nodep = yyval.nodep->in.right;
			    } break;
case 162:
# line 713 "cgram.y"
{  yyval.nodep = doszof( yypvt[-1].nodep ); } break;
case 163:
# line 715 "cgram.y"
{  yyval.nodep = buildtree( UNARY MUL, buildtree( PLUS, yypvt[-3].nodep, yypvt[-1].nodep ), NIL ); } break;
case 164:
# line 717 "cgram.y"
{  yyval.nodep=buildtree(UNARY CALL,yypvt[-1].nodep,NIL); } break;
case 165:
# line 719 "cgram.y"
{  yyval.nodep=buildtree(CALL,yypvt[-2].nodep,yypvt[-1].nodep); } break;
case 166:
# line 721 "cgram.y"
{  if( yypvt[-1].intval == DOT ){
				if( notlval( yypvt[-2].nodep ) )uerror("structure reference must be addressable");
				yypvt[-2].nodep = buildtree( UNARY AND, yypvt[-2].nodep, NIL );
				}
			    idname = yypvt[-0].intval;
			    yyval.nodep = buildtree( STREF, yypvt[-2].nodep, buildtree( NAME, NIL, NIL ) );
			    } break;
case 167:
# line 729 "cgram.y"
{  idname = yypvt[-0].intval;
			    /* recognize identifiers in initializations */
			    if( blevel==0 && stab[idname].stype == UNDEF ) {
				register NODE *q;
				werror( "undeclared initializer name %.*s", NCHNAM, stab[idname].sname );
				q = block( FREE, NIL, NIL, INT, 0, INT );
				q->tn.rval = idname;
				defid( q, EXTERN );
				}
			    yyval.nodep=buildtree(NAME,NIL,NIL);
			    stab[yypvt[-0].intval].suse = -lineno;
			} break;
case 168:
# line 742 "cgram.y"
{  yyval.nodep=bcon(0);
			    yyval.nodep->tn.lval = lastcon;
			    yyval.nodep->tn.rval = NONAME;
			    if( yypvt[-0].intval ) yyval.nodep->fn.csiz = yyval.nodep->in.type = ctype(LONG);
			    } break;
case 169:
# line 748 "cgram.y"
{  yyval.nodep=buildtree(FCON,NIL,NIL);
			    yyval.nodep->fpn.dval = dcon;
			    } break;
case 170:
# line 752 "cgram.y"
{  yyval.nodep = getstr(); /* get string contents */ } break;
case 171:
# line 754 "cgram.y"
{ yyval.nodep=yypvt[-1].nodep; } break;
case 172:
# line 758 "cgram.y"
{
			yyval.nodep = tymerge( yypvt[-1].nodep, yypvt[-0].nodep );
			yyval.nodep->in.op = NAME;
			yypvt[-1].nodep->in.op = FREE;
			} break;
case 173:
# line 766 "cgram.y"
{ yyval.nodep = bdty( NAME, NIL, -1 ); } break;
case 174:
# line 768 "cgram.y"
{ yyval.nodep = bdty( UNARY CALL, bdty(NAME,NIL,-1),0); } break;
case 175:
# line 770 "cgram.y"
{  yyval.nodep = bdty( UNARY CALL, yypvt[-3].nodep, 0 ); } break;
case 176:
# line 772 "cgram.y"
{  goto umul; } break;
case 177:
# line 774 "cgram.y"
{  goto uary; } break;
case 178:
# line 776 "cgram.y"
{  goto bary;  } break;
case 179:
# line 778 "cgram.y"
{ yyval.nodep = yypvt[-1].nodep; } break;
case 180:
# line 782 "cgram.y"
{  if( stab[yypvt[-1].intval].stype == UNDEF ){
				register NODE *q;
				q = block( FREE, NIL, NIL, FTN|INT, 0, INT );
				q->tn.rval = yypvt[-1].intval;
				defid( q, EXTERN );
				}
			    idname = yypvt[-1].intval;
			    yyval.nodep=buildtree(NAME,NIL,NIL);
			    stab[idname].suse = -lineno;
			} break;
		}
		goto yystack;  /* stack new state and value */

	}
e 776 "cgram.y"
{  goto bary;  } break;
case 179:
# line 778 "cgram.y"
{ yyval.nodep = yypvt[-1].nodep; } break;
case 180:
# line 782 "cgram.y"
{  if( stab[yypvt[-1].intval].stype == UNDEF ){
				register NODE *q;
				q = block( FREE, NIL, NIL, FTN|INT, 0, INT );
				q->tn.rval = yypvt[-1].intval;
				defid( q, EXTERN );
				}
			    idname = yypvt[-1].intval;
			    yyval.nodep=buildtree(NAME,NIL,NIL);
			    stab[idname].suse = -lineno;
			}c86/code.c                                                                                             666      26      12        16437  3260403362   5573                                                                                                                                                                                                                                                                                                                                                                      # include <stdio.h>
# include <signal.h>

# include "mfile1"

int proflag;
int strftn = 0;	/* is the current function one which returns a value */
FILE *tmpfile;
FILE *outfile = stdout;

branch( n ){
	/* output a branch to label n */
	printf( "	br	L%d\n", n );
	}

int lastloc = PROG;

defalign(n) {
	/* cause the alignment to become a multiple of n */
	n /= SZCHAR;
	if( lastloc != PROG && n > 1 ) fprintf(outfile, "	.even\n" );
	}

locctr( l ){
	register temp;
	/* l is PROG, ADATA, DATA, STRNG, ISTRNG, or STAB */

	if( l == lastloc ) return(l);
	temp = lastloc;
	lastloc = l;
	switch( l ){

	case PROG:
		outfile = stdout;
		if( temp!=STRNG && temp!=ISTRNG ) printf( "	.text\n" );
		break;

	case DATA:
	case ADATA:
		outfile = stdout;
		if( temp!=DATA && temp!=ADATA && temp!=STRNG && temp!=ISTRNG)
			printf( "	.data\n" );
		break;

	case STRNG:
	case ISTRNG:
		outfile = tmpfile;
		break;

	case STAB:
		cerror( "locctr: STAB unused" );
		break;

	default:
		cerror( "illegal location counter" );
		}

	return( temp );
	}

deflab( n ){
	/* output something to define the current position as label n */
	fprintf( outfile, "L%d:\n", n );
	}

int crslab = 10;

getlab(){
	/* return a number usable for a label */
	return( ++crslab );
	}

efcode(){
	/* code for the end of a function */

	deflab( retlab );

	if( strftn ){  /* copy output (in r0) to caller */
		register struct symtab *p;
		register int stlab;
		register int count;
		int size;

		p = &stab[curftn];

		stlab = getlab();
		printf( "	mov	si,ax\n	mov	di,#L%d\n", stlab );
		size = tsize( DECREF(p->stype), p->dimoff, p->sizoff ) / SZCHAR;
		printf( "	mov	cx,#%d\n	cld\n	repz\n	movw\n", size/2 );
		printf( "	mov	ax,#L%d\n", stlab );
		printf( "	.bss\nL%d:	.=.+%d\n	.text\n", stlab, size );
		}

	printf("\tlea\tsp,*-4(bp)\n\tpop\tdi\n\tpop\tsi\n\tpop\tbp\n\tret\n");

	p2bend();
	}

bfcode( a, n ) int a[]; {
	/* code for the beginning of a function; a is an array of
		indices in stab for the arguments; n is the number */
	register i;
	register temp;
	register struct symtab *p;
	int off;
	extern char *rnames[];

	locctr( PROG );
	p = &stab[curftn];
	defnam( p );
	temp = p->stype;
	temp = DECREF(temp);
	strftn = (temp==STRTY) || (temp==UNIONTY);

	retlab = getlab();
	if( proflag ){
		int plab;
		plab = getlab();
		printf( "	mov	ax,#L%d\n", plab );
		printf( "	call	mcount\n" );
		printf( "	.bss\nL%d:	.=.+2\n	.text\n", plab );
		}

	/* routine prolog */

	printf( "\tpush\tbp\n\tmov\tbp,sp\n\tpush\tsi\n\tpush\tdi\n" );
	/* adjust stack for autos */
	printf( "	sub	sp,#LF%d\n", ftnno );

	/* check for stack overflow */
/*	printf( "	lea	ax,-LF%d-64(bp)\n", ftnno );
	printf( "\tcmp\tax,bp\n\tjnb\t.+7\n\tcmp\tax,__memtop\n\tja\t.+5\n\tcall\t__bomb\n" );
*/

	off = ARGINIT;

	for( i=0; i<n; ++i ){
		p = &stab[a[i]];
		if( p->sclass == REGISTER ){
			temp = p->offset;  /* save register number */
			p->sclass = PARAM;  /* forget that it is a register */
			p->offset = NOOFFSET;
			oalloc( p, &off );
			printf( "\tmov\t%s,%d(bp)\n", rnames[temp], p->offset/SZCHAR );
			p->offset = temp;  /* remember register number */
			p->sclass = REGISTER;   /* remember that it is a register */
			}
		else {
			if( oalloc( p, &off ) ) cerror( "bad argument" );
			}

		}
	}

bccode(){ /* called just before the first executable statment */
		/* by now, the automatics and register variables are allocated */
	SETOFF( autooff, SZINT );
	/* set aside store area offset */
	p2bbeg( autooff, regvar );
	}

ejobcode( flag ){
	/* called just before final exit */
	/* flag is 1 if errors, 0 if none */
	}

aobeg(){
	/* called before removing automatics from stab */
	}

aocode(p) struct symtab *p; {
	/* called when automatic p removed from stab */
	}

aoend(){
	/* called after removing all automatics from stab */
	}

defnam( p ) register struct symtab *p; {
	/* define the current location as the name p->sname */

	if( p->sclass == EXTDEF ){
		printf( "	.globl	%s\n", exname( p->sname ) );
		}
	if( p->sclass == STATIC && p->slevel>1 ) deflab( p->offset );
	else printf( "%s:\n", exname( p->sname ) );

	}

bycode( t, i ){
	/* put byte i+1 in a string */

	i &= 07;
	if( t < 0 ){ /* end of the string */
		if( i != 0 ) fprintf( outfile, "\n" );
		}

	else { /* stash byte t into string */
		if( i == 0 ) fprintf( outfile, "	.byte	" );
		else fprintf( outfile, "," );
		fprintf( outfile, "%d", t );
		if( i == 07 ) fprintf( outfile, "\n" );
		}
	}

zecode( n ){
	/* n integer words of zeros */
	OFFSZ temp;
	register i;

	if( n <= 0 ) return;
	printf( "	.zerow	%d\n", n );
	temp = n;
	inoff += temp*SZINT;
	}

fldal( t ) unsigned t; { /* return the alignment of field of type t */
	uerror( "illegal field type" );
	return( ALINT );
	}

fldty( p ) struct symtab *p; { /* fix up type of field p */
	;
	}

where(c){ /* print location of error  */
	/* c is either 'u', 'c', or 'w' */
	fprintf( stderr, "%s, line %d: ", ftitle, lineno );
	}

char *tmpname = "/tmp/pcXXXXXX";

main( argc, argv ) char *argv[]; {
	int dexit();
	register int c;
	register int i;
	int r;

	for( i=1; i<argc; ++i )
		if( argv[i][0] == '-' && argv[i][1] == 'X' && argv[i][2] == 'p' ) {
			proflag = 1;
			}

	mktemp(tmpname);
	if(signal( SIGHUP, SIG_IGN) != SIG_IGN) signal(SIGHUP, dexit);
	if(signal( SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, dexit);
	if(signal( SIGTERM, SIG_IGN) != SIG_IGN) signal(SIGTERM, dexit);
	tmpfile = fopen( tmpname, "w" );

	r = mainp1( argc, argv );

	tmpfile = freopen( tmpname, "r", tmpfile );
	if( tmpfile != NULL )
		while((c=getc(tmpfile)) != EOF )
			putchar(c);
	else cerror( "Lost temp file" );
	unlink(tmpname);
	return( r );
	}

dexit( v ) {
	unlink(tmpname);
	exit(1);
	}

genswitch(p,n) register struct sw *p;{
	/*	p points to an array of structures, each consisting
		of a constant value and a label.
		The first is >=0 if there is a default label;
		its value is the label number
		The entries p[1] to p[n] are the nontrivial cases
		*/
	register i;
	register CONSZ j, range;
	register dlab, swlab;

	range = p[n].sval-p[1].sval;
	dlab = p->slab >= 0 ? p->slab : getlab();

	if( range>0 && range <= 3*n && n>=4 ){ /* implement a direct switch */

		if( p[1].sval ){
			printf( "	sub	ax,#" );
			printf( CONFMT, p[1].sval );
			printf( "\n" );
			}

		/* note that this is a cl; it thus checks
		   for numbers below range as well as out of range.
		   */
		printf( "	cmp	ax,#%ld\n", range );
		printf( "	bhi	L%d\n", dlab );
		printf( "	sal	ax,*1\n" );
		printf( "	xchg	ax,bx\n" );
		printf( "	jmp	cs:@L%d(bx)\n", swlab = getlab() );

		/* output table */

		printf("L%d:\n", swlab );

		for( i=1,j=p[1].sval; i<=n; ++j )
		  printf( "\t.word\tL%d\n", ( j == p[i].sval ) ? p[i++].slab : dlab);

	} else genbinary(p,1,n,0,dlab);		/* do binary search */

	if( p->slab< 0 ) deflab( dlab );
}

genbinary(p,lo,hi,lab,dlab)
  register struct sw *p;
  {	register int i,lab1;

	if (lab) printf("L%d:",lab);	/* print label, if any */

	if (hi-lo > 4) {		/* if lots more, do another level */
	  i = lo + ((hi-lo)>>1);	/* index at which we'll break this time */
	  printf( "	cmp	ax,#" );
	  printf( CONFMT, p[i].sval );
	  printf( "\n	beq	L%d\n", p[i].slab );
	  printf( "	bgt	L%d\n", lab1=getlab() );
	  genbinary(p,lo,i-1,0,dlab);
	  genbinary(p,i+1,hi,lab1,dlab);
	} else {			/* simple switch code for remaining cases */
	  for( i=lo; i<=hi; ++i ) {
	    printf( "	cmp	ax,#" );
	    printf( CONFMT, p[i].sval );
	    printf( "\n	beq	L%d\n", p[i].slab );
	  }
	  branch( dlab );
	}
}
o another level */
	  i = lo + ((hi-lo)>>1);	/* index at which we'll break this time */
	  printf( "	cmp	ax,#" );
	  printf( CONFMT, p[i].sval );
	  printf( "\n	beq	L%d\n", p[i].slab );
	  printf( "	bgt	L%d\n", lab1=getlab() c86/comm1.c                                                                                            444      26      12           50  2537050424   5572                                                                                                                                                                                                                                                                                                                                                                      # include "mfile1"

# include "common"

binary(p,i+1,hi,lab1,dlab);
	} else {			/* simple switch code for remaining cases */
	  for( i=lo; i<=hi; ++i ) {
	    printf( "	cmp	ax,#" );
	    printf( CONFMT, p[i].sval );
	    printf( "\n	beq	L%d\n", p[i].slab );
	  }
	  branch( dlab );
	}
}
o another level */
	  i = lo + ((hi-lo)>>1);	/* index at which we'll break this time */
	  printf( "	cmp	ax,#" );
	  printf( CONFMT, p[i].sval );
	  printf( "\n	beq	L%d\n", p[i].slab );
	 /usr/src/local/Machines/8086/c86     c86/local.c                                                                                            644      26      12        20540  3330045327   5736                                                                                                                                                                                                                                                                                                                                                                      # include "mfile1"


/*	this file contains code which is dependent on the target machine */

NODE *
cast( p, t ) register NODE *p; TWORD t; {
	/* cast node p to type t */

	p = buildtree( CAST, block( NAME, NIL, NIL, t, 0, (int)t ), p );
	p->in.left->in.op = FREE;
	p->in.op = FREE;
	return( p->in.right );
	}

NODE *
clocal(p) NODE *p; {

	/* this is called to do local transformations on
	   an expression tree preparitory to its being
	   written out in intermediate code.
	*/

	/* the major essential job is rewriting the
	   automatic variables and arguments in terms of
	   REG and OREG nodes */
	/* conversion ops which are not necessary are also clobbered here */
	/* in addition, any special features (such as rewriting
	   exclusive or) are easily handled here as well */

	register struct symtab *q;
	register NODE *r;
	register o;
	register m, ml;

	switch( o = p->in.op ){

	case NAME:
		if( p->tn.rval < 0 ) { /* already processed; ignore... */
			return(p);
			}
		q = &stab[p->tn.rval];
		switch( q->sclass ){

		case AUTO:
		case PARAM:
			/* fake up a structure reference */
			r = block( REG, NIL, NIL, PTR+STRTY, 0, 0 );
			r->tn.lval = 0;
			r->tn.rval = (q->sclass==AUTO?STKREG:ARGREG);
			p = stref( block( STREF, r, p, 0, 0, 0 ) );
			break;

		case ULABEL:
		case LABEL:
		case STATIC:
			if( q->slevel == 0 ) break;
			p->tn.lval = 0;
			p->tn.rval = -q->offset;
			break;

		case REGISTER:
			p->in.op = REG;
			p->tn.lval = 0;
			p->tn.rval = q->offset;
			break;

			}
		break;
	case LT:
	case LE:
	case GT:
	case GE:
		if( ISPTR( p->in.left->in.type ) || ISPTR( p->in.right->in.type ) ){
			p->in.op += (ULT-LT);
			}
		break;

	case PCONV:
		/* do pointer conversions for char and longs */
		ml = p->in.left->in.type;
		if( ( ml==CHAR || ml==UCHAR || ml==LONG || ml==ULONG ) && p->in.left->in.op != ICON ) {
		  p->in.op = SCONV;
		  break;
		}

		/* pointers all have the same representation; the type is inherited */
		p->in.left->in.type = p->in.type;
		p->in.left->fn.cdim = p->fn.cdim;
		p->in.left->fn.csiz = p->fn.csiz;
		p->in.op = FREE;
		return( p->in.left );

	case SCONV:
		m = (p->in.type == FLOAT || p->in.type == DOUBLE );
		ml = (p->in.left->in.type == FLOAT || p->in.left->in.type == DOUBLE );
		if( m != ml ) break;
		if( m || ml ) goto clob;	/* ignore float <=> double conversions */

		/* now, look for conversions downwards */

		m = p->in.type;
		ml = p->in.left->in.type;
		if( p->in.left->in.op == ICON ){ /* simulate the conversion here */
			CONSZ val;
			val = p->in.left->tn.lval;
			switch( m ){
			case CHAR:
				p->in.left->tn.lval = (char) val;
				break;
			case UCHAR:
				p->in.left->tn.lval = val & 0XFF;
				break;
			case UNSIGNED:
				p->in.left->tn.lval = val & 0XFFFFL;
				break;
			case INT:
				p->in.left->tn.lval = (int)val;
				break;
				}
			p->in.left->in.type = m;
			}
		else if( p->in.left->in.op == FCON ){ /* simulate the conversion here */
			p->in.left->in.type = m;
		} else if ((ISUNSIGNED(m)?DEUNSIGN(m):m)==(ISUNSIGNED(ml)?DEUNSIGN(ml):ml)) {
			p->in.left->in.type = m;
		} else if (m != 0) break; /* clobber conversion to void */

		/* clobber conversion */
	clob:	p->in.op = FREE;
		return( p->in.left );  /* conversion gets clobbered */

	case PVCONV:
	case PMCONV:
		if( p->in.right->in.op != ICON ) cerror( "bad conversion", 0);
		p->in.op = FREE;
		return( buildtree( o==PMCONV?MUL:DIV, p->in.left, p->in.right ) );

	case PLUS:
	case MINUS:
	case LS:
	case MUL:
		/* optimize address calculations with long indexes */
		if( ISPTR( p->in.type ) || ISARY( p->in.type ) ) {
			if( p->in.left->in.type==LONG || p->in.left->in.type==ULONG )
				p->in.left = cast( p->in.left, INT );
			if( p->in.right->in.type==LONG || p->in.right->in.type==ULONG )
				p->in.right = cast( p->in.right, INT );
			}
		break;

		}

	return(p);
	}

andable( p ) NODE *p; {
	return(1);  /* all names can have & taken on them */
	}

cendarg(){ /* at the end of the arguments of a ftn, set the automatic offset */
	autooff = AUTOINIT;
	}

cisreg( t ) TWORD t; { /* is an automatic variable of type t OK for a register variable */

	if( t==INT || t==UNSIGNED || ISPTR(t) ) return(1);
	return(0);
	}

NODE *
offcon( off, t, d, s ) OFFSZ off; TWORD t; {

	/* return a node, for structure references, which is suitable for
	   being added to a pointer of type t, in order to be off bits offset
	   into a structure */

	register NODE *p;

	/* t, d, and s are the type, dimension offset, and sizeoffset */
	/* in general they  are necessary for offcon, but not on H'well */

	p = bcon(0);
	p->tn.lval = off/SZCHAR;
	return(p);

	}

static inwd	/* current bit offsed in word */;
static word	/* word being built from fields */;

incode( p, sz ) register NODE *p; {

	/* generate initialization code for assigning a constant c
		to a field of width sz */
	/* we assume that the proper alignment has been obtained */
	/* inoff is updated to have the proper final value */
	/* we also assume sz  < SZINT */

	if((sz+inwd) > SZINT) cerror("incode: field > int");
	word |= (p->tn.lval<<inwd) & ((unsigned int)-1 >> (SZINT-inwd-sz));
	inwd += sz;
	inoff += sz;
	if(inoff%SZINT == 0) {
		printf( "	.word %d\n", word);
		word = inwd = 0;
		}
	}

fincode( d, sz ) double d; {
	/* output code to initialize space of size sz to the value d */
	/* the proper alignment has been obtained */
	/* inoff is updated to have the proper final value */
	/* on the target machine, write it out in hex! */

	register short *mi = (short *)&d;
	int sign,exp,frac1,frac2,frac3,frac4;
	extern FILE *outfile;

#ifdef vax|pdp11
	/* the code below unpacks the PDP11/VAX floating point representation
	 * and reassembles it for the 8087.  Of course, it should only be
	 * expected to work on VAXes and PDP11's...
	 */
	sign = (mi[0] >> 15) & 1;	/* sign */
	exp = ((mi[0] >> 7) & 0377) - 128;	/* unbiased exponent */
	frac1 = (mi[0]<<9) | ((mi[1]>>7) & 0777);
	frac2 = (mi[1]<<9) | ((mi[2]>>7) & 0777);
	frac3 = (mi[2]<<9) | ((mi[3]>>7) & 0777);
	frac4 = mi[3]<<9;

	if( sz==SZDOUBLE ) {
	  if (d == 0.0) exp = 0;		/* zeroes are special */
	  else exp += 1023 - 1;

	  fprintf(outfile, "	.word 0x%x,0x%x,0x%x,0x%x\n",
		  ((frac3 << 4) | ((frac4 >> 12) & 017)) & 0177777,
		  ((frac2 << 4) | ((frac3 >> 12) & 017)) & 0177777,
		  ((frac1 << 4) | ((frac2 >> 12) & 017)) & 0177777,
		  (sign<<15) | ((exp & 03777) << 4) | ((frac1 >> 12) & 017));
	} else {
	  if (d == 0.0) exp = 0;		/* zeroes are special */
	  else exp += 127 - 1;

	  fprintf(outfile, "	.word 0x%x,0x%x\n",
		  ((frac1 << 7) | ((frac2 >> 9) & 0177)) & 0177777,
		  (sign<<15) | ((exp & 0377) << 7) | ((frac1 >> 9) & 0177));
	}
	inoff += sz;
#else
	cerror( "fincode routine in local.c needs to be fixed up!" );
#endif
	}

cinit( p, sz ) NODE *p; {
	/* arrange for the initialization of p into a space of
	size sz */
	/* the proper alignment has been opbtained */
	/* inoff is updated to have the proper final value */
	ecode( p );
	inoff += sz;
	}

vfdzero( n ){ /* define n bits of zeros in a vfd */

	if( n <= 0 ) return;

	inwd += n;
	inoff += n;
	if( inoff%ALINT ==0 ) {
		printf( "	.word %d\n", word );
		word = inwd = 0;
		}
	}


char *
exname( p ) char *p; {
	/* make a name look like an external name in the local machine */

	static char text[NCHNAM+1];

	register i;

	text[0] = '_';
	for( i=1; *p&&(i<NCHNAM); ++i ){
		text[i] = *p++;
		}

	text[i] = '\0';
	text[NCHNAM] = '\0';  /* truncate */

	return( text );
	}

ctype( type ) TWORD type; { /* map types which are not defined on the local machine */
	switch( BTYPE(type) ){
	case SHORT:
		MODTYPE(type,INT);
		break;
	case USHORT:
		MODTYPE(type,UNSIGNED);
		}
	return( type );
	}

noinit() { /* curid is a variable which is defined but
	is not initialized (and not a function );
	This routine returns the stroage class for an uninitialized declaration */

	return(EXTERN);

	}

commdec( id ){ /* make a common declaration for id, if reasonable */
	register struct symtab *q;
	OFFSZ off;

	q = &stab[id];
	printf( "	.comm	%s,", exname( q->sname ) );
	off = tsize( q->stype, q->dimoff, q->sizoff );
	printf( CONFMT, off/SZCHAR );
	printf( "\n" );
	}

isitlong( cb, ce ){ /* is lastcon to be long or short */
	/* cb is the first character of the representation, ce the last */

	if( ce == 'l' || ce == 'L' ||
		lastcon >= (1L << (SZINT-1) ) ) return (1);
	return(0);
	}


isitfloat( s ) char *s; {
	double atof();
	dcon = atof(s);
	return( FCON );
	}

ecode( p ) NODE *p; {

	/* walk the tree and write out the nodes.. */

	if( nerrors ) return;
	p2tree( p );
	p2compile( p );
	}

stype, q->dimoff, q->sizoff );
	printf( CONFMT, off/SZCHAR );
	printf( "\n" );
	}

isitlong( cb, ce ){ /* is lastcon to be long or short */
	/* cb is the first c86/local2.c                                                                                           444      26      12        47737  3357031723   6043                                                                                                                                                                                                                                                                                                                                                                      # include "mfile2"
/* a lot of the machine dependent parts of the second pass */

# define BITMASK(n) ((1L<<n)-1)

lineid( l, fn ) char *fn; {
	/* identify line l and file fn */
	printf( "|	line %d, file %s\n", l, fn );
	}

eobl2(){
	OFFSZ spoff;	/* offset from stack pointer */

	spoff = maxoff;
	if( spoff >= AUTOINIT ) spoff -= AUTOINIT;
	spoff /= SZCHAR;
	SETOFF(spoff,2);
	printf( "	LF%d = %ld\n", ftnno, spoff );
	if( fltused ) fltused = 0;
	}

struct hoptab { int opmask; char * opstring; } ioptab[]= {

	ASG PLUS, "add",
	ASG MINUS, "sub",
	ASG OR,	"or",
	ASG AND,"and",
	ASG ER,	"xor",
	ASG MUL, "imul",
	ASG DIV, "idiv",
	ASG MOD, "idiv",
	ASG LS,	"sal",
	ASG RS,	"sar",
	-1, ""    };

hopcode( f, o ){
	/* output the appropriate string from the above table */

	register struct hoptab *q;

	for( q = ioptab;  q->opmask>=0; ++q ){
		if( q->opmask == o ){
			printf( "%s", q->opstring );
			if( f == 'F' ) printf( "f" );
			return;
			}
		}
	cerror( "no hoptab for %s", opst[o] );
	}

char *
rnames[]= {  /* keyed to register number tokens */

	"ax", "dx",
	"bx", "si", "di",
	"cx", "bp", "sp"
	};

int rstatus[] = {
	SAREG|STAREG,
	SAREG|STAREG,
	SAREG|STAREG|SBREG|STBREG,
	SAREG|STAREG|SBREG|STBREG,
	SAREG|STAREG|SBREG|STBREG,
	SAREG,
	SAREG|SBREG,
	SAREG|SBREG,
	};

NODE *brnode;
int brcase;

int toff = 0; /* number of stack locations used for args */

zzzcode( p, c ) NODE *p; {
	static int zzzlabel;
	static int dglab;			/* somtimes need two labels */
	register m;
	switch( c ){

	case '1':
		p = getlr( p, '1' );
		p->tn.lval++;
		adrput(p);
		p->tn.lval--;
		return;

	case 'O':
		switch (p->in.op) {
		  case PLUS:
		  case ASG PLUS:	printf("fadd"); return;

		  case MINUS:
		  case ASG MINUS:	printf("fsub"); return;

		  case MUL:
		  case ASG MUL:		printf("fmul"); return;

		  case DIV:
		  case ASG DIV:		printf("fdiv"); return;

		  default:		printf("???");
		}
		return;

	case 'c':
		acon( p->in.right );
		return;

	case 'd':
		acon( p->in.left );
		return;

	case 'B':	/* output b if type is byte */
		if( p->in.type == CHAR || p->in.type == UCHAR ) printf( "b" );
		else if( p->in.type == FLOAT ) printf( "f" );
		else if( p->in.type == DOUBLE ) printf( "d" );
		return;

	case 'l':
		p = p->in.left;
		goto ford;

	case 'r':
		p = p->in.right;
	ford:	putchar( p->in.type == DOUBLE ? 'd' : 'f');
		return;

	case 'N':  /* logical ops, turned into 0-1 */
		/* use register given by register 1 */
		cbgen( 0, m=getlab(), 'I' );
		deflab( p->bn.label );
		printf( "	mov	%s,*0\n", rnames[getlr( p, '1' )->tn.rval] );
		if( p->in.type == LONG || p->in.type == ULONG )
			printf( "	mov	%s,*0\n", rnames[getlr( p, '1' )->tn.rval + 1] );
		deflab( m );
		return;

	case 'x': zzzlabel = getlab();
	case 'y': printf( LABFMT, zzzlabel );
		  break;
	case 'Y': dglab = getlab();
		  printf( LABFMT, dglab );		/* for long shifts */
		  break;

	case 'X': zzzlabel = getlab();
	case 'z': deflab( zzzlabel ); return;

	case 's': deflab ( dglab ); return;

	case 'L':
		acon( p->in.left );
		return;

	case 'I':
	case 'F':
		cbgen( p->in.op, p->bn.label, c );
		return;

	case 'A':
	case 'C':
		/* logical operators for longs
		   defer comparisons until branch occurs */

		brnode = tcopy( p );
		brcase = c;
		return;

	case 'V':
		if( ISUNSIGNED(p->in.type) ){
			printf( "	mov	dx,*0\n" );
			}
		else {
			printf( "	cwd\n" );
			}
		return;

		/* stack management macros */
	case '-':
		toff++;
		return;

	case '4':
		toff += 4;
		return;

	case '~':
		/* complimented CR */
		p->in.right->tn.lval = ~p->in.right->tn.lval;
		conput( getlr( p, 'R' ) );
		p->in.right->tn.lval = ~p->in.right->tn.lval;
		return;

	case 'M':
		/* negated CR */
		p->in.right->tn.lval = -p->in.right->tn.lval;
		conput( getlr( p, 'R' ) );
		p->in.right->tn.lval = -p->in.right->tn.lval;
		return;

	case 'e':	/* sign extend A1 from byte */
		m = p->in.type;
		if (getlr(p,'1')->tn.rval == AX) {
		  printf("	cbw");
		  if (m==LONG || m==ULONG) printf("; cwd");
		} else {
		  expand(p, RNOP, "	mov	cx,*8\n	sal	A1,cl\n	sar	A1,cl");
		  if (m==LONG || m==ULONG)
		    expand(p, RNOP, "; mov\tU1,*0\n\tor\tA1,A1\n\tjge\t.+4\n\tnot\tU1");
		}		
		return;

	case 'E':	/* sign extend A1 from word */
		if (getlr(p,'1')->tn.rval == AX) printf("	cwd\n");
		else expand(p, RNOP, "\tmov\tU1,#0\n\tor\tA1,A1\n\tjge\t.+4\n\tnot\tU1\n");
		return;

	case 'T':
		/* Truncate longs for type conversions:
		    LONG|ULONG -> CHAR|UCHAR|INT|UNSIGNED
		   increment offset to second word */

		m = p->in.type;
		p = p->in.left;
		switch( p->in.op ){
		case NAME:
		case OREG:
			return;
		case REG:
			rfree( p->tn.rval, p->in.type );
			p->in.type = m;
			rbusy( p->tn.rval, p->in.type );
			return;
		default:
			cerror( "Illegal ZT type conversion" );
			return;

			}

	case 'U':
		/* same as AL for exp under U* */
		if( p->in.left->in.op == UNARY MUL ) {
			adrput( getlr( p->in.left, 'L' ) );
			return;
			}
		cerror( "Illegal ZU" );
		/* NO RETURN */

	case 'W':	/* structure size */
		if( p->in.op == STASG )
			printf( "%d", p->stn.stsize);
		else	cerror( "Not a structure" );
		return;

	case 'S':  /* structure assignment */
		{
			register NODE *l, *r;
			register size, count;

			if( p->in.op == STASG ){
				l = p->in.left;
				r = p->in.right;
				}
			else cerror( "STASG bad" );

			size = p->stn.stsize;
			count = size / 2;

			if (!(rstatus[SI] & STAREG)) printf("	push	si\n");
			if (!(rstatus[DI] & STAREG)) printf("	push	di\n");

			expand(r, FOREFF,"	cld\n	mov	si,AR\n");
			if (ISPTR(l->in.type)) expand(l, FOREFF,"	mov	di,AL\n");
			else expand(l, FOREFF,"	lea	di,AL\n");

			if (count > 3)
			  printf("	mov	cx,#%d\n	repz\n	movw\n", count);
			else while (count-- > 0) printf("	movw\n");
			if (!(rstatus[DI] & STAREG)) printf("	pop	di\n");
			if (!(rstatus[SI] & STAREG)) printf("	pop	si\n");

			if( r->in.op == NAME ) r->in.op = ICON;
			else if( r->in.op == OREG ) r->in.op = REG;

			}
		break;

	case 'D':  /* double assignment */
		{
			register NODE *l, *r;
			register size, count;

			if( p->in.op == ASSIGN ){
				l = p->in.left;
				r = p->in.right;
				}
			else cerror( "ASSIGN bad" );
/*
			if( r->in.op == ICON ) r->in.op = NAME;
			else if( r->in.op == REG ) r->in.op = OREG;
			else if( r->in.op != OREG ) cerror( "STASG-r" );
*/
			size = 8;
			count = 4;

			printf("	push	si\n	push	di\n");
			expand( r, FOREFF, "	lea	si,AR\n" );
			expand( l, FOREFF, "	lea	di,AL\n" );
			printf("	cld\n	mov	cx,#%d\n	repz\n	movw\n", count);
			printf("	pop	si\n	pop	di\n");

/*			if( r->in.op == NAME ) r->in.op = ICON;
			else if( r->in.op == OREG ) r->in.op = REG;
*/
			}
		break;

	default:
		cerror( "illegal zzzcode" );
		}
	}

rmove( rt, rs, t )
  TWORD t;
  {	printf( "\tmov\t%s,%s\n", rnames[rt], rnames[rs] );
	if (t == LONG)	printf( "\tmov\t%s,%s\n", rnames[rt+1], rnames[rs+1] );
}

struct respref
respref[] = {
	INTAREG,INTAREG|INTBREG,
	INTBREG,INTBREG,
	INAREG,	INAREG|INBREG|SOREG|SNAME|SCON,
	INBREG,	INBREG|SOREG|SNAME|SCON,
	INTEMP,	INTEMP,
	FORARG,	FORARG,
	0,	0 };

setregs(){ /* set up temporary registers */
	register i;

	/* use any unused variable registers as scratch registers */
	fregs = maxtreg>=MINRVAR ? maxtreg + 1 : MINRVAR;
	for( i=MINRVAR; i<=MAXRVAR; i++ )
		rstatus[i] = i<fregs ? SAREG|STAREG|SBREG|STBREG : SAREG|SBREG;
	}

szty(t) TWORD t; { /* size, in words, needed to hold thing of type t */
	/* really is the number of registers to hold type t */
	switch( t ) {

	case LONG:
	case ULONG:
		return( SZLONG/SZINT );

	default:
		return(1);

		}
	}

rewfld( p ) NODE *p; {
	return(1);
	}

callreg(p) NODE *p; {
	return( (p->in.type==DOUBLE||p->in.type==FLOAT) ? AX : AX );
	}

shltype( o, p ) NODE *p; {
	return ( o==NAME || o==REG || o==ICON || o==OREG );
	}

flshape( p ) NODE *p; {
	register o = p->in.op;
	return( o==NAME || o==REG || o==ICON || o==OREG );
	}

shtemp( p ) register NODE *p; {
	if( p->in.op == UNARY MUL ) p = p->in.left;
	if( p->in.op == REG || p->in.op == OREG ) return( !istreg( p->tn.rval ) );
	return( p->in.op == NAME || p->in.op == ICON );
	}

spsz( t, v ) TWORD t; CONSZ v; {

	/* is v the size to increment something of type t */

	if( !ISPTR(t) ) return( 0 );
	t = DECREF(t);

	if( ISPTR(t) ) return( v == 2 );

	switch( t ){

	case UCHAR:
	case CHAR:
		return( v == 1 );

	case INT:
	case UNSIGNED:
		return( v == 2 );

	case FLOAT:
		return( v == 4 );

	case DOUBLE:
		return( v == 8 );
		}

	return( 0 );
	}

shumul( p ) register NODE *p; {
	return( 0 );  
/*	return(1);	*/
	}

adrcon( val ) CONSZ val; {
	printf( CONFMT, val );
	}

conput( p ) register NODE *p; {
	switch( p->in.op ){

	case ICON:
		acon( p );
		return;

	case REG:
		printf( "%s", rnames[p->tn.rval] );
		return;

	default:
		cerror( "illegal conput" );
		}
	}

insput( p ) NODE *p; {
	cerror( "insput" );
	}

upput( p ) NODE *p; {
	/* output the address of the second word in the
	   pair pointed to by p (for LONGs)*/
	CONSZ save;

	if( p->in.op == FLD ){
		p = p->in.left;
		}

	save = p->tn.lval;
	switch( p->in.op ){

	case NAME:
		p->tn.lval += SZINT/SZCHAR;
		acon( p );
		break;

	case ICON:
		/* addressable value of the constant */
		if (p->tn.name[0] != '\0') printf("*0");
		else {
		  CONSZ save; /* print the high order value */
		  save = p->tn.lval;
		  p->tn.lval = ( p->tn.lval >> SZINT ) & BITMASK(SZINT);
		  if (p->tn.name[0]!='\0' || p->tn.lval<-128 || p->tn.lval>127)
		    printf( "#" );
		  acon( p );
		  p->tn.lval = save;
		}
		break;

	case REG:
		printf( "%s", rnames[p->tn.rval+1] );
		break;

	case OREG:
		p->tn.lval += SZINT/SZCHAR;
		if( p->tn.rval == BP ){  /* in the argument region */
			if( p->in.name[0] != '\0' ) werror( "bad arg temp" );
			}
		if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon( p );
		printf( "(%s)", rnames[p->tn.rval] );
		break;

	default:
		cerror( "illegal upper address" );
		break;

		}
	p->tn.lval = save;

	}

adrput( p ) register NODE *p; {
	/* output an address, with offsets, from p */

	if( p->in.op == FLD ){
		p = p->in.left;
		}
	switch( p->in.op ){

	case NAME:
		acon( p );
		return;

	case ICON:
		/* addressable value of the constant */
		if( szty( p->in.type ) == 2 ) {
			/* print the high order value */
			CONSZ save;
			save = p->tn.lval;
			p->tn.lval &= BITMASK(SZINT);
			if (p->tn.name[0]!='\0' || p->tn.lval<-128 || p->tn.lval>127)
			  printf( "#" );
			acon( p );
			p->tn.lval = save;
			return;
			}
		if (p->tn.name[0]!='\0' || p->tn.lval<-128 || p->tn.lval>127) printf( "#" );
		acon( p );
		return;

	case REG:
		printf( "%s", rnames[p->tn.rval] );
		return;

	case OREG:
		if( p->tn.rval == BP ){  /* in the argument region */
			if( p->in.name[0] != '\0' ) werror( "bad arg temp" );
			}
		if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon( p );
		printf( "(%s)", rnames[p->tn.rval] );
		return;

	default:
		cerror( "illegal address" );
		return;

		}

	}

acon( p ) register NODE *p; { /* print out a constant */

	if( p->in.name[0] == '\0' ){	/* constant only */
		if (p->tn.lval>=-128 && p->tn.lval<=127) printf( "*" );
		printf( CONFMT, p->tn.lval);
		}
	else if( p->tn.lval == 0 ) {	/* name only */
		printf( "%.*s", NCHNAM, p->in.name );
		}
	else {				/* name + offset */
		printf( "%.*s+", NCHNAM, p->in.name );
		printf( CONFMT, p->tn.lval );
		}
	}

genscall( p, cookie ) register NODE *p; {
	/* structure valued call */
	return( gencall( p, cookie ) );
	}

gencall( p, cookie ) register NODE *p; {
	/* generate the call given by p */
	register temp;
	register m;

	if( p->in.right ) temp = argsize( p->in.right );
	else temp = 0;

	if( p->in.right ){ /* generate args */
		genargs( p->in.right );
		}

	if( !shltype( p->in.left->in.op, p->in.left ) ) {
		order( p->in.left, INBREG|SOREG );
		}

	p->in.op = UNARY CALL;
	m = match( p, p->in.type==DOUBLE ? INTEMP : INTAREG );
	popargs( temp );
	return(m != MDONE);
	}

popargs( size ) register size; {
	/* pop arguments from stack */

	toff -= size/2;
	switch(size) {
	  case 2:	printf("	pop	cx\n");
	  case 0:	break;
	  default:	printf( "	add	sp,%c%d\n",
				size>127 ? '#':'*', size );
	}
}

char *ccbranches[] = {
	"	beq	L%d\n",
	"	bne	L%d\n",
	"	ble	L%d\n",
	"	blt	L%d\n",
	"	bge	L%d\n",
	"	bgt	L%d\n",
	"	blos	L%d\n",
	"	blo	L%d\n",
	"	bhis	L%d\n",
	"	bhi	L%d\n",
	};

/* floating point comparisons set unsigned condition codes */
char fcc[] = { EQ, NE, ULE, ULT, UGE, UGT, ULE, ULT, UGE, UGT };

/*	long branch table

   This table, when indexed by a logical operator,
   selects a set of three logical conditions required
   to generate long comparisons and branches.  A zero
   entry indicates that no branch is required.
   E.G.:  The <= operator would generate:
	cmp	UL,UR
	blt	lable	/ 1st entry LT -> lable
	bgt	1f	/ 2nd entry GT -> 1f
	cmp	AL,AR
	blos	lable	/ 3rd entry ULE -> lable
   1:
 */

int lbranches[][3] = {
	/*EQ*/	0,	NE,	EQ,
	/*NE*/	NE,	0,	NE,
	/*LE*/	LT,	GT,	ULE,
	/*LT*/	LT,	GT,	ULT,
	/*GE*/	GT,	LT,	UGE,
	/*GT*/	GT,	LT,	UGT,
	/*ULE*/	ULT,	UGT,	ULE,
	/*ULT*/	ULT,	UGT,	ULT,
	/*UGE*/	UGT,	ULT,	UGE,
	/*UGT*/	UGT,	ULT,	UGT,
	};

cbgen( o, lab, mode ) { /*   printf conditional and unconditional branches */
	register *plb;
	int lab1f;

	if( o == 0 ) printf( "	br	L%d\n", lab );
	else	if( o > UGT ) cerror( "bad conditional branch: %s", opst[o] );
	else {
		switch( brcase ) {

		case 'C':
			plb = lbranches[ o-EQ ];
			lab1f = getlab();
			expand( brnode, FORCC, "\tcmp\tUL,UR\n" );
			if( *plb != 0 )
				printf( ccbranches[*plb-EQ], lab);
			if( *++plb != 0 )
				printf( ccbranches[*plb-EQ], lab1f);
			expand( brnode, FORCC, "\tcmp\tAL,AR\n" );
			printf( ccbranches[*++plb-EQ], lab);
			deflab( lab1f );
			reclaim( brnode, RNULL, 0 );
			break;

		default:
			if( mode=='F' ) o = fcc[ o-EQ ];
			printf( ccbranches[o-EQ], lab );
			break;
			}

		brcase = 0;
		brnode = 0;
		}
	}

nextcook( p, cookie ) NODE *p; {
	/* we have failed to match p with cookie; try another */
	if( cookie == FORREW ) return( 0 );  /* hopeless! */
	if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG|INAREG|INBREG );
	if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG );
	return( FORREW );
	}

lastchance( p, cook ) NODE *p; {
	if (cook == FORARG) {
	  order ( p, p->in.type==DOUBLE ? INTEMP : INTAREG );
	  return(1);
	}

	/* forget it! */
	return(0);
	}

struct functbl {
	int fop;
	TWORD ftype;
	char *func;
	} opfunc[] = {
	MUL,		LONG,	"lmul",
	DIV,		LONG,	"ldiv",
	MOD,		LONG,	"lrem",
	ASG MUL,	LONG,	"almul",
	ASG DIV,	LONG,	"aldiv",
	ASG MOD,	LONG,	"alrem",
	MUL,		ULONG,	"lmul",
	DIV,		ULONG,	"uldiv",
	MOD,		ULONG,	"ulrem",
	ASG MUL,	ULONG,	"almul",
	ASG DIV,	ULONG,	"auldiv",
	ASG MOD,	ULONG,	"aulrem",
#ifndef X8087
	PLUS,		DOUBLE,	"fadd",
	MINUS,		DOUBLE, "fsub",
	MUL,		DOUBLE, "fmul",
	DIV,		DOUBLE, "fdiv",
	UNARY MINUS,	DOUBLE, "fneg",
	UNARY MINUS,	FLOAT,	"fneg",
	ASG PLUS,	DOUBLE,	"afadd",
	ASG MINUS,	DOUBLE, "afsub",
	ASG MUL,	DOUBLE, "afmul",
	ASG DIV,	DOUBLE, "afdiv",
	ASG PLUS,	FLOAT,	"afaddf",
	ASG MINUS,	FLOAT,	"afsubf",
	ASG MUL,	FLOAT,	"afmulf",
	ASG DIV,	FLOAT,	"afdivf",
#endif
	0,	0,	0 };

hardops(p)  register NODE *p; {
	/* change hard to do operators into function calls.
	   for pdp11 do long * / %	*/
	register NODE *q;
	register struct functbl *f;
	register o;
	register TWORD t;

	o = p->in.op;
	t = p->in.type;
	if( t!=LONG && t!=ULONG && t!=DOUBLE && t!=FLOAT) return;

	if (o==SCONV) { hardconv(p); return; }

	for( f=opfunc; f->fop; f++ ) {
		if( o==f->fop && t==f->ftype ) goto convert;
		}
	return;

	/* need address of left node for ASG OP */
	/* WARNING - this won't work for long in a REG */
	convert:
	if( asgop( o ) ) {
		switch( p->in.left->in.op ) {

		case UNARY MUL:	/* convert to address */
			p->in.left->in.op = FREE;
			p->in.left = p->in.left->in.left;
			break;

		case NAME:	/* convert to ICON pointer */
			p->in.left->in.op = ICON;
			p->in.left->in.type = INCREF( p->in.left->in.type );
			break;

		case OREG:	/* convert OREG to address */
			p->in.left->in.op = REG;
			p->in.left->in.type = INCREF( p->in.left->in.type );
			if( p->in.left->tn.lval != 0 ) {
				q = talloc();
				q->in.op = PLUS;
				q->in.rall = NOPREF;
				q->in.type = p->in.left->in.type;
				q->in.left = p->in.left;
				q->in.right = talloc();

				q->in.right->in.op = ICON;
				q->in.right->in.rall = NOPREF;
				q->in.right->in.type = INT;
				q->in.right->in.name[0] = '\0';
				q->in.right->tn.lval = p->in.left->tn.lval;
				q->in.right->tn.rval = 0;

				p->in.left->tn.lval = 0;
				p->in.left = q;
				}
			break;


		/* rewrite "foo <op>= bar" as "foo = foo <op> bar" for foo in a reg */
		case REG:
			q = talloc();
			q->in.op = p->in.op - 1;	/* change <op>= to <op> */
			q->in.rall = p->in.rall;
			q->in.type = p->in.type;
			q->in.left = talloc();
			q->in.right = p->in.right;
			p->in.op = ASSIGN;
			p->in.right = q;
			q = q->in.left;			/* make a copy of "foo" */
			q->in.op = p->in.left->in.op;
			q->in.rall = p->in.left->in.rall;
			q->in.type = p->in.left->in.type;
			q->tn.lval = p->in.left->tn.lval;
			q->tn.rval = p->in.left->tn.rval;
			hardops(p->in.right);
			return;

		default:
			cerror( "Bad address for hard ops" );
			/* NO RETURN */

			}
		}

	/* build comma op for args to function */
	if ( optype(p->in.op) == BITYPE ) {
	  q = talloc();
	  q->in.op = CM;
	  q->in.rall = NOPREF;
	  q->in.type = INT;
	  q->in.left = p->in.left;
	  q->in.right = p->in.right;
	} else q = p->in.left;

	p->in.op = CALL;
	p->in.right = q;

	/* put function name in left node of call */
	p->in.left = q = talloc();
	q->in.op = ICON;
	q->in.rall = NOPREF;
	q->in.type = INCREF( FTN + p->in.type );
	strcpy( q->in.name, f->func );
	q->tn.lval = 0;
	q->tn.rval = 0;
	return;

	}

/* do fix and float conversions */
hardconv(p)
  register NODE *p;
  {	register NODE *q;
	register TWORD t,tl;
	int m,ml;

	t = p->in.type;
	tl = p->in.left->in.type;

	m = t==DOUBLE || t==FLOAT;
	ml = tl==DOUBLE || tl==FLOAT;

	if (m==ml) return;

#ifndef X8087
	p->in.op = CALL;
	p->in.right = p->in.left;

	/* put function name in left node of call */
	p->in.left = q = talloc();
	q->in.op = ICON;
	q->in.rall = NOPREF;
	q->in.type = INCREF( FTN + p->in.type );
	strcpy( q->tn.name, m ? "float" : "fix" );
	q->tn.lval = 0;
	q->tn.rval = 0;
#endif
}

/* return 1 if node is a SCONV from short to int */
shortconv( p )
  register NODE *p;
  {	if ( p->in.op==SCONV && p->in.type==INT && p->in.left->in.type==SHORT)
	  return( 1 );
	return( 0 );
}

/* do local tree transformations and optimizations */
optim2( p )
  register NODE *p;
  {	register NODE *q;
#ifndef X8087
	/* change <flt exp>1 <logop> <flt exp>2 to
	 * (<exp>1 - <exp>2) <logop> 0.0
	 */
	if (logop(p->in.op) &&
	    ((q = p->in.left)->in.type==FLOAT || q->in.type==DOUBLE) &&
	    ((q = p->in.right)->in.type==FLOAT || q->in.type==DOUBLE)) {
	  q = talloc();
	  q->in.op = MINUS;
	  q->in.rall = NOPREF;
	  q->in.type = DOUBLE;
	  q->in.left = p->in.left;
	  q->in.right = p->in.right;
	  p->in.left = q;
	  p->in.right = q = talloc();
	  q->tn.op = ICON;
	  q->tn.type = DOUBLE;
	  q->tn.name[0] = '\0';
	  q->tn.rval = 0;
	  q->tn.lval = 0;
	}
#endif
}

myreader(p) register NODE *p; {
	walkf( p, optim2 );
	walkf( p, hardops );	/* convert ops to function calls */
	canon( p );		/* expands r-vals for fileds */
	toff = 0;  /* stack offset swindle */
	}

special( p, shape ) register NODE *p; {
	/* special shape matching routine */

	switch( shape ) {

	case SXCON:
		if (p->in.op==ICON && p->in.name[0]=='\0') return(1);
		break;

	case SCCON:
		if( p->in.op == ICON && p->in.name[0]=='\0' && p->tn.lval>= -128 && p->tn.lval <=127 ) return( 1 );
		break;

	case SICON:
		if( p->in.op == ICON && p->in.name[0]=='\0' && p->tn.lval>= -32768 && p->tn.lval <=32767 ) return( 1 );
		break;

	default:
		cerror( "bad special shape" );

		}

	return( 0 );
	}

# ifndef ONEPASS
main( argc, argv ) char *argv[]; {
	return( mainp2( argc, argv ) );
	}
# endif

# ifdef MULTILEVEL
# include "mldec.h"

struct ml_node mltree[] ={

DEFINCDEC,	INCR,	0,
	INCR,	SANY,	TANY,
		OPANY,	SAREG|STAREG,	TANY,
		OPANY,	SCON,	TANY,

DEFINCDEC,	ASG MINUS,	0,
	ASG MINUS,	SANY,	TANY,
		REG,	SANY,	TANY,
		ICON,	SANY,	TANY,

TSOREG,	1,	0,
	UNARY MUL,	SANY,	TANY,
		REG,	SANY,	TANY,

TSOREG,	2,	0,
	UNARY MUL,	SANY,	TANY,
		PLUS,	SANY,	TANY,
			REG,	SANY,	TANY,
			ICON,	SANY,	TCHAR|TUCHAR|TSHORT|TUSHORT|TINT|TUNSIGNED|TPOINT,

TSOREG,	2,	0,
	UNARY MUL,	SANY,	TANY,
		MINUS,	SANY,	TANY,
			REG,	SANY,	TANY,
			ICON,	SANY,	TCHAR|TUCHAR|TSHORT|TUSHORT|TINT|TUNSIGNED|TPOINT,
0,0,0};
# endif
,	TANY,
		OPANY,	SAREG|STAREG,	TAc86/match.c                                                                                            444      26      12        32003  3226573753   5750                                                                                                                                                                                                                                                                                                                                                                      # include "mfile2"

extern xdebug;

int fldsz, fldshf;

static int mamask[] = { /* masks for matching dope with shapes */
	SIMPFLG,		/* OPSIMP */
	SIMPFLG|ASGFLG,		/* ASG OPSIMP */
	COMMFLG,	/* OPCOMM */
	COMMFLG|ASGFLG,	/* ASG OPCOMM */
	MULFLG,		/* OPMUL */
	MULFLG|ASGFLG,	/* ASG OPMUL */
	DIVFLG,		/* OPDIV */
	DIVFLG|ASGFLG,	/* ASG OPDIV */
	UTYPE,		/* OPUNARY */
	TYFLG,		/* ASG OPUNARY is senseless */
	LTYPE,		/* OPLEAF */
	TYFLG,		/* ASG OPLEAF is senseless */
	0,		/* OPANY */
	ASGOPFLG|ASGFLG,	/* ASG OPANY */
	LOGFLG,		/* OPLOG */
	TYFLG,		/* ASG OPLOG is senseless */
	FLOFLG,		/* OPFLOAT */
	FLOFLG|ASGFLG,	/* ASG OPFLOAT */
	SHFFLG,		/* OPSHFT */
	SHFFLG|ASGFLG,	/* ASG OPSHIFT */
	SPFLG,		/* OPLTYPE */
	TYFLG,		/* ASG OPLTYPE is senseless */
	};

int sdebug = 0;

tshape( p, shape ) NODE *p; {
	/* return true if shape is appropriate for the node p
	   side effect for SFLD is to set up fldsz,etc */
	register o, mask;

	o = p->in.op;

	if( sdebug ){
		printf( "tshape( %o, %o), op = %d\n", p, shape, o );
		}

	if( shape & SPECIAL ){

		switch( shape ){

		case SZERO:
		case SONE:
		case SMONE:
			if( o != ICON || p->in.name[0] ) return(0);
			if( p->tn.lval == 0 && shape == SZERO ) return(1);
			else if( p->tn.lval == 1 && shape == SONE ) return(1);
			else if( p->tn.lval == -1 && shape == SMONE ) return(1);
			else return(0);

		default:
# ifdef MULTILEVEL
			if( shape & MULTILEVEL )
				return( mlmatch(p,shape,0) );
			else
# endif
			return( special( p, shape ) );
			}
		}

	if( shape & SANY ) return(1);

	if( (shape&INTEMP) && shtemp(p) ) return(1);

	if( (shape&SWADD) && (o==NAME||o==OREG) ){
		if( BYTEOFF(p->tn.lval) ) return(0);
		}

	switch( o ){

	case NAME:
		return( shape&SNAME );
	case ICON:
		mask = SCON;
		return( shape & mask );

	case FLD:
		if( shape & SFLD ){
			if( !flshape( p->in.left ) ) return(0);
			/* it is a FIELD shape; make side-effects */
			o = p->tn.rval;
			fldsz = UPKFSZ(o);
# ifdef RTOLBYTES
			fldshf = UPKFOFF(o);
# else
			fldshf = SZINT - fldsz - UPKFOFF(o);
# endif
			return(1);
			}
		return(0);

	case CCODES:
		return( shape&SCC );

	case REG:
		/* distinctions:
		SAREG	any scalar register
		STAREG	any temporary scalar register
		SBREG	any lvalue (index) register
		STBREG	any temporary lvalue register
		*/
		mask = isbreg( p->tn.rval ) ? SAREG|SBREG : SAREG;
		if( istreg( p->tn.rval ) && busy[p->tn.rval]<=1 ) mask |= mask==SAREG ? STAREG : STBREG|STAREG;
		return( shape & mask );

	case OREG:
		return( shape & SOREG );

	case UNARY MUL:
		/* return STARNM or STARREG or 0 */
		return( shumul(p->in.left) & shape );

		}

	return(0);
	}

int tdebug = 0;

ttype( t, tword ) TWORD t; {
	/* does the type t match tword */

	if( tword & TANY ) return(1);

	if( tdebug ){
		printf( "ttype( %o, %o )\n", t, tword );
		}
	if( ISPTR(t) && (tword&TPTRTO) ) {
		do {
			t = DECREF(t);
		} while ( ISARY(t) );
			/* arrays that are left are usually only
			   in structure references... */
		return( ttype( t, tword&(~TPTRTO) ) );
		}
	if( t != BTYPE(t) ) return( tword & TPOINT ); /* TPOINT means not simple! */
	if( tword & TPTRTO ) return(0);

	switch( t ){

	case CHAR:
		return( tword & TCHAR );
	case SHORT:
		return( tword & TSHORT );
	case STRTY:
	case UNIONTY:
		return( tword & TSTRUCT );
	case INT:
		return( tword & TINT );
	case UNSIGNED:
		return( tword & TUNSIGNED );
	case USHORT:
		return( tword & TUSHORT );
	case UCHAR:
		return( tword & TUCHAR );
	case ULONG:
		return( tword & TULONG );
	case LONG:
		return( tword & TLONG );
	case FLOAT:
		return( tword & TFLOAT );
	case DOUBLE:
		return( tword & TDOUBLE );
		}

	return(0);
	}

struct optab *rwtable;

struct optab *opptr[DSIZE];

setrew(){
	/* set rwtable to first value which allows rewrite */
	register struct optab *q;
	register int i;

# ifdef MULTILEVEL
	/* also initialize multi-level tree links */
	mlinit();
# endif

	for( q = table; q->op != FREE; ++q ){
		if( q->needs == REWRITE ){
			rwtable = q;
			goto more;
			}
		}
	cerror( "bad setrew" );


	more:
	for( i=0; i<DSIZE; ++i ){
		if( dope[i] ){ /* there is an op... */
			for( q=table; q->op != FREE; ++q ){
				/*  beware; things like LTYPE that match
				    multiple things in the tree must
				    not try to look at the NIL at this
				    stage of things!  Put something else
				    first in table.c  */
				/* at one point, the operator matching was 15% of the
				    total comile time; thus, the function
				    call that was here was removed...
				*/

				if( q->op < OPSIMP ){
					if( q->op==i ) break;
					}
				else {
					register opmtemp;
					if((opmtemp=mamask[q->op - OPSIMP])&SPFLG){
						if( i==NAME || i==ICON || i==OREG ) break;
						else if( shltype( i, NIL ) ) break;
						}
					else if( (dope[i]&(opmtemp|ASGFLG)) == opmtemp ) break;
					}
				}
			opptr[i] = q;
			}
		}
	}

match( p, cookie ) NODE *p; {
	/* called by: order, gencall
	   look for match in table and generate code if found unless
	   entry specified REWRITE.
	   returns MDONE, MNOPE, or rewrite specification from table */

	register struct optab *q;
	register NODE *r;

	rcount();
	if( cookie == FORREW ) q = rwtable;
	else q = opptr[p->in.op];

	for( ; q->op != FREE; ++q ){

		/* at one point the call that was here was over 15% of the total time;
		    thus the function call was expanded inline */
		if( q->op < OPSIMP ){
			if( q->op!=p->in.op ) continue;
			}
		else {
			register opmtemp;
			if((opmtemp=mamask[q->op - OPSIMP])&SPFLG){
				if( p->in.op!=NAME && p->in.op!=ICON && p->in.op!= OREG &&
					! shltype( p->in.op, p ) ) continue;
				}
			else if( (dope[p->in.op]&(opmtemp|ASGFLG)) != opmtemp ) continue;
			}

/* printf("match operator, cookie=0%o\n",cookie); */
		if( !(q->visit & cookie ) ) continue;
/* printf("match cookie\n"); */
		r = getlr( p, 'L' );			/* see if left child matches */
		if( !tshape( r, q->lshape ) ) continue;
/* printf("match left shape\n"); */
		if( !ttype( r->in.type, q->ltype ) ) continue;
/* printf("match left type\n"); */
		r = getlr( p, 'R' );			/* see if right child matches */
		if( !tshape( r, q->rshape ) ) continue;
/* printf("match right shape\n"); */
		if( !ttype( r->in.type, q->rtype ) ) continue;
/* printf("match right type\n"); */

			/* REWRITE means no code from this match but go ahead
			   and rewrite node to help future match */
		if( q->needs & REWRITE ) return( q->rewrite );
		if( !allo( p, q ) ) continue;			/* if can't generate code, skip entry */

		/* resources are available */

		expand( p, cookie, q->cstring );		/* generate code */
		reclaim( p, q->rewrite, cookie );

		return(MDONE);

		}

	return(MNOPE);
	}

int rtyflg = 0;

expand( p, cookie, cp ) register NODE *p;  register char *cp; {
	/* generate code by interpreting table entry */

	CONSZ val;

	rtyflg = 0;

	for( ; *cp; ++cp ){
		switch( *cp ){

		default:
			PUTCHAR( *cp );
			continue;  /* this is the usual case... */

		case 'T':
			/* rewrite register type is suppressed */
			rtyflg = 1;
			continue;

		case 'Z':  /* special machine dependent operations */
			zzzcode( p, *++cp );
			continue;

		case 'F':  /* this line deleted if FOREFF is active */
			if( cookie & FOREFF ) while( *++cp != '\n' ) ; /* VOID */
			continue;

		case 'S':  /* field size */
			printf( "%d", fldsz );
			continue;

		case 'H':  /* field shift */
			printf( "%d", fldshf );
			continue;

		case 'M':  /* field mask */
		case 'N':  /* complement of field mask */
			val = 1;
			val <<= fldsz;
			--val;
			val <<= fldshf;
			adrcon( *cp=='M' ? val : ~val );
			continue;

		case 'L':  /* output special label field */
			printf( "%d", p->bn.label );
			continue;

		case 'O':  /* opcode string */
			hopcode( *++cp, p->in.op );
			continue;

		case 'B':  /* byte offset in word */
			val = getlr(p,*++cp)->tn.lval;
			val = BYTEOFF(val);
			printf( CONFMT, val );
			continue;

		case 'C': /* for constant value only */
			conput( getlr( p, *++cp ) );
			continue;

		case 'I': /* in instruction */
			insput( getlr( p, *++cp ) );
			continue;

		case 'A': /* address of */
			adrput( getlr( p, *++cp ) );
			continue;

		case 'U': /* for upper half of address, only */
			upput( getlr( p, *++cp ) );
			continue;

			}

		}

	}

NODE *
getlr( p, c ) NODE *p; {

	/* return the pointer to the left or right side of p, or p itself,
	   depending on the optype of p */

	switch( c ) {

	case '1':
	case '2':
	case '3':
		return( &resc[c-'1'] );

	case 'L':
		return( optype( p->in.op ) == LTYPE ? p : p->in.left );

	case 'R':
		return( optype( p->in.op ) != BITYPE ? p : p->in.right );

		}
	cerror( "bad getlr: %c", c );
	/* NOTREACHED */
	}
# ifdef MULTILEVEL

union mltemplate{
	struct ml_head{
		int tag; /* identifies class of tree */
		int subtag; /* subclass of tree */
		union mltemplate * nexthead; /* linked by mlinit() */
		} mlhead;
	struct ml_node{
		int op; /* either an operator or op description */
		int nshape; /* shape of node */
		/* both op and nshape must match the node.
		 * where the work is to be done entirely by
		 * op, nshape can be SANY, visa versa, op can
		 * be OPANY.
		 */
		int ntype; /* type descriptor from mfile2 */
		} mlnode;
	};

# define MLSZ 30

extern union mltemplate mltree[];
int mlstack[MLSZ];
int *mlsp; /* pointing into mlstack */
NODE * ststack[MLSZ];
NODE **stp; /* pointing into ststack */

mlinit(){
	union mltemplate **lastlink;
	register union mltemplate *n;
	register mlop;

	lastlink = &(mltree[0].nexthead);
	n = &mltree[0];
	for( ; (n++)->mlhead.tag != 0;
		*lastlink = ++n, lastlink = &(n->mlhead.nexthead) ){
		if( xdebug )printf("mlinit: %d\n",(n-1)->mlhead.tag);
	/* wander thru a tree with a stack finding
	 * its structure so the next header can be located.
	 */
		mlsp = mlstack;

		for( ;; ++n ){
			if( (mlop = n->mlnode.op) < OPSIMP ){
				switch( optype(mlop) ){

					default:
						cerror("(1)unknown opcode: %o",mlop);
					case BITYPE:
						goto binary;
					case UTYPE:
						break;
					case LTYPE:
						goto leaf;
					}
				}
			else{
				if( mamask[mlop-OPSIMP] &
					(SIMPFLG|COMMFLG|MULFLG|DIVFLG|LOGFLG|FLOFLG|SHFFLG) ){
				binary:
					*mlsp++ = BITYPE;
					}
				else if( ! (mamask[mlop-OPSIMP] & UTYPE) ){/* includes OPANY */

				leaf:
					if( mlsp == mlstack )
						goto tree_end;
					else if ( *--mlsp != BITYPE )
						cerror("(1)bad multi-level tree descriptor around mltree[%d]",
						n-mltree);
					}
				}
			}
		tree_end: /* n points to final leaf */
		;
		}
		if( xdebug > 3 ){
			printf("mltree={\n");
			for( n= &(mltree[0]); n->mlhead.tag != 0; ++n)
				printf("%o: %d, %d, %o,\n",n,
				n->mlhead.tag,n->mlhead.subtag,n->mlhead.nexthead);
			printf("	}\n");
			}
	}

mlmatch( subtree, target, subtarget ) NODE * subtree; int target,subtarget;{
	/*
	 * does subtree match a multi-level tree with
	 * tag "target"?  Return zero on failure,
	 * non-zero subtag on success (or MDONE if
	 * there is a zero subtag field).
	 */
	union mltemplate *head; /* current template header */
	register union mltemplate *n; /* node being matched */
	NODE * st; /* subtree being matched */
	register int mlop;

	if( xdebug ) printf("mlmatch(%o,%d)\n",subtree,target);
	for( head = &(mltree[0]); head->mlhead.tag != 0;
		head=head->mlhead.nexthead){
		if( xdebug > 1 )printf("mlmatch head(%o) tag(%d)\n",
			head->mlhead.tag);
		if( head->mlhead.tag != target )continue;
		if( subtarget && head->mlhead.subtag != subtarget)continue;
		if( xdebug ) printf("mlmatch for %d\n",target);

		/* potential for match */

		n = head + 1;
		st = subtree;
		stp = ststack;
		mlsp = mlstack;
		/* compare n->op, ->nshape, ->ntype to
		 * the subtree node st
		 */
		for( ;; ++n ){ /* for each node in multi-level template */
			/* opmatch */
			if( n->op < OPSIMP ){
				if( st->op != n->op )break;
				}
			else {
				register opmtemp;
				if((opmtemp=mamask[n->op-OPSIMP])&SPFLG){
					if(st->op!=NAME && st->op!=ICON && st->op!=OREG && 
						! shltype(st->op,st)) break;
					}
				else if((dope[st->op]&(opmtemp|ASGFLG))!=opmtemp) break;
				}
			/* check shape and type */

			if( ! tshape( st, n->mlnode.nshape ) ) break;
			if( ! ttype( st->type, n->mlnode.ntype ) ) break;

			/* that node matched, let's try another */
			/* must advance both st and n and halt at right time */

			if( (mlop = n->mlnode.op) < OPSIMP ){
				switch( optype(mlop) ){

					default:
						cerror("(2)unknown opcode: %o",mlop);
					case BITYPE:
						goto binary;
					case UTYPE:
						st = st->left;
						break;
					case LTYPE:
						goto leaf;
					}
				}
			else{
				if( mamask[mlop - OPSIMP] &
					(SIMPFLG|COMMFLG|MULFLG|DIVFLG|LOGFLG|FLOFLG|SHFFLG) ){
				binary:
					*mlsp++ = BITYPE;
					*stp++ = st;
					st = st->left;
					}
				else if( ! (mamask[mlop-OPSIMP] & UTYPE) ){/* includes OPANY */

				leaf:
					if( mlsp == mlstack )
						goto matched;
					else if ( *--mlsp != BITYPE )
						cerror("(2)bad multi-level tree descriptor around mltree[%d]",
						n-mltree);
					st = (*--stp)->right;
					}
				else /* UNARY */ st = st->left;
				}
			continue;

			matched:
			/* complete multi-level match successful */
			if( xdebug ) printf("mlmatch() success\n");
			if( head->mlhead.subtag == 0 ) return( MDONE );
			else {
				if( xdebug )printf("\treturns %d\n",
					head->mlhead.subtag );
				return( head->mlhead.subtag );
				}
			}
		}
	return( 0 );
	}
# endif
if ( *--mlsp != BITYPE )
						cerror("(2)bad multi-level tree descriptor around mltree[%d]",
						n-mltree);
					st = (*--stp)->right;
					}
				else /* UNARY */ st = st->left;
				}
			continue;

			matched:
			/* complete multi-level match successful */
			if( xdebug ) printf("mlmatch() success\n");
			if( head->mlhead.subtag == 0 ) return( MDONE );
			else {
				if( xdebug )printf("\treturns %d\n",
					head->mlhead.subtag );
				return( head->mlhead.subtag );
				}
			}
		}
	return( 0 );
	}
# endc86/optim.c                                                                                            444      26      12         7507  2537050424   5764                                                                                                                                                                                                                                                                                                                                                                      # include "mfile1"

# define SWAP(p,q) {sp=p; p=q; q=sp;}
# define RCON(p) (p->in.right->in.op==ICON)
# define RO(p) p->in.right->in.op
# define RV(p) p->in.right->tn.lval
# define LCON(p) (p->in.left->in.op==ICON)
# define LO(p) p->in.left->in.op
# define LV(p) p->in.left->tn.lval

int oflag = 0;

NODE *
fortarg( p ) NODE *p; {
	/* fortran function arguments */

	if( p->in.op == CM ){
		p->in.left = fortarg( p->in.left );
		p->in.right = fortarg( p->in.right );
		return(p);
		}

	while( ISPTR(p->in.type) ){
		p = buildtree( UNARY MUL, p, NIL );
		}
	return( optim(p) );
	}

	/* mapping relationals when the sides are reversed */
short revrel[] ={ EQ, NE, GE, GT, LE, LT, UGE, UGT, ULE, ULT };
NODE *
optim(p) register NODE *p; {
	/* local optimizations, most of which are probably machine independent */

	register o, ty;
	NODE *sp;
	int i;
	TWORD t;

	if( (t=BTYPE(p->in.type))==ENUMTY || t==MOETY ) econvert(p);
	if( oflag ) return(p);
	ty = optype( o=p->in.op);
	if( ty == LTYPE ) return(p);

	if( ty == BITYPE ) p->in.right = optim(p->in.right);
	p->in.left = optim(p->in.left);

	/* collect constants */

	switch(o){

	case SCONV:
	case PCONV:
		return( clocal(p) );

	case FORTCALL:
		p->in.right = fortarg( p->in.right );
		break;

	case UNARY AND:
		if( LO(p) != NAME ) cerror( "& error" );

		if( !andable(p->in.left) ) return(p);

		LO(p) = ICON;

		setuleft:
		/* paint over the type of the left hand side with the type of the top */
		p->in.left->in.type = p->in.type;
		p->in.left->fn.cdim = p->fn.cdim;
		p->in.left->fn.csiz = p->fn.csiz;
		p->in.op = FREE;
		return( p->in.left );

	case UNARY MUL:
		if( LO(p) != ICON ) break;
		LO(p) = NAME;
		goto setuleft;

	case MINUS:
		if( !nncon(p->in.right) ) break;
		RV(p) = -RV(p);
		o = p->in.op = PLUS;

	case MUL:
	case PLUS:
	case AND:
	case OR:
	case ER:
		/* commutative ops; for now, just collect constants */
		/* someday, do it right */
		if( nncon(p->in.left) || ( LCON(p) && !RCON(p) ) ) SWAP( p->in.left, p->in.right );
		/* make ops tower to the left, not the right */
		if( RO(p) == o ){
			NODE *t1, *t2, *t3;
			t1 = p->in.left;
			sp = p->in.right;
			t2 = sp->in.left;
			t3 = sp->in.right;
			/* now, put together again */
			p->in.left = sp;
			sp->in.left = t1;
			sp->in.right = t2;
			p->in.right = t3;
			}
		if(o == PLUS && LO(p) == MINUS && RCON(p) && RCON(p->in.left) &&
		  conval(p->in.right, MINUS, p->in.left->in.right)){
			zapleft:
			RO(p->in.left) = FREE;
			LO(p) = FREE;
			p->in.left = p->in.left->in.left;
		}
		if( RCON(p) && LO(p)==o && RCON(p->in.left) && conval( p->in.right, o, p->in.left->in.right ) ){
			goto zapleft;
			}
		else if( LCON(p) && RCON(p) && conval( p->in.left, o, p->in.right ) ){
			zapright:
			RO(p) = FREE;
			p->in.left = makety( p->in.left, p->in.type, p->fn.cdim, p->fn.csiz );
			p->in.op = FREE;
			return( clocal( p->in.left ) );
			}

		/* change muls to shifts */

		if( o==MUL && nncon(p->in.right) && (i=ispow2(RV(p)))>=0){
			if( i == 0 ){ /* multiplication by 1 */
				goto zapright;
				}
			o = p->in.op = LS;
			p->in.right->in.type = p->in.right->fn.csiz = INT;
			RV(p) = i;
			}

		/* change +'s of negative consts back to - */
		if( o==PLUS && nncon(p->in.right) && RV(p)<0 ){
			RV(p) = -RV(p);
			o = p->in.op = MINUS;
			}
		break;

	case DIV:
		if( nncon( p->in.right ) && p->in.right->tn.lval == 1 ) goto zapright;
		break;

	case EQ:
	case NE:
	case LT:
	case LE:
	case GT:
	case GE:
	case ULT:
	case ULE:
	case UGT:
	case UGE:
		if( !LCON(p) ) break;

		/* exchange operands */

		sp = p->in.left;
		p->in.left = p->in.right;
		p->in.right = sp;
		p->in.op = revrel[p->in.op - EQ ];
		break;

		}

	return(p);
	}

ispow2( c ) CONSZ c; {
	register i;
	if( c <= 0 || (c&(c-1)) ) return(-1);
	for( i=0; c>1; ++i) c >>= 1;
	return(i);
	}

nncon( p ) NODE *p; {
	/* is p a constant without a name */
	return( p->in.op == ICON && p->tn.rval == NONAME );
	}
NE:
	case LT:
	case LE:
	case GT:
	case GE:
	case ULT:
	case ULE:
	case UGT:
	case UGE:
		if( !LCON(p) ) break;

		/* exchange operands */

		sp = p->in.left;
		p->in.left = p->in.rightc86/order.c                                                                                            444      26      12        42044  3330045431   5754                                                                                                                                                                                                                                                                                                                                                                      # include "mfile2"

int fltused = 0;

stoasg( p, o ) register NODE *p; {
	/* should the assignment op p be stored,
	   given that it lies as the right operand of o
	   (or the left, if o==UNARY MUL) */
	return( shltype(p->in.left->in.op, p->in.left ) );

	}

deltest( p ) register NODE *p; {
	/* should we delay the INCR or DECR operation p */
# ifndef MULTILEVEL
	if( p->in.op == INCR && p->in.left->in.op == REG && spsz( p->in.left->in.type, p->in.right->tn.lval ) ){
		/* STARREG */
		return( 0 );
		}
# else
	if( mlmatch(p,DEFINCDEC,INCR) && spsz( p->in.left->in.type, p->in.right->tn.lval ) ){
		/* STARREG */
		return( 0 );
		}
# endif

	p = p->in.left;
	if( p->in.op == UNARY MUL ) p = p->in.left;
	return( p->in.op == NAME || p->in.op == OREG || p->in.op == REG );
	}

mkadrs(p) register NODE *p; {
	register o;

	o = p->in.op;

	if( asgop(o) ){
		if( p->in.left->in.su >= p->in.right->in.su ){
			if( p->in.left->in.op == UNARY MUL ){
				if( p->in.right->in.su > 0 )
					SETSTO( p->in.right, INTEMP );
				else {
					if( p->in.left->in.su > 0 ) 
						SETSTO( p->in.left->in.left, INTEMP );
					else cerror( "store finds both sides trivial" );
					}
				}
			else if( p->in.left->in.op == FLD && p->in.left->in.left->in.op == UNARY MUL ){
				SETSTO( p->in.left->in.left->in.left, INTEMP );
				}
			else { /* should be only structure assignment */
				SETSTO( p->in.left, INTEMP );
				}
			}
		else SETSTO( p->in.right, INTEMP );
		}
	else {
		if( p->in.left->in.su > p->in.right->in.su ){
			SETSTO( p->in.left, INTEMP );
			}
		else {
			SETSTO( p->in.right, INTEMP );
			}
		}
	}

notoff( t, r, off, cp) TWORD t; CONSZ off; char *cp; {
	/* is it legal to make an OREG or NAME entry which has an
	/* offset of off, (from a register of r), if the
	/* resulting thing had type t */

	/* return( 1 );  /* NO */
	return(0);  /* YES */
	}

# define max(x,y) ((x)<(y)?(y):(x))
# define min(x,y) ((x)<(y)?(x):(y))


# define ZCHAR 01
# define ZLONG 02
# define ZFLOAT 04

zum( p, zap ) register NODE *p; {
	/* zap Sethi-Ullman number for chars, longs, floats */
	/* in the case of longs, only STARNM's are zapped */
	/* ZCHAR, ZLONG, ZFLOAT are used to select the zapping */

	register su;

	su = p->in.su;

	switch( p->in.type ){

	case CHAR:
	case UCHAR:
		if( !(zap&ZCHAR) ) break;
		if( su == 0 ) p->in.su = su = 1;
		break;

	case LONG:
	case ULONG:
		if( !(zap&ZLONG) ) break;
		if( p->in.op == UNARY MUL && su == 0 ) p->in.su = su = 2;
		break;

	case FLOAT:
		if( !(zap&ZFLOAT) ) break;
		if( su == 0 ) p->in.su = su = 1;

		}

	return( su );
	}

sucomp( p ) register NODE *p; {

	/* set the su field in the node to the sethi-ullman
	   number, or local equivalent */

	register o, ty, sul, sur;
	register nr;

	ty = optype( o=p->in.op);
	nr = szty( p->in.type );
	p->in.su = 0;

	if( ty == LTYPE ) return;
	else if( ty == UTYPE ){
		switch( o ) {
		case UNARY CALL:
		case UNARY STCALL:
			p->in.su = fregs;  /* all regs needed */
			return;

		case UNARY MUL:
			if( shumul( p->in.left ) ) { p->in.su = 1; return; }

		default:
			p->in.su = max( p->in.left->in.su, nr);
			return;
			}
		}


	/* If rhs needs n, lhs needs m, regular su computation */

	sul = p->in.left->in.su;
	sur = p->in.right->in.su;

	if( o == ASSIGN ){
		asop:  /* also used for +=, etc., to memory */
/* This is for *p = *q where p,q are (long *) */

		if((p->in.left->in.op == UNARY MUL))
			if((p->in.left->in.left->in.su == 0))
				sul = 1;


		if( sul==0 ){
			/* don't need to worry about the left side */
			p->in.su = max( sur, nr );
			}
		else {
			/* right, left address, op */
			if( sur == 0 ){
				/* just get the lhs address into a register, and mov */
				/* the `nr' covers the case where value is in reg afterwards */
				p->in.su = max( sul, nr );
				}
			else {
				/* right, left address, op */
				p->in.su = max( sur, nr+sul );
				}
			}
		return;
		}

	if( o == CALL || o == STCALL ){
		/* in effect, takes all free registers */
		p->in.su = fregs;
		return;
		}

	if( o == STASG ){
		/* right, then left */
		p->in.su = max( max( sul+nr, sur), fregs );
		return;
		}

	if( logop(o) ){
		/* do the harder side, then the easier side, into registers */
		/* left then right, max(sul,sur+nr) */
		/* right then left, max(sur,sul+nr) */
		/* to hold both sides in regs: nr+nr */
		nr = szty( p->in.left->in.type );
		sul = zum( p->in.left, ZLONG|ZCHAR );
		sur = zum( p->in.right, ZLONG|ZCHAR );
		p->in.su = min( max(sul,sur+nr), max(sur,sul+nr) );
		return;
		}

	if( asgop(o) ){
		/* computed by doing right, doing left address, doing left, op, and store */
		switch( o ) {
		case INCR:
		case DECR:
			/* do as binary op */
			break;

		case ASG DIV:
		case ASG MOD:
		case ASG MUL:
			if( p->in.type!=FLOAT && p->in.type!=DOUBLE ) nr = fregs;
			goto gencase;

		case ASG PLUS:
		case ASG MINUS:
		case ASG AND:  /* really bic */
		case ASG OR:
			if( p->in.type == INT || p->in.type == UNSIGNED || ISPTR(p->in.type) ) goto asop;

		gencase:
		default:
			sur = zum( p->in.right, ZCHAR|ZLONG );
			if( sur == 0 ){ /* easy case: if addressable,
				do left value, op, store */
				if( sul == 0 ) p->in.su = nr;
				/* harder: left adr, val, op, store */
				else p->in.su = max( sul, nr+1 );
				}
			else { /* do right, left adr, left value, op, store */
				if( sul == 0 ){  /* right, left value, op, store */
					p->in.su = max( sur, nr+nr );
					}
				else {
					p->in.su = max( sur, max( sul+nr, 1+nr+nr ) );
					}
				}
			return;
			}
		}

	switch( o ){
	case ANDAND:
	case OROR:
	case QUEST:
	case COLON:
	case COMOP:
		p->in.su = max( max(sul,sur), nr);
		return;
		}

	if( ( o==DIV || o==MOD || o==MUL )
	    && p->in.type!=FLOAT && p->in.type!=DOUBLE ) nr = fregs;
	if( o==PLUS || o==MUL || o==OR || o==ER ){
		/* AND is ruined by the hardware */
		/* permute: get the harder on the left */

		register rt, lt;

		if( istnode( p->in.left ) || sul > sur ) goto noswap;  /* don't do it! */

		/* look for a funny type on the left, one on the right */


		lt = p->in.left->in.type;
		rt = p->in.right->in.type;

		if( rt == FLOAT && lt == DOUBLE ) goto swap;

		if( (rt==CHAR||rt==UCHAR) && (lt==INT||lt==UNSIGNED||ISPTR(lt)) ) goto swap;

		if( lt==LONG || lt==ULONG ){
			if( rt==LONG || rt==ULONG ){
				/* if one is a STARNM, swap */
				if( p->in.left->in.op == UNARY MUL && sul==0 ) goto noswap;
				if( p->in.right->in.op == UNARY MUL && p->in.left->in.op != UNARY MUL ) goto swap;
				goto noswap;
				}
			else if( p->in.left->in.op == UNARY MUL && sul == 0 ) goto noswap;
			else goto swap;  /* put long on right, unless STARNM */
			}

		/* we are finished with the type stuff now; if one is addressable,
			put it on the right */
		if( sul == 0 && sur != 0 ){

			NODE *s;
			int ssu;

		swap:
			ssu = sul;  sul = sur; sur = ssu;
			s = p->in.left;  p->in.left = p->in.right; p->in.right = s;
			}
		}
	noswap:

	sur = zum( p->in.right, ZCHAR|ZLONG|ZFLOAT );
	if( sur == 0 ){
		/* get left value into a register, do op */
		p->in.su = max( nr, sul );
		}
	else {
		/* do harder into a register, then easier */
		p->in.su = max( nr+nr, min( max( sul, nr+sur ), max( sur, nr+sul ) ) );
		}
	}

int radebug = 0;

mkrall( p, r ) register NODE *p; {
	/* insure that the use of p gets done with register r; in effect, */
	/* simulate offstar */

	if( p->in.op == FLD ){
		p->in.left->in.rall = p->in.rall;
		p = p->in.left;
		}

	if( p->in.op != UNARY MUL ) return;  /* no more to do */
	p = p->in.left;
	if( p->in.op == UNARY MUL ){
		p->in.rall = r;
		p = p->in.left;
		}
	if( p->in.op == PLUS && p->in.right->in.op == ICON ){
		p->in.rall = r;
		p = p->in.left;
		}
	rallo( p, r );
	}

rallo( p, down ) register NODE *p; {
	/* do register allocation */
	register o, type, down1, down2, ty;

	if( radebug ) printf( "rallo( %o, %o )\n", p, down );

	down2 = NOPREF;
	p->in.rall = down;
	down1 = ( down &= ~MUSTDO );

	ty = optype( o = p->in.op );
	type = p->in.type;


	if( type == DOUBLE || type == FLOAT ){
		if( o == FORCE ) down1 = AX|MUSTDO;
		++fltused;
		}
	else switch( o ) {
	case ASSIGN:	
		down1 = NOPREF;
		down2 = down;
		break;

	case ASG MUL:
		rallo( p->in.left, AX|MUSTDO );
		rallo( p->in.right, NOPREF );
		return;

	case ASG DIV:
	case ASG MOD:
		/* keep the addresses out of the hair of (r0,r1) */
		if(fregs == 2 ){
			/* lhs in (r0,r1), nothing else matters */
			down1 = AX|MUSTDO;
			down2 = NOPREF;
			break;
			}
		/* at least 3 regs free */
		/* compute lhs in (r0,r1), address of left in r2 */
		p->in.left->in.rall = AX|MUSTDO;
		mkrall( p->in.left, AX|MUSTDO );
		/* now, deal with right */
		if( fregs == 3 ) rallo( p->in.right, NOPREF );
		else {
			/* put address of long or value here */
			p->in.right->in.rall = BX|MUSTDO;
			mkrall( p->in.right, BX|MUSTDO );
			}
		return;

	case MUL:
		rallo( p->in.left, AX|MUSTDO );
		rallo( p->in.right, NOPREF );
		return;

	case DIV:
	case MOD:
		rallo( p->in.left, AX|MUSTDO );

		if( fregs == 2 ){
			rallo( p->in.right, NOPREF );
			return;
			}
		/* compute addresses, stay away from (r0,r1) */

		p->in.right->in.rall = BX|MUSTDO;
		mkrall( p->in.right, BX|MUSTDO );
		return;

	case CALL:
	case STASG:
	case EQ:
	case NE:
	case GT:
	case GE:
	case LT:
	case LE:
	case NOT:
	case ANDAND:
	case OROR:
		down1 = NOPREF;
		break;

	case FORCE:	
		down1 = AX|MUSTDO;
		break;

		}

	if( ty != LTYPE ) rallo( p->in.left, down1 );
	if( ty == BITYPE ) rallo( p->in.right, down2 );

	}

offstar( p ) register NODE *p; {
	/* handle indirections */

	if( p->in.op == UNARY MUL ) p = p->in.left;

	if( p->in.op == PLUS || p->in.op == MINUS ){
		if( p->in.right->in.op == ICON ){
			order( p->in.left , INTBREG|INBREG );
			return;
			}
		}
	order( p, INTBREG|INBREG );
	}

setincr( p ) NODE *p; {
	return( 0 );	/* for the moment, don't bother */
	}

niceuty( p ) register NODE *p; {
	register TWORD t;

	return( p->in.op == UNARY MUL && (t=p->in.type)!=CHAR &&
		t!= UCHAR && t!= FLOAT &&
		shumul( p->in.left) != STARREG );
	}

setbin( p ) register NODE *p; {
	register NODE *r, *l;

	r = p->in.right;
	l = p->in.left;

	if( p->in.right->in.su == 0 ){ /* rhs is addressable */
		if( logop( p->in.op ) ){
			if( l->in.op == UNARY MUL && l->in.type != FLOAT && shumul( l->in.left ) != STARREG ) offstar( l->in.left );
			else order( l, INAREG|INTAREG|INTEMP );
			return( 1 );
			}
		if( !istnode( l ) ){
			if ( shltype(l->in.op,l) ) order( l, INTAREG|INTEMP );
			else order( l, INAREG|INTAREG|INTEMP );
			return( 1 );
			}
		/* rewrite */
		return( 0 );
		}
	/* now, rhs is complicated: must do both sides into registers */
	/* do the harder side first */

	if( logop( p->in.op ) ){
		/* relational: do both sides into regs if need be */

		if( r->in.su > l->in.su ){
			if( niceuty(r) && l->in.su==0 ){
				offstar( r->in.left );
				return( 1 );
				}
			else if( !istnode( r ) ){
				order( r, INAREG|INTAREG|INTEMP );
				return( 1 );
				}
			}
		if( niceuty(l) && r->in.su==0){
			offstar( l->in.left );
			return( 1 );
			}
		else if( !istnode( l ) ){
			order( l, INAREG|INTAREG|INTEMP );
			return( 1 );
			}
		else if( niceuty(r) && l->in.su==0) {
			offstar( r->in.left );
			return( 1 );
			}
		else if( !istnode( r ) ){
			order( r, INAREG|INTAREG|INTEMP );
			return( 1 );
			}
		cerror( "setbin can't deal with %s", opst[p->in.op] );
		}

	/* ordinary operator */

	if( !istnode(r) && r->in.su > l->in.su ){
		/* if there is a chance of making it addressable, try it... */
		if( niceuty(r) && l->in.su==0 ){
			offstar( r->in.left );
			return( 1 );  /* hopefully, it is addressable by now */
			}
		order( r, INAREG|INTAREG|INTEMP );  /* anything goes on rhs */
		return( 1 );
		}
	else {
		if( !istnode( l ) ){
			order( l, INAREG|INTAREG|INTEMP );
			return( 1 );
			}
		/* rewrite */
		return( 0 );
		}
	}

setstr( p ) register NODE *p; { /* structure assignment */
	register NODE *q;

	if( p->in.right->in.su != 0 ){
		order( p->in.right, INAREG|INBREG );
		return(1);
		}

	q = p->in.left;
	if( q->in.op != NAME && q->in.op != OREG ){
		if( q->in.op != UNARY MUL ) cerror( "bad setstr" );
		if( q->in.left->in.su != 0 ) order( q->in.left, INAREG|INBREG );
		p->in.left = q->in.left;
		q->in.op = FREE;
		return( 1 );
		}
	return( 0 );
	}

setasg( p ) register NODE *p; {
	/* setup for assignment operator */

	if (p->in.type == DOUBLE || p->in.type == FLOAT) {
	  if (p->in.right->in.su != 0) { order( p->in.right, INTEMP ); return(1); }
	} else if( p->in.right->in.su != 0 && p->in.right->in.op != REG ) {
		if( p->in.right->in.op == UNARY MUL && p->in.left->in.su==0 )
			offstar( p->in.right->in.left );
		else if (p->in.left->in.su == 0)
			order( p->in.right, INAREG|SOREG|SNAME|SCON );
		else order( p->in.right, INAREG|SNAME|SCON );
		return(1);
		}

	if( p->in.left->in.op == UNARY MUL /* && !tshape( p->in.left, STARREG|STARNM )*/ ){
		offstar( p->in.left /* ->in.left */ );
		return(1);
		}
	if( p->in.left->in.op == FLD && p->in.left->in.left->in.op == UNARY MUL ){
		offstar( p->in.left->in.left->in.left );
		return(1);
		}
	/* if things are really strange, get rhs into a register */
	if( p->in.right->in.op != REG ){
		order( p->in.right, INAREG|INBREG );
		return( 1 );
		}
	return(0);
	}

setasop( p ) register NODE *p; {
	/* setup for =ops */
	register sul, sur;
	register NODE *q, *p2;

	sul = p->in.left->in.su;
	sur = p->in.right->in.su;

	switch( p->in.op ){
	case ASG MUL:
	case ASG DIV:
	case ASG MOD:
		if( p->in.type != INT && p->in.type != UNSIGNED && !ISPTR(p->in.type) ) break;
		if( !istnode(p->in.left) ) break;/*return ( 0 );*/
		if( p->in.right->in.type == ICON || p->in.right->in.type == CHAR || p->in.right->in.type == UCHAR ){
			order( p->in.right, INAREG );
			return( 1 );
			}
		break;

	case ASG AND:
	case ASG ER:
	case ASG PLUS:
	case ASG OR:
	case ASG MINUS:
		if( p->in.type != INT && p->in.type != UNSIGNED && !ISPTR(p->in.type) ) break;
		if( p->in.right->in.type == CHAR || p->in.right->in.type == UCHAR ){
			order( p->in.right, INAREG );
			return( 1 );
			}
		if (sul == 0) { order( p->in.right, INAREG ); return( 1 ); }
		break;
	}

	if( sur == 0 ){

	leftadr:
		/* easy case: if addressable, do left value, op, store */
		if( sul == 0 ) goto rew;  /* rewrite */

		/* harder; make aleft address, val, op, and store */

		if( p->in.left->in.op == UNARY MUL ){
			offstar( p->in.left->in.left );
			return( 1 );
			}
		if( p->in.left->in.op == FLD && p->in.left->in.left->in.op == UNARY MUL ){
			offstar( p->in.left->in.left->in.left );
			return( 1 );
			}
	rew:	/* rewrite, accounting for autoincrement and autodecrement */

		q = p->in.left;
		if( q->in.op == FLD ) q = q->in.left;
		if( q->in.op != UNARY MUL || shumul(q->in.left) != STARREG ) return(0); /* let reader.c do it */

		/* mimic code from reader.c */

		p2 = tcopy( p );
		p->in.op = ASSIGN;
		reclaim( p->in.right, RNULL, 0 );
		p->in.right = p2;

		/* now, zap INCR on right, ASG MINUS on left */

		if( q->in.left->in.op == INCR ){
			q = p2->in.left;
			if( q->in.op == FLD ) q = q->in.left;
			if( q->in.left->in.op != INCR ) cerror( "bad incr rewrite" );
			}
		else if( q->in.left->in.op != ASG MINUS )  cerror( " bad -= rewrite" );

		q->in.left->in.right->in.op = FREE;
		q->in.left->in.op = FREE;
		q->in.left = q->in.left->in.left;

		/* now, resume reader.c rewriting code */

		canon(p);
		rallo( p, p->in.rall );
		order( p2->in.left, INTBREG|INTAREG|INTEMP );
		order( p2, INTBREG|INTAREG|INTEMP );
		return( 1 );
		}

	/* harder case: do right, left address, left value, op, store */

	if( p->in.right->in.op == UNARY MUL && p->in.left->in.su==0){
		offstar( p->in.right->in.left );
		return( 1 );
		}
	/* sur> 0, since otherwise, done above */
	if( p->in.right->in.op == REG ) goto leftadr;  /* make lhs addressable */
	order( p->in.right, INTEMP|INAREG|INBREG );
	return( 1 );
	}

int crslab = 10000;

getlab(){
	return( crslab++ );
	}

deflab( l ){
	printf( "L%d:\n", l );
	}

genargs( p) register NODE *p; {
	register size;

	/* generate code for the arguments */

	/*  first, do the arguments on the right (last->first) */
	while( p->in.op == CM ){
		genargs( p->in.right );
		p->in.op = FREE;
		p = p->in.left;
		}

	if( p->in.op == STARG ){ /* structure valued argument */

		size = p->stn.stsize;
		if( p->in.left->in.op == ICON ){
			/* make into a name node */
			p->in.op = FREE;
			p= p->in.left;
			p->in.op = NAME;
			}
		else {
			/* make it look beautiful... */
			p->in.op = UNARY MUL;
			canon( p );  /* turn it into an oreg */
			if( p->in.op != OREG ){
				offstar( p->in.left );
				canon( p );
				if( p->in.op != OREG ){
					offstar( p->in.left );
					canon( p );
					if( p->in.op != OREG ) cerror( "stuck starg" );
					}
				}
			}

		p->tn.lval += size;  /* end of structure */
		/* put on stack backwards */
		for( ; size>0; size -= 2 ){
			p->tn.lval -= 2;
			expand( p, RNOP, "	push	AR\nZ-" );
			}
		reclaim( p, RNULL, 0 );
		return;
		}

	/* ordinary case */

	if (p->in.type == DOUBLE && p->in.su!=0) order ( p, INTEMP );
	order( p, FORARG );
	}

argsize( p ) register NODE *p; {
	register t;
	t = 0;
	if( p->in.op == CM ){
		t = argsize( p->in.left );
		p = p->in.right;
		}
	if( p->in.type == DOUBLE || p->in.type == FLOAT ){
		SETOFF( t, 2 );
		return( t+8 );
		}
	else if( p->in.type == LONG || p->in.type == ULONG ) {
		SETOFF( t, 2);
		return( t+4 );
		}
	else if( p->in.op == STARG ){
		SETOFF( t, p->stn.stalign );  /* alignment */
		return( t + p->stn.stsize );  /* size */
		}
	else {
		SETOFF( t, 2 );
		return( t+2 );
		}
	}
der( p, FORARG );
	}

argsize( p ) register NODE *p; {
	register t;
	t = 0;
	if( p->in.op == CM ){
		t = argsize( p->in.left );
		p = p->in.right;
		}
	if( p->in.type == DOUBLE || p->in.type == FLOAT ){
		SETOFF( t, 2 );
		return( t+8 );
		}
	else if( p->in.type == LONG || p->in.type == ULONG ) {
		SETOFF( t, 2);
		return( t+4 );
		}
	else if( p->in.op == STARG ){
		SETOFF( t, p->stn.stalign );  /* alignment */
		return( t + p->stn.stsize );  /* size */
		}
	else {
		SETOc86/pftn.c                                                                                             666      26      12       113725  3227160434   5651                                                                                                                                                                                                                                                                                                                                                                      # include "mfile1"

unsigned int offsz;

struct instk {
	int in_sz;   /* size of array element */
	int in_x;    /* current index for structure member in structure initializations */
	int in_n;    /* number of initializations seen */
	int in_s;    /* sizoff */
	int in_d;    /* dimoff */
	TWORD in_t;    /* type */
	int in_id;   /* stab index */
	int in_fl;   /* flag which says if this level is controlled by {} */
	OFFSZ in_off;  /* offset of the beginning of this level */
	}
instack[10],
*pstk;

	/* defines used for getting things off of the initialization stack */


struct symtab *relook();


int ddebug = 0;

struct symtab * mknonuniq();

defid( q, class )  NODE *q; {
	register struct symtab *p;
	int idp;
	TWORD type;
	TWORD stp;
	int scl;
	int dsym, ddef;
	int slev, temp;

	if( q == NIL ) return;  /* an error was detected */

	if( q < node || q >= &node[TREESZ] ) cerror( "defid call" );

	idp = q->tn.rval;

	if( idp < 0 ) cerror( "tyreduce" );
	p = &stab[idp];

# ifndef BUG1
	if( ddebug ){
		printf( "defid( %.*s (%d), ", NCHNAM, p->sname, idp );
		tprint( q->in.type );
		printf( ", %s, (%d,%d) ), level %d\n", scnames(class), q->fn.cdim, q->fn.csiz, blevel );
		}
# endif

	fixtype( q, class );

	type = q->in.type;
	class = fixclass( class, type );

	stp = p->stype;
	slev = p->slevel;

# ifndef BUG1
	if( ddebug ){
		printf( "	modified to " );
		tprint( type );
		printf( ", %s\n", scnames(class) );
		printf( "	previous def'n: " );
		tprint( stp );
		printf( ", %s, (%d,%d) ), level %d\n", scnames(p->sclass), p->dimoff, p->sizoff, slev );
		}
# endif

	if( stp == FTN && p->sclass == SNULL )goto enter;
		/* name encountered as function, not yet defined */
		/* BUG here!  can't incompatibly declare func. in inner block */
	if( stp == UNDEF|| stp == FARG ){
		if( blevel==1 && stp!=FARG ) switch( class ){

		default:
			if(!(class&FIELD)) uerror( "declared argument %.*s is missing", NCHNAM, p->sname );
		case MOS:
		case STNAME:
		case MOU:
		case UNAME:
		case MOE:
		case ENAME:
		case TYPEDEF:
			;
			}
		goto enter;
		}

	if( type != stp ) goto mismatch;
	/* test (and possibly adjust) dimensions */
	dsym = p->dimoff;
	ddef = q->fn.cdim;
	for( temp=type; temp&TMASK; temp = DECREF(temp) ){
		if( ISARY(temp) ){
			if( dimtab[dsym] == 0 ) dimtab[dsym] = dimtab[ddef];
			else if( dimtab[ddef]!=0 && dimtab[dsym] != dimtab[ddef] ){
				goto mismatch;
				}
			++dsym;
			++ddef;
			}
		}

	/* check that redeclarations are to the same structure */
	if( (temp==STRTY||temp==UNIONTY||temp==ENUMTY) && p->sizoff != q->fn.csiz
		 && class!=STNAME && class!=UNAME && class!=ENAME ){
		goto mismatch;
		}

	scl = ( p->sclass );

# ifndef BUG1
	if( ddebug ){
		printf( "	previous class: %s\n", scnames(scl) );
		}
# endif

	if( class&FIELD ){
		/* redefinition */
		if( !falloc( p, class&FLDSIZ, 1, NIL ) ) {
			/* successful allocation */
			psave( idp );
			return;
			}
		/* blew it: resume at end of switch... */
		}

	else switch( class ){

	case EXTERN:
		switch( scl ){
		case STATIC:
		case USTATIC:
			if( slev==0 ) return;
			break;
		case EXTDEF:
		case EXTERN:
		case FORTRAN:
		case UFORTRAN:
			return;
			}
		break;

	case STATIC:
		if( scl==USTATIC || (scl==EXTERN && blevel==0) ){
			p->sclass = STATIC;
			if( ISFTN(type) ) curftn = idp;
			return;
			}
		break;

	case USTATIC:
		if( scl==STATIC || scl==USTATIC ) return;
		break;

	case LABEL:
		if( scl == ULABEL ){
			p->sclass = LABEL;
			deflab( p->offset );
			return;
			}
		break;

	case TYPEDEF:
		if( scl == class ) return;
		break;

	case UFORTRAN:
		if( scl == UFORTRAN || scl == FORTRAN ) return;
		break;

	case FORTRAN:
		if( scl == UFORTRAN ){
			p->sclass = FORTRAN;
			if( ISFTN(type) ) curftn = idp;
			return;
			}
		break;

	case MOU:
	case MOS:
		if( scl == class ) {
			if( oalloc( p, &strucoff ) ) break;
			if( class == MOU ) strucoff = 0;
			psave( idp );
			return;
			}
		break;

	case MOE:
		if( scl == class ){
			if( p->offset!= strucoff++ ) break;
			psave( idp );
			}
		break;

	case EXTDEF:
		if( scl == EXTERN ) {
			p->sclass = EXTDEF;
			if( ISFTN(type) ) curftn = idp;
			return;
			}
		break;

	case STNAME:
	case UNAME:
	case ENAME:
		if( scl != class ) break;
		if( dimtab[p->sizoff] == 0 ) return;  /* previous entry just a mention */
		break;

	case ULABEL:
		if( scl == LABEL || scl == ULABEL ) return;
	case PARAM:
	case AUTO:
	case REGISTER:
		;  /* mismatch.. */

		}

	mismatch:
	/* allow nonunique structure/union member names */

	if( class==MOU || class==MOS || class & FIELD ){/* make a new entry */
		int * memp;
		p->sflags |= SNONUNIQ;  /* old entry is nonunique */
		/* determine if name has occurred in this structure/union */
		for( memp = &paramstk[paramno-1];
			/* while */ *memp>=0 && stab[*memp].sclass != STNAME
				&& stab[*memp].sclass != UNAME;
			/* iterate */ --memp){ char * cname, * oname;
			if( stab[*memp].sflags & SNONUNIQ ){int k;
				cname=p->sname;
				oname=stab[*memp].sname;
				for(k=1; k<=NCHNAM; ++k){
					if(*cname++ != *oname)goto diff;
					if(!*oname++)break;
					}
				uerror("redeclaration of: %s",p->sname);
				break;
				diff: continue;
				}
			}
		p = mknonuniq( &idp ); /* update p and idp to new entry */
		goto enter;
		}
	if( blevel > slev && class != EXTERN && class != FORTRAN &&
		class != UFORTRAN && !( class == LABEL && slev >= 2 ) ){
		q->tn.rval = idp = hide( p );
		p = &stab[idp];
		goto enter;
		}
	uerror( "redeclaration of %.*s", NCHNAM, p->sname );
	if( class==EXTDEF && ISFTN(type) ) curftn = idp;
	return;

	enter:  /* make a new entry */

# ifndef BUG1
	if( ddebug ) printf( "	new entry made\n" );
# endif
	if( type == UNDEF ) uerror("void type for %.*s",NCHNAM,p->sname);
	p->stype = type;
	p->sclass = class;
	p->slevel = blevel;
	p->offset = NOOFFSET;
	p->suse = lineno;
	if( class == STNAME || class == UNAME || class == ENAME ) {
		p->sizoff = curdim;
		dstash( 0 );  /* size */
		dstash( -1 ); /* index to members of str or union */
		dstash( ALSTRUCT );  /* alignment */
		dstash( idp );  /* name index */
		}
	else {
		switch( BTYPE(type) ){
		case STRTY:
		case UNIONTY:
		case ENUMTY:
			p->sizoff = q->fn.csiz;
			break;
		default:
			p->sizoff = BTYPE(type);
			}
		}

	/* copy dimensions */

	p->dimoff = q->fn.cdim;

	/* allocate offsets */
	if( class&FIELD ){
		falloc( p, class&FLDSIZ, 0, NIL );  /* new entry */
		psave( idp );
		}
	else switch( class ){

	case AUTO:
		oalloc( p, &autooff );
		break;
	case STATIC:
	case EXTDEF:
		p->offset = getlab();
		if( ISFTN(type) ) curftn = idp;
		break;
	case ULABEL:
	case LABEL:
		p->offset = getlab();
		p->slevel = 2;
		if( class == LABEL ){
			locctr( PROG );
			deflab( p->offset );
			}
		break;

	case EXTERN:
	case UFORTRAN:
	case FORTRAN:
		p->offset = getlab();
		p->slevel = 0;
		break;
	case MOU:
	case MOS:
		oalloc( p, &strucoff );
		if( class == MOU ) strucoff = 0;
		psave( idp );
		break;

	case MOE:
		p->offset = strucoff++;
		psave( idp );
		break;
	case REGISTER:
		p->offset = regvar--;
		if( blevel == 1 ) p->sflags |= SSET;
		if( regvar < minrvar ) minrvar = regvar;
		break;
		}

	/* user-supplied routine to fix up new definitions */

	FIXDEF(p);

# ifndef BUG1
	if( ddebug ) printf( "	dimoff, sizoff, offset: %d, %d, %d\n", p->dimoff, p->sizoff, p->offset );
# endif

	}

psave( i ){
	if( paramno >= PARAMSZ ){
		cerror( "parameter stack overflow");
		}
	paramstk[ paramno++ ] = i;
	}

ftnend(){ /* end of function */
	if( retlab != NOLAB ){ /* inside a real function */
		efcode();
		}
	checkst(0);
	retstat = 0;
	tcheck();
	curclass = SNULL;
	brklab = contlab = retlab = NOLAB;
	flostat = 0;
	if( nerrors == 0 ){
		if( psavbc != & asavbc[0] ) cerror("bcsave error");
		if( paramno != 0 ) cerror("parameter reset error");
		if( swx != 0 ) cerror( "switch error");
		}
	psavbc = &asavbc[0];
	paramno = 0;
	autooff = AUTOINIT;
	minrvar = regvar = MAXRVAR;
	reached = 1;
	swx = 0;
	swp = swtab;
	locctr(DATA);
	}

dclargs(){
	register i, j;
	register struct symtab *p;
	register NODE *q;
	argoff = ARGINIT;
# ifndef BUG1
	if( ddebug > 2) printf("dclargs()\n");
# endif
	for( i=0; i<paramno; ++i ){
		if( (j = paramstk[i]) < 0 ) continue;
		p = &stab[j];
# ifndef BUG1
		if( ddebug > 2 ){
			printf("\t%.*s (%d) ",NCHNAM,p->sname, j);
			tprint(p->stype);
			printf("\n");
			}
# endif
		if( p->stype == FARG ) {
			q = block(FREE,NIL,NIL,INT,0,INT);
			q->tn.rval = j;
			defid( q, PARAM );
			}
		oalloc( p, &argoff );  /* always set aside space, even for register arguments */
		FIXARG(p); /* local arg hook, eg. for sym. debugger */
		}
	cendarg();
	locctr(PROG);
	defalign(ALINT);
	++ftnno;
	bfcode( paramstk, paramno );
	paramno = 0;
	}

NODE *
rstruct( idn, soru ){ /* reference to a structure or union, with no definition */
	register struct symtab *p;
	register NODE *q;
	p = &stab[idn];
	switch( p->stype ){

	case UNDEF:
	def:
		q = block( FREE, NIL, NIL, 0, 0, 0 );
		q->tn.rval = idn;
		q->in.type = (soru&INSTRUCT) ? STRTY : ( (soru&INUNION) ? UNIONTY : ENUMTY );
		defid( q, (soru&INSTRUCT) ? STNAME : ( (soru&INUNION) ? UNAME : ENAME ) );
		break;

	case STRTY:
		if( soru & INSTRUCT ) break;
		goto def;

	case UNIONTY:
		if( soru & INUNION ) break;
		goto def;

	case ENUMTY:
		if( !(soru&(INUNION|INSTRUCT)) ) break;
		goto def;

		}
	stwart = instruct;
	return( mkty( p->stype, 0, p->sizoff ) );
	}

moedef( idn ){
	register NODE *q;

	q = block( FREE, NIL, NIL, MOETY, 0, 0 );
	q->tn.rval = idn;
	if( idn>=0 ) defid( q, MOE );
	}

bstruct( idn, soru ){ /* begining of structure or union declaration */
	register NODE *q;

	psave( instruct );
	psave( curclass );
	psave( strucoff );
	strucoff = 0;
	instruct = soru;
	q = block( FREE, NIL, NIL, 0, 0, 0 );
	q->tn.rval = idn;
	if( instruct==INSTRUCT ){
		curclass = MOS;
		q->in.type = STRTY;
		if( idn >= 0 ) defid( q, STNAME );
		}
	else if( instruct == INUNION ) {
		curclass = MOU;
		q->in.type = UNIONTY;
		if( idn >= 0 ) defid( q, UNAME );
		}
	else { /* enum */
		curclass = MOE;
		q->in.type = ENUMTY;
		if( idn >= 0 ) defid( q, ENAME );
		}
	psave( idn = q->tn.rval );
	/* the "real" definition is where the members are seen */
	if( idn >= 0 ) stab[idn].suse = lineno;
	return( paramno-4 );
	}

NODE *
dclstruct( oparam ){
	register struct symtab *p;
	register i, al, sa, j, sz, szindex;
	register TWORD temp;
	register high, low;

	/* paramstack contains:
		paramstack[ oparam ] = previous instruct
		paramstack[ oparam+1 ] = previous class
		paramstk[ oparam+2 ] = previous strucoff
		paramstk[ oparam+3 ] = structure name

		paramstk[ oparam+4, ... ]  = member stab indices

		*/


	if( (i=paramstk[oparam+3]) < 0 ){
		szindex = curdim;
		dstash( 0 );  /* size */
		dstash( -1 );  /* index to member names */
		dstash( ALSTRUCT );  /* alignment */
		dstash( -lineno );  /* name of structure */
		}
	else {
		szindex = stab[i].sizoff;
		}

# ifndef BUG1
	if( ddebug ){
		printf( "dclstruct( %.*s ), szindex = %d\n", NCHNAM,(i>=0)? stab[i].sname : "??", szindex );
		}
# endif
	temp = (instruct&INSTRUCT)?STRTY:((instruct&INUNION)?UNIONTY:ENUMTY);
	stwart = instruct = paramstk[ oparam ];
	curclass = paramstk[ oparam+1 ];
	dimtab[ szindex+1 ] = curdim;
	al = ALSTRUCT;

	high = low = 0;

	for( i = oparam+4;  i< paramno; ++i ){
		dstash( j=paramstk[i] );
		if( j<0 || j>= SYMTSZ ) cerror( "gummy structure member" );
		p = &stab[j];
		if( temp == ENUMTY ){
			if( p->offset < low ) low = p->offset;
			if( p->offset > high ) high = p->offset;
			p->sizoff = szindex;
			continue;
			}
		sa = talign( p->stype, p->sizoff );
		if( p->sclass & FIELD ){
			sz = p->sclass&FLDSIZ;
			}
		else {
			sz = tsize( p->stype, p->dimoff, p->sizoff );
			}
		if( sz == 0 ){
			uerror( "illegal zero sized structure member: %.*s", NCHNAM, p->sname );
			}
		if( sz > strucoff ) strucoff = sz;  /* for use with unions */
		SETOFF( al, sa );
		/* set al, the alignment, to the lcm of the alignments of the members */
		}
	dstash( -1 );  /* endmarker */
	SETOFF( strucoff, al );

	if( temp == ENUMTY ){
		register TWORD ty;

# ifdef ENUMSIZE
		ty = ENUMSIZE(high,low);
# else
		if( (char)high == high && (char)low == low ) ty = ctype( CHAR );
		else if( (short)high == high && (short)low == low ) ty = ctype( SHORT );
		else ty = ctype(INT);
#endif
		strucoff = tsize( ty, 0, (int)ty );
		dimtab[ szindex+2 ] = al = talign( ty, (int)ty );
		}

	if( strucoff == 0 ) uerror( "zero sized structure" );
	dimtab[ szindex ] = strucoff;
	dimtab[ szindex+2 ] = al;
	dimtab[ szindex+3 ] = paramstk[ oparam+3 ];  /* name index */

	FIXSTRUCT( szindex, oparam ); /* local hook, eg. for sym debugger */
# ifndef BUG1
	if( ddebug>1 ){
		printf( "\tdimtab[%d,%d,%d,%d] = %d,%d,%d,%d\n",
			szindex,szindex+1,szindex+2,szindex+3,
			dimtab[szindex],dimtab[szindex+1],dimtab[szindex+2],
			dimtab[szindex+3] );
		for( i = dimtab[szindex+1]; dimtab[i] >= 0; ++i ){
			printf( "\tmember %.*s(%d)\n", NCHNAM, stab[dimtab[i]].sname, dimtab[i] );
			}
		}
# endif

	strucoff = paramstk[ oparam+2 ];
	paramno = oparam;

	return( mkty( temp, 0, szindex ) );
	}

	/* VARARGS */
yyerror( s ) char *s; { /* error printing routine in parser */

	uerror( s );

	}

yyaccpt(){
	ftnend();
	}

ftnarg( idn ) {
	switch( stab[idn].stype ){

	case UNDEF:
		/* this parameter, entered at scan */
		break;
	case FARG:
		uerror("redeclaration of formal parameter, %.*s",
			NCHNAM, stab[idn].sname);
		/* fall thru */
	case FTN:
		/* the name of this function matches parm */
		/* fall thru */
	default:
		idn = hide( &stab[idn]);
		break;
	case TNULL:
		/* unused entry, fill it */
		;
		}
	stab[idn].stype = FARG;
	stab[idn].sclass = PARAM;
	psave( idn );
	}

talign( ty, s) register unsigned ty; register s; {
	/* compute the alignment of an object with type ty, sizeoff index s */

	register i;
	if( s<0 && ty!=INT && ty!=CHAR && ty!=SHORT && ty!=UNSIGNED && ty!=UCHAR && ty!=USHORT 
#ifdef LONGFIELDS
		&& ty!=LONG && ty!=ULONG
#endif
					){
		return( fldal( ty ) );
		}

	for( i=0; i<=(SZINT-BTSHIFT-1); i+=TSHIFT ){
		switch( (ty>>i)&TMASK ){

		case FTN:
			cerror( "compiler takes alignment of function");
		case PTR:
			return( ALPOINT );
		case ARY:
			continue;
		case 0:
			break;
			}
		}

	switch( BTYPE(ty) ){

	case UNIONTY:
	case ENUMTY:
	case STRTY:
		return( (unsigned int) dimtab[ s+2 ] );
	case CHAR:
	case UCHAR:
		return( ALCHAR );
	case FLOAT:
		return( ALFLOAT );
	case DOUBLE:
		return( ALDOUBLE );
	case LONG:
	case ULONG:
		return( ALLONG );
	case SHORT:
	case USHORT:
		return( ALSHORT );
	default:
		return( ALINT );
		}
	}

OFFSZ
tsize( ty, d, s )  TWORD ty; {
	/* compute the size associated with type ty,
	    dimoff d, and sizoff s */
	/* BETTER NOT BE CALLED WHEN t, d, and s REFER TO A BIT FIELD... */

	int i;
	OFFSZ mult;

	mult = 1;

	for( i=0; i<=(SZINT-BTSHIFT-1); i+=TSHIFT ){
		switch( (ty>>i)&TMASK ){

		case FTN:
			cerror( "compiler takes size of function");
		case PTR:
			return( SZPOINT * mult );
		case ARY:
			mult *= (unsigned int) dimtab[ d++ ];
			continue;
		case 0:
			break;

			}
		}

	if( dimtab[s]==0 ) {
		uerror( "unknown size");
		return( SZINT );
		}
	return( (unsigned int) dimtab[ s ] * mult );
	}

inforce( n ) OFFSZ n; {  /* force inoff to have the value n */
	/* inoff is updated to have the value n */
	OFFSZ wb;
	register rest;
	/* rest is used to do a lot of conversion to ints... */

	if( inoff == n ) return;
	if( inoff > n ) {
		cerror( "initialization alignment error");
		}

	wb = inoff;
	SETOFF( wb, SZINT );

	/* wb now has the next higher word boundary */

	if( wb >= n ){ /* in the same word */
		rest = n - inoff;
		vfdzero( rest );
		return;
		}

	/* otherwise, extend inoff to be word aligned */

	rest = wb - inoff;
	vfdzero( rest );

	/* now, skip full words until near to n */

	rest = (n-inoff)/SZINT;
	zecode( rest );

	/* now, the remainder of the last word */

	rest = n-inoff;
	vfdzero( rest );
	if( inoff != n ) cerror( "inoff error");

	}

vfdalign( n ){ /* make inoff have the offset the next alignment of n */
	OFFSZ m;

	m = inoff;
	SETOFF( m, n );
	inforce( m );
	}


int idebug = 0;

int ibseen = 0;  /* the number of } constructions which have been filled */

int iclass;  /* storage class of thing being initialized */

int ilocctr = 0;  /* location counter for current initialization */

beginit(curid){
	/* beginning of initilization; set location ctr and set type */
	register struct symtab *p;

# ifndef BUG1
	if( idebug >= 3 ) printf( "beginit(), curid = %d\n", curid );
# endif

	p = &stab[curid];

	iclass = p->sclass;
	if( curclass == EXTERN || curclass == FORTRAN ) iclass = EXTERN;
	switch( iclass ){

	case UNAME:
	case EXTERN:
		return;
	case AUTO:
	case REGISTER:
		break;
	case EXTDEF:
	case STATIC:
		ilocctr = ISARY(p->stype)?ADATA:DATA;
		locctr( ilocctr );
		defalign( talign( p->stype, p->sizoff ) );
		defnam( p );

		}

	inoff = 0;
	ibseen = 0;

	pstk = 0;

	instk( curid, p->stype, p->dimoff, p->sizoff, inoff );

	}

instk( id, t, d, s, off ) OFFSZ off; TWORD t; {
	/* make a new entry on the parameter stack to initialize id */

	register struct symtab *p;

	for(;;){
# ifndef BUG1
		if( idebug ) printf( "instk((%d, %o,%d,%d, %d)\n", id, t, d, s, off );
# endif

		/* save information on the stack */

		if( !pstk ) pstk = instack;
		else ++pstk;

		pstk->in_fl = 0;	/* { flag */
		pstk->in_id =  id ;
		pstk->in_t =  t ;
		pstk->in_d =  d ;
		pstk->in_s =  s ;
		pstk->in_n = 0;  /* number seen */
		pstk->in_x =  t==STRTY ?dimtab[s+1] : 0 ;
		pstk->in_off =  off;   /* offset at the beginning of this element */
		/* if t is an array, DECREF(t) can't be a field */
		/* INS_sz has size of array elements, and -size for fields */
		if( ISARY(t) ){
			pstk->in_sz = tsize( DECREF(t), d+1, s );
			}
		else if( stab[id].sclass & FIELD ){
			pstk->in_sz = - ( stab[id].sclass & FLDSIZ );
			}
		else {
			pstk->in_sz = 0;
			}

		if( (iclass==AUTO || iclass == REGISTER ) &&
			(ISARY(t) || t==STRTY) ) uerror( "no automatic aggregate initialization" );

		/* now, if this is not a scalar, put on another element */

		if( ISARY(t) ){
			t = DECREF(t);
			++d;
			continue;
			}
		else if( t == STRTY ){
			id = dimtab[pstk->in_x];
			p = &stab[id];
			if( p->sclass != MOS && !(p->sclass&FIELD) ) cerror( "insane structure member list" );
			t = p->stype;
			d = p->dimoff;
			s = p->sizoff;
			off += p->offset;
			continue;
			}
		else return;
		}
	}

NODE *
getstr(){ /* decide if the string is external or an initializer, and get the contents accordingly */

	register l, temp;
	register NODE *p;

	if( (iclass==EXTDEF||iclass==STATIC) && (pstk->in_t == CHAR || pstk->in_t == UCHAR) &&
			pstk!=instack && ISARY( pstk[-1].in_t ) ){
		/* treat "abc" as { 'a', 'b', 'c', 0 } */
		strflg = 1;
		ilbrace();  /* simulate { */
		inforce( pstk->in_off );
		/* if the array is inflexible (not top level), pass in the size and
			be prepared to throw away unwanted initializers */
		lxstr((pstk-1)!=instack?dimtab[(pstk-1)->in_d]:0);  /* get the contents */
		irbrace();  /* simulate } */
		return( NIL );
		}
	else { /* make a label, and get the contents and stash them away */
		if( iclass != SNULL ){ /* initializing */
			/* fill out previous word, to permit pointer */
			vfdalign( ALPOINT );
			}
		temp = locctr( blevel==0?ISTRNG:STRNG ); /* set up location counter */
		deflab( l = getlab() );
		strflg = 0;
		lxstr(0); /* get the contents */
		locctr( blevel==0?ilocctr:temp );
		p = buildtree( STRING, NIL, NIL );
		p->tn.rval = -l;
		return(p);
		}
	}

putbyte( v ){ /* simulate byte v appearing in a list of integer values */
	register NODE *p;
	p = bcon(v);
	incode( p, SZCHAR );
	tfree( p );
	gotscal();
	}

endinit(){
	register TWORD t;
	register d, s, n, d1;

# ifndef BUG1
	if( idebug ) printf( "endinit(), inoff = %d\n", inoff );
# endif

	switch( iclass ){

	case EXTERN:
	case AUTO:
	case REGISTER:
		return;
		}

	pstk = instack;

	t = pstk->in_t;
	d = pstk->in_d;
	s = pstk->in_s;
	n = pstk->in_n;

	if( ISARY(t) ){
		d1 = dimtab[d];

		vfdalign( pstk->in_sz );  /* fill out part of the last element, if needed */
		n = inoff/pstk->in_sz;  /* real number of initializers */
		if( d1 >= n ){
			/* once again, t is an array, so no fields */
			inforce( tsize( t, d, s ) );
			n = d1;
			}
		if( d1!=0 && d1!=n ) uerror( "too many initializers");
		if( n==0 ) werror( "empty array declaration");
		dimtab[d] = n;
		}

	else if( t == STRTY || t == UNIONTY ){
		/* clearly not fields either */
		inforce( tsize( t, d, s ) );
		}
	else if( n > 1 ) uerror( "bad scalar initialization");
	/* this will never be called with a field element... */
	else inforce( tsize(t,d,s) );

	paramno = 0;
	vfdalign( AL_INIT );
	inoff = 0;
	iclass = SNULL;

	}

doinit( p ) register NODE *p; {

	/* take care of generating a value for the initializer p */
	/* inoff has the current offset (last bit written)
		in the current word being generated */

	register sz, d, s;
	register TWORD t;

	/* note: size of an individual initializer is assumed to fit into an int */

	if( iclass < 0 ) goto leave;
	if( iclass == EXTERN || iclass == UNAME ){
		uerror( "cannot initialize extern or union" );
		iclass = -1;
		goto leave;
		}

	if( iclass == AUTO || iclass == REGISTER ){
		/* do the initialization and get out, without regard 
		    for filing out the variable with zeros, etc. */
		bccode();
		idname = pstk->in_id;
		p = buildtree( ASSIGN, buildtree( NAME, NIL, NIL ), p );
		ecomp(p);
		return;
		}

	if( p == NIL ) return;  /* for throwing away strings that have been turned into lists */

	if( ibseen ){
		uerror( "} expected");
		goto leave;
		}

# ifndef BUG1
	if( idebug > 1 ) printf( "doinit(%o)\n", p );
# endif

	t = pstk->in_t;  /* type required */
	d = pstk->in_d;
	s = pstk->in_s;
	if( pstk->in_sz < 0 ){  /* bit field */
		sz = -pstk->in_sz;
		}
	else {
		sz = tsize( t, d, s );
		}

	inforce( pstk->in_off );

	p = buildtree( ASSIGN, block( NAME, NIL,NIL, t, d, s ), p );
	p->in.left->in.op = FREE;
	p->in.left = p->in.right;
	p->in.right = NIL;
	p->in.left = optim( p->in.left );
	if( p->in.left->in.op == UNARY AND ){
		p->in.left->in.op = FREE;
		p->in.left = p->in.left->in.left;
		}
	p->in.op = INIT;

	if( sz < SZINT ){ /* special case: bit fields, etc. */
		if( p->in.left->in.op != ICON ) uerror( "illegal initialization" );
		else incode( p->in.left, sz );
		}
	else if( p->in.left->in.op == FCON ){
		fincode( p->in.left->fpn.dval, sz );
		}
	else {
		cinit( optim(p), sz );
		}

	gotscal();

	leave:
	tfree(p);
	}

gotscal(){
	register t, ix;
	register n, id;
	struct symtab *p;
	OFFSZ temp;

	for( ; pstk > instack; ) {

		if( pstk->in_fl ) ++ibseen;

		--pstk;
		
		t = pstk->in_t;

		if( t == STRTY ){
			ix = ++pstk->in_x;
			if( (id=dimtab[ix]) < 0 ) continue;

			/* otherwise, put next element on the stack */

			p = &stab[id];
			instk( id, p->stype, p->dimoff, p->sizoff, p->offset+pstk->in_off );
			return;
			}
		else if( ISARY(t) ){
			n = ++pstk->in_n;
			if( n >= dimtab[pstk->in_d] && pstk > instack ) continue;

			/* put the new element onto the stack */

			temp = pstk->in_sz;
			instk( pstk->in_id, (TWORD)DECREF(pstk->in_t), pstk->in_d+1, pstk->in_s,
				pstk->in_off+n*temp );
			return;
			}

		}

	}

ilbrace(){ /* process an initializer's left brace */
	register t;
	struct instk *temp;

	temp = pstk;

	for( ; pstk > instack; --pstk ){

		t = pstk->in_t;
		if( t != STRTY && !ISARY(t) ) continue; /* not an aggregate */
		if( pstk->in_fl ){ /* already associated with a { */
			if( pstk->in_n ) uerror( "illegal {");
			continue;
			}

		/* we have one ... */
		pstk->in_fl = 1;
		break;
		}

	/* cannot find one */
	/* ignore such right braces */

	pstk = temp;
	}

irbrace(){
	/* called when a '}' is seen */

# ifndef BUG1
	if( idebug ) printf( "irbrace(): paramno = %d on entry\n", paramno );
# endif

	if( ibseen ) {
		--ibseen;
		return;
		}

	for( ; pstk > instack; --pstk ){
		if( !pstk->in_fl ) continue;

		/* we have one now */

		pstk->in_fl = 0;  /* cancel { */
		gotscal();  /* take it away... */
		return;
		}

	/* these right braces match ignored left braces: throw out */

	}

upoff( size, alignment, poff ) register alignment, *poff; {
	/* update the offset pointed to by poff; return the
	/* offset of a value of size `size', alignment `alignment',
	/* given that off is increasing */

	register off;

	off = *poff;
	SETOFF( off, alignment );
	if( (offsz-off) <=  size ){
		if( instruct!=INSTRUCT )cerror("too many local variables");
		else cerror("Structure too large");
		}
	*poff = off+size;
	return( off );
	}

oalloc( p, poff ) register struct symtab *p; register *poff; {
	/* allocate p with offset *poff, and update *poff */
	register al, off, tsz;
	int noff;

	al = talign( p->stype, p->sizoff );
	noff = off = *poff;
	tsz = tsize( p->stype, p->dimoff, p->sizoff );
#ifdef BACKAUTO
	if( p->sclass == AUTO ){
		if( (offsz-off) <= tsz ) cerror("too many local variables");
		noff = off + tsz;
		SETOFF( noff, al );
		off = -noff;
		}
	else
#endif
		if( p->sclass == PARAM && ( tsz < SZINT ) ){
			off = upoff( SZINT, ALINT, &noff );
# ifndef RTOLBYTES
			off = noff - tsz;
#endif
			}
		else
		{
		off = upoff( tsz, al, &noff );
		}

	if( p->sclass != REGISTER ){ /* in case we are allocating stack space for register arguments */
		if( p->offset == NOOFFSET ) p->offset = off;
		else if( off != p->offset ) return(1);
		}

	*poff = noff;
	return(0);
	}

falloc( p, w, new, pty )  register struct symtab *p; NODE *pty; {
	/* allocate a field of width w */
	/* new is 0 if new entry, 1 if redefinition, -1 if alignment */

	register al,sz,type;

	type = (new<0)? pty->in.type : p->stype;

	/* this must be fixed to use the current type in alignments */
	switch( new<0?pty->in.type:p->stype ){

	case ENUMTY:
		{
			int s;
			s = new<0 ? pty->fn.csiz : p->sizoff;
			al = dimtab[s+2];
			sz = dimtab[s];
			break;
			}

	case CHAR:
	case UCHAR:
		al = ALCHAR;
		sz = SZCHAR;
		break;

	case SHORT:
	case USHORT:
		al = ALSHORT;
		sz = SZSHORT;
		break;

	case INT:
	case UNSIGNED:
		al = ALINT;
		sz = SZINT;
		break;
#ifdef LONGFIELDS

	case LONG:
	case ULONG:
		al = ALLONG;
		sz = SZLONG;
		break;
#endif

	default:
		if( new < 0 ) {
			uerror( "illegal field type" );
			al = ALINT;
			}
		else {
			al = fldal( p->stype );
			sz =SZINT;
			}
		}

	if( w > sz ) {
		uerror( "field too big");
		w = sz;
		}

	if( w == 0 ){ /* align only */
		SETOFF( strucoff, al );
		if( new >= 0 ) uerror( "zero size field");
		return(0);
		}

	if( strucoff%al + w > sz ) SETOFF( strucoff, al );
	if( new < 0 ) {
		if( (offsz-strucoff) <= w )
			cerror("structure too large");
		strucoff += w;  /* we know it will fit */
		return(0);
		}

	/* establish the field */

	if( new == 1 ) { /* previous definition */
		if( p->offset != strucoff || p->sclass != (FIELD|w) ) return(1);
		}
	p->offset = strucoff;
	if( (offsz-strucoff) <= w ) cerror("structure too large");
	strucoff += w;
	p->stype = type;
	fldty( p );
	return(0);
	}

nidcl( p ) NODE *p; { /* handle unitialized declarations */
	/* assumed to be not functions */
	register class;
	register commflag;  /* flag for labelled common declarations */

	commflag = 0;

	/* compute class */
	if( (class=curclass) == SNULL ){
		if( blevel > 1 ) class = AUTO;
		else if( blevel != 0 || instruct ) cerror( "nidcl error" );
		else { /* blevel = 0 */
			class = noinit();
			if( class == EXTERN ) commflag = 1;
			}
		}

	defid( p, class );

	if( class==EXTDEF || class==STATIC ){
		/* simulate initialization by 0 */
		beginit(p->tn.rval);
		endinit();
		}
	if( commflag ) commdec( p->tn.rval );
	}

TWORD
types( t1, t2, t3 ) TWORD t1, t2, t3; {
	/* return a basic type from basic types t1, t2, and t3 */

	TWORD t[3], noun, adj, unsg;
	register i;

	t[0] = t1;
	t[1] = t2;
	t[2] = t3;

	unsg = INT;  /* INT or UNSIGNED */
	noun = UNDEF;  /* INT, CHAR, or FLOAT */
	adj = INT;  /* INT, LONG, or SHORT */

	for( i=0; i<3; ++i ){
		switch( t[i] ){

		default:
		bad:
			uerror( "illegal type combination" );
			return( INT );

		case UNDEF:
			continue;

		case UNSIGNED:
			if( unsg != INT ) goto bad;
			unsg = UNSIGNED;
			continue;

		case LONG:
		case SHORT:
			if( adj != INT ) goto bad;
			adj = t[i];
			continue;

		case INT:
		case CHAR:
		case FLOAT:
			if( noun != UNDEF ) goto bad;
			noun = t[i];
			continue;
			}
		}

	/* now, construct final type */
	if( noun == UNDEF ) noun = INT;
	else if( noun == FLOAT ){
		if( unsg != INT || adj == SHORT ) goto bad;
		return( adj==LONG ? DOUBLE : FLOAT );
		}
	else if( noun == CHAR && adj != INT ) goto bad;

	/* now, noun is INT or CHAR */
	if( adj != INT ) noun = adj;
	if( unsg == UNSIGNED ) return( noun + (UNSIGNED-INT) );
	else return( noun );
	}

NODE *
tymerge( typ, idp ) NODE *typ, *idp; {
	/* merge type typ with identifier idp  */

	register unsigned t;
	register i;
	extern int eprint();

	if( typ->in.op != TYPE ) cerror( "tymerge: arg 1" );
	if(idp == NIL ) return( NIL );

# ifndef BUG1
	if( ddebug > 2 ) fwalk( idp, eprint, 0 );
# endif

	idp->in.type = typ->in.type;
	idp->fn.cdim = curdim;
	tyreduce( idp );
	idp->fn.csiz = typ->fn.csiz;

	for( t=typ->in.type, i=typ->fn.cdim; t&TMASK; t = DECREF(t) ){
		if( ISARY(t) ) dstash( dimtab[i++] );
		}

	/* now idp is a single node: fix up type */

	idp->in.type = ctype( idp->in.type );

	if( (t = BTYPE(idp->in.type)) != STRTY && t != UNIONTY && t != ENUMTY ){
		idp->fn.csiz = t;  /* in case ctype has rewritten things */
		}

	return( idp );
	}

tyreduce( p ) register NODE *p; {

	/* build a type, and stash away dimensions, from a parse tree of the declaration */
	/* the type is build top down, the dimensions bottom up */
	register o, temp;
	register unsigned t;

	o = p->in.op;
	p->in.op = FREE;

	if( o == NAME ) return;

	t = INCREF( p->in.type );
	if( o == UNARY CALL ) t += (FTN-PTR);
	else if( o == LB ){
		t += (ARY-PTR);
		temp = p->in.right->tn.lval;
		p->in.right->in.op = FREE;
		}

	p->in.left->in.type = t;
	tyreduce( p->in.left );

	if( o == LB ) dstash( temp );

	p->tn.rval = p->in.left->tn.rval;
	p->in.type = p->in.left->in.type;

	}

fixtype( p, class ) register NODE *p; {
	register unsigned t, type;
	register mod1, mod2;
	/* fix up the types, and check for legality */

	if( (type = p->in.type) == UNDEF ) return;
	if( mod2 = (type&TMASK) ){
		t = DECREF(type);
		while( mod1=mod2, mod2 = (t&TMASK) ){
			if( mod1 == ARY && mod2 == FTN ){
				uerror( "array of functions is illegal" );
				type = 0;
				}
			else if( mod1 == FTN && ( mod2 == ARY || mod2 == FTN ) ){
				uerror( "function returns illegal type" );
				type = 0;
				}
			t = DECREF(t);
			}
		}

	/* detect function arguments, watching out for structure declarations */
	/* for example, beware of f(x) struct [ int a[10]; } *x; { ... } */
	/* the danger is that "a" will be converted to a pointer */

	if( class==SNULL && blevel==1 && !(instruct&(INSTRUCT|INUNION)) ) class = PARAM;
	if( class == PARAM || ( class==REGISTER && blevel==1 ) ){
		if( type == FLOAT ) type = DOUBLE;
		else if( ISARY(type) ){
			++p->fn.cdim;
			type += (PTR-ARY);
			}
		else if( ISFTN(type) ){
			werror( "a function is declared as an argument" );
			type = INCREF(type);
			}

		}

	if( instruct && ISFTN(type) ){
		uerror( "function illegal in structure or union" );
		type = INCREF(type);
		}
	p->in.type = type;
	}

uclass( class ) register class; {
	/* give undefined version of class */
	if( class == SNULL ) return( EXTERN );
	else if( class == STATIC ) return( USTATIC );
	else if( class == FORTRAN ) return( UFORTRAN );
	else return( class );
	}

fixclass( class, type ) TWORD type; {

	/* first, fix null class */

	if( class == SNULL ){
		if( instruct&INSTRUCT ) class = MOS;
		else if( instruct&INUNION ) class = MOU;
		else if( blevel == 0 ) class = EXTDEF;
		else if( blevel == 1 ) class = PARAM;
		else class = AUTO;

		}

	/* now, do general checking */

	if( ISFTN( type ) ){
		switch( class ) {
		default:
			uerror( "function has illegal storage class" );
		case AUTO:
			class = EXTERN;
		case EXTERN:
		case EXTDEF:
		case FORTRAN:
		case TYPEDEF:
		case STATIC:
		case UFORTRAN:
		case USTATIC:
			;
			}
		}

	if( class&FIELD ){
		if( !(instruct&INSTRUCT) ) uerror( "illegal use of field" );
		return( class );
		}

	switch( class ){

	case MOU:
		if( !(instruct&INUNION) ) uerror( "illegal class" );
		return( class );

	case MOS:
		if( !(instruct&INSTRUCT) ) uerror( "illegal class" );
		return( class );

	case MOE:
		if( instruct & (INSTRUCT|INUNION) ) uerror( "illegal class" );
		return( class );

	case REGISTER:
		if( blevel == 0 ) uerror( "illegal register declaration" );
		else if( regvar >= MINRVAR && cisreg( type ) ) return( class );
		if( blevel == 1 ) return( PARAM );
		else return( AUTO );

	case AUTO:
	case LABEL:
	case ULABEL:
		if( blevel < 2 ) uerror( "illegal class" );
		return( class );

	case PARAM:
		if( blevel != 1 ) uerror( "illegal class" );
		return( class );

	case UFORTRAN:
	case FORTRAN:
# ifdef NOFORTRAN
			NOFORTRAN;    /* a condition which can regulate the FORTRAN usage */
# endif
		if( !ISFTN(type) ) uerror( "fortran declaration must apply to function" );
		else {
			type = DECREF(type);
			if( ISFTN(type) || ISARY(type) || ISPTR(type) ) {
				uerror( "fortran function has wrong type" );
				}
			}
	case STNAME:
	case UNAME:
	case ENAME:
	case EXTERN:
	case STATIC:
	case EXTDEF:
	case TYPEDEF:
	case USTATIC:
		return( class );

	default:
		cerror( "illegal class: %d", class );
		/* NOTREACHED */

		}
	}

struct symtab *
mknonuniq(idindex) int *idindex; {/* locate a symbol table entry for */
	/* an occurrence of a nonunique structure member name */
	/* or field */
	register i;
	register struct symtab * sp;
	char *p,*q;

	sp = & stab[ i= *idindex ]; /* position search at old entry */
	while( sp->stype != TNULL ){ /* locate unused entry */
		if( ++i >= SYMTSZ ){/* wrap around symbol table */
			i = 0;
			sp = stab;
			}
		else ++sp;
		if( i == *idindex ) cerror("Symbol table full");
		}
	sp->sflags = SNONUNIQ | SMOS;
	p = sp->sname;
	q = stab[*idindex].sname; /* old entry name */
# ifndef BUG1
	if( ddebug ){
		printf("\tnonunique entry for %s from %d to %d\n",
			q, *idindex, i );
		}
# endif
	*idindex = i;
	for( i=1; i<=NCHNAM; ++i ){ /* copy name */
		if( *p++ = *q /* assign */ ) ++q;
		}
	return ( sp );
	}

lookup( name, s) char *name; { 
	/* look up name: must agree with s w.r.t. STAG, SMOS and SHIDDEN */

	register char *p, *q;
	int i, j, ii;
	register struct symtab *sp;

	/* compute initial hash index */
# ifndef BUG1
	if( ddebug > 2 ){
		printf( "lookup( %.*s, %d ), stwart=%d, instruct=%d\n", NCHNAM, name, s, stwart, instruct );
		}
# endif

	i = 0;
	for( p=name, j=0; *p != '\0'; ++p ){
		i = (i<<1)+*p;
		if( ++j >= NCHNAM ) break;
		}
	i = i%SYMTSZ;
	if (i < 0) i = -i;	/* in case hash overflowed */
	sp = &stab[ii=i];

	for(;;){ /* look for name */

		if( sp->stype == TNULL ){ /* empty slot */
			p = sp->sname;
			sp->sflags = s;  /* set STAG, SMOS if needed, turn off all others */
			for( j=0; j<NCHNAM; ++j ) if( *p++ = *name ) ++name;
			sp->stype = UNDEF;
			sp->sclass = SNULL;
			return( i );
			}
		if( (sp->sflags & (STAG|SMOS|SHIDDEN)) != s ) goto next;
		p = sp->sname;
		q = name;
		for( j=0; j<NCHNAM;++j ){
			if( *p++ != *q ) goto next;
			if( !*q++ ) break;
			}
		return( i );
	next:
		if( ++i >= SYMTSZ ){
			i = 0;
			sp = stab;
			}
		else ++sp;
		if( i == ii ) cerror( "symbol table full" );
		}
	}

#ifndef checkst
/* if not debugging, make checkst a macro */
checkst(lev){
	register int s, i, j;
	register struct symtab *p, *q;

	for( i=0, p=stab; i<SYMTSZ; ++i, ++p ){
		if( p->stype == TNULL ) continue;
		j = lookup( p->sname, p->sflags&(SMOS|STAG) );
		if( j != i ){
			q = &stab[j];
			if( q->stype == UNDEF ||
			    q->slevel <= p->slevel ){
				cerror( "check error: %.*s", NCHNAM, q->sname );
				}
			}
		else if( p->slevel > lev ) cerror( "%.*s check at level %d", NCHNAM, p->sname, lev );
		}
	}
#endif

struct symtab *
relook(p) register struct symtab *p; {  /* look up p again, and see where it lies */

	register struct symtab *q;

	/* I'm not sure that this handles towers of several hidden definitions in all cases */
	q = &stab[lookup( p->sname, p->sflags&(STAG|SMOS|SHIDDEN) )];
	/* make relook always point to either p or an empty cell */
	if( q->stype == UNDEF ){
		q->stype = TNULL;
		return(q);
		}
	while( q != p ){
		if( q->stype == TNULL ) break;
		if( ++q >= &stab[SYMTSZ] ) q=stab;
		}
	return(q);
	}

clearst( lev ){ /* clear entries of internal scope  from the symbol table */
	register struct symtab *p, *q, *r;
	register int temp, rehash;

	temp = lineno;
	aobeg();

	/* first, find an empty slot to prevent newly hashed entries from
	   being slopped into... */

	for( q=stab; q< &stab[SYMTSZ]; ++q ){
		if( q->stype == TNULL )goto search;
		}

	cerror( "symbol table full");

	search:
	p = q;

	for(;;){
		if( p->stype == TNULL ) {
			rehash = 0;
			goto next;
			}
		lineno = p->suse;
		if( lineno < 0 ) lineno = - lineno;
		if( p->slevel>lev ){ /* must clobber */
			if( p->stype == UNDEF || ( p->sclass == ULABEL && lev < 2 ) ){
				lineno = temp;
				uerror( "%.*s undefined", NCHNAM, p->sname );
				}
			else aocode(p);
# ifndef BUG1
			if (ddebug) printf("removing %*s from stab[ %d], flags %o level %d\n",
				NCHNAM,p->sname,p-stab,p->sflags,p->slevel);
# endif
			if( p->sflags & SHIDES ) unhide(p);
			p->stype = TNULL;
			rehash = 1;
			goto next;
			}
		if( rehash ){
			if( (r=relook(p)) != p ){
				movestab( r, p );
				p->stype = TNULL;
				}
			}
		next:
		if( ++p >= &stab[SYMTSZ] ) p = stab;
		if( p == q ) break;
		}
	lineno = temp;
	aoend();
	}

movestab( p, q ) register struct symtab *p, *q; {
	int k;
	/* structure assignment: *p = *q; */
	p->stype = q->stype;
	p->sclass = q->sclass;
	p->slevel = q->slevel;
	p->offset = q->offset;
	p->sflags = q->sflags;
	p->dimoff = q->dimoff;
	p->sizoff = q->sizoff;
	p->suse = q->suse;
	for( k=0; k<NCHNAM; ++k ){
		p->sname[k] = q->sname[k];
		}
	}

hide( p ) register struct symtab *p; {
	register struct symtab *q;
	for( q=p+1; ; ++q ){
		if( q >= &stab[SYMTSZ] ) q = stab;
		if( q == p ) cerror( "symbol table full" );
		if( q->stype == TNULL ) break;
		}
	movestab( q, p );
	p->sflags |= SHIDDEN;
	q->sflags = (p->sflags&(SMOS|STAG)) | SHIDES;
	if( hflag ) werror( "%.*s redefinition hides earlier one", NCHNAM, p->sname );
# ifndef BUG1
	if( ddebug ) printf( "	%d hidden in %d\n", p-stab, q-stab );
# endif
	return( idname = q-stab );
	}

unhide( p ) register struct symtab *p; {
	register struct symtab *q;
	register s, j;

	s = p->sflags & (SMOS|STAG);
	q = p;

	for(;;){

		if( q == stab ) q = &stab[SYMTSZ-1];
		else --q;

		if( q == p ) break;

		if( (q->sflags&(SMOS|STAG)) == s ){
			for( j =0; j<NCHNAM; ++j ) if( p->sname[j] != q->sname[j] ) break;
			if( j == NCHNAM ){ /* found the name */
				q->sflags &= ~SHIDDEN;
# ifndef BUG1
				if( ddebug ) printf( "unhide uncovered %d from %d\n", q-stab,p-stab);
# endif
				return;
				}
			}

		}
	cerror( "unhide fails" );
	}
tab *p; {
	register struct symtab *q;
	regic86/reader.c                                                                                           666      26      12        61606  3227205644   6127                                                                                                                                                                                                                                                                                                                                                                      # include "mfile2"

/*	some storage declarations */

# ifndef ONEPASS
NODE node[TREESZ];
char filename[100] = "";  /* the name of the file */
int ftnno;  /* number of current function */
int lineno;
# else
# define NOMAIN
#endif

int nrecur;
int lflag;
int edebug = 0;
int xdebug = 0;
int udebug = 0;

OFFSZ tmpoff;  /* offset for first temporary, in bits for current block */
OFFSZ maxoff;  /* maximum temporary offset over all blocks in current ftn, in bits */
int maxtreg;

NODE *stotree;
int stocook;

OFFSZ baseoff = 0;
OFFSZ maxtemp = 0;

p2init( argc, argv ) char *argv[];{
	/* set the values of the pass 2 arguments */

	register int c;
	register char *cp;
	register files;

	allo0();  /* free all regs */
	files = 0;

	for( c=1; c<argc; ++c ){
		if( *(cp=argv[c]) == '-' ){
			while( *++cp ){
				switch( *cp ){

				case 'X':  /* pass1 flags */
					while( *++cp ) { /* VOID */ }
					--cp;
					break;

				case 'l':  /* linenos */
					++lflag;
					break;

				case 'e':  /* expressions */
					++edebug;
					break;

				case 'o':  /* orders */
					++odebug;
					break;

				case 'r':  /* register allocation */
					++rdebug;
					break;

				case 'a':  /* rallo */
					++radebug;
					break;

				case 't':  /* ttype calls */
					++tdebug;
					break;

				case 's':  /* shapes */
					++sdebug;
					break;

				case 'u':  /* Sethi-Ullman testing (machine dependent) */
					++udebug;
					break;

				case 'x':  /* general machine-dependent debugging flag */
					++xdebug;
					break;

				default:
					cerror( "bad option: %c", *cp );
					}
				}
			}
		else files = 1;  /* assumed to be a filename */
		}

	mkdope();
	setrew();
	return( files );

	}

# ifndef NOMAIN

mainp2( argc, argv ) char *argv[]; {
	register files;
	register temp;
	register c;
	register char *cp;
	register NODE *p;

	files = p2init( argc, argv );
	tinit();

	reread:

	if( files ){
		while( files < argc && argv[files][0] == '-' ) {
			++files;
			}
		if( files > argc ) return( nerrors );
		freopen( argv[files], "r", stdin );
		}
	while( (c=getchar()) > 0 ) switch( c ){
	case ')':
		/* copy line unchanged */
		while( (c=getchar()) > 0 ){
			PUTCHAR(c);
			if( c == '\n' ) break;
			}
		continue;

	case '[':
		/* beginning of a block */
		temp = rdin(10);  /* ftnno */
		tmpoff = baseoff = rdin(10); /* autooff for block gives max offset of autos in block */
		maxtreg = rdin(10);
		if( getchar() != '\n' ) cerror( "intermediate file format error");

		if( temp != ftnno ){ /* beginning of function */
			maxoff = baseoff;
			ftnno = temp;
			maxtemp = 0;
			}
		else {
			if( baseoff > maxoff ) maxoff = baseoff;
			/* maxoff at end of ftn is max of autos and temps
			   over all blocks in the function */
			}
		setregs();
		continue;

	case ']':  /* end of block */
		SETOFF( maxoff, ALSTACK );
		eobl2();
		while( (c=getchar()) != '\n' ){
			if( c <= 0 ) cerror( "intermediate file format eof" );
			}
		continue;

	case '.':
		/* compile code for an expression */
		lineno = rdin( 10 );
		for( cp=filename; (*cp=getchar()) != '\n'; ++cp ) ; /* VOID, reads filename */
		*cp = '\0';
		if( lflag ) lineid( lineno, filename );

		tmpoff = baseoff;  /* expression at top level reuses temps */
		p = eread();

# ifndef BUG4
		if( edebug ) fwalk( p, eprint, 0 );
# endif

# ifdef MYREADER
		MYREADER(p);  /* do your own laundering of the input */
# endif

		nrecur = 0;
		delay( p );  /* expression statement  throws out results */
		reclaim( p, RNULL, 0 );

		allchk();
		tcheck();
		continue;

	default:
		cerror( "intermediate file format error" );

		}

	/* EOF */
	if( files ) goto reread;
	return(nerrors);

	}

# endif

# ifdef ONEPASS

p2compile( p ) NODE *p; {

	if( lflag ) lineid( lineno, filename );
	tmpoff = baseoff;  /* expression at top level reuses temps */
	/* generate code for the tree p */
# ifndef BUG4
	if( edebug ) fwalk( p, eprint, 0 );
# endif

# ifdef MYREADER
	MYREADER(p);  /* do your own laundering of the input */
# endif
	nrecur = 0;
	delay( p );  /* do the code generation */
	reclaim( p, RNULL, 0 );
	allchk();
	/* can't do tcheck here; some stuff (e.g., attributes) may be around from first pass */
	/* first pass will do it... */
	}

p2bbeg( aoff, myreg ) {
	static int myftn = -1;
	tmpoff = baseoff = aoff;
	maxtreg = myreg;
	if( myftn != ftnno ){ /* beginning of function */
		maxoff = baseoff;
		myftn = ftnno;
		maxtemp = 0;
		}
	else {
		if( baseoff > maxoff ) maxoff = baseoff;
		/* maxoff at end of ftn is max of autos and temps over all blocks */
		}
	setregs();
	}

p2bend(){
	SETOFF( maxoff, ALSTACK );
	eobl2();
	}

# endif

NODE *deltrees[DELAYS];
int deli;

delay( p ) register NODE *p; {
	/* look in all legal places for COMOP's and ++ and -- ops to delay */
	/* note; don't delay ++ and -- within calls or things like
	/* getchar (in their macro forms) will start behaving strangely */
	register i;

	/* look for visible COMOPS, and rewrite repeatedly */

	while( delay1( p ) ) { /* VOID */ }

	/* look for visible, delayable ++ and -- */

	deli = 0;
	delay2( p );
	codgen( p, FOREFF );  /* do what is left */
	for( i = 0; i<deli; ++i ) codgen( deltrees[i], FOREFF );  /* do the rest */
	}

delay1( p ) register NODE *p; {  /* look for COMOPS */
	register o, ty;

	o = p->in.op;
	ty = optype( o );
	if( ty == LTYPE ) return( 0 );
	else if( ty == UTYPE ) return( delay1( p->in.left ) );

	switch( o ){

	case QUEST:
	case ANDAND:
	case OROR:
		/* don't look on RHS */
		return( delay1(p->in.left ) );

	case COMOP:  /* the meat of the routine */
		delay( p->in.left );  /* completely evaluate the LHS */
		/* rewrite the COMOP */
		{ register NODE *q;
			q = p->in.right;
			ncopy( p, p->in.right );
			q->in.op = FREE;
			}
		return( 1 );
		}

	return( delay1(p->in.left) || delay1(p->in.right ) );
	}

delay2( p ) register NODE *p; {

	/* look for delayable ++ and -- operators */

	register o, ty;
	o = p->in.op;
	ty = optype( o );

	switch( o ){

	case NOT:
	case QUEST:
	case ANDAND:
	case OROR:
	case CALL:
	case UNARY CALL:
	case STCALL:
	case UNARY STCALL:
	case FORTCALL:
	case UNARY FORTCALL:
	case COMOP:
	case CBRANCH:
		/* for the moment, don7t delay past a conditional context, or
		/* inside of a call */
		return;

	case INCR:
	case DECR:
		if( deltest( p ) ){
			if( deli < DELAYS ){
				register NODE *q;
				deltrees[deli++] = tcopy(p);
				q = p->in.left;
				p->in.right->in.op = FREE;  /* zap constant */
				ncopy( p, q );
				q->in.op = FREE;
				return;
				}
			}

		}

	if( ty == BITYPE ) delay2( p->in.right );
	if( ty != LTYPE ) delay2( p->in.left );
	}

codgen( p, cookie ) NODE *p; {

	/* generate the code for p;
	   order may call codgen recursively */
	/* cookie is used to describe the context */

	for(;;){
		canon(p);  /* creats OREG from * if possible and does sucomp */
		stotree = NIL;
# ifndef BUG4
		if( edebug ){
			printf( "store called on:\n" );
			fwalk( p, eprint, 0 );
			}
# endif
		store(p);
		if( stotree==NIL ) break;

		/* because it's minimal, can do w.o. stores */

		order( stotree, stocook );
		}

	order( p, cookie );

	}

# ifndef BUG4
char *cnames[] = {
	"SANY",
	"SAREG",
	"STAREG",
	"SBREG",
	"STBREG",
	"SCC",
	"SNAME",
	"SCON",
	"SFLD",
	"SOREG",
	"STARNM",
	"STARREG",
	"INTEMP",
	"FORARG",
	"SWADD",
	0,
	};

prcook( cookie ){

	/* print a nice-looking description of cookie */

	int i, flag;

	if( cookie & SPECIAL ){
		if( cookie == SZERO ) printf( "SZERO" );
		else if( cookie == SONE ) printf( "SONE" );
		else if( cookie == SMONE ) printf( "SMONE" );
		else printf( "SPECIAL+%d", cookie & ~SPECIAL );
		return;
		}

	flag = 0;
	for( i=0; cnames[i]; ++i ){
		if( cookie & (1<<i) ){
			if( flag ) printf( "|" );
			++flag;
			printf( cnames[i] );
			}
		}

	}
# endif

int odebug = 0;

order(p,cook) NODE *p; {

	register o, ty, m;
	int m1;
	int cookie;
	NODE *p1, *p2;

	cookie = cook;
	rcount();
	canon(p);
	rallo( p, p->in.rall );
	goto first;
	/* by this time, p should be able to be generated without stores;
	   the only question is how */

	again:

	cookie = cook;
	rcount();
	canon(p);
	rallo( p, p->in.rall );
	/* if any rewriting and canonicalization has put
	 * the tree (p) into a shape that cook is happy
	 * with (exclusive of FOREFF, FORREW, and INTEMP)
	 * then we are done.
	 * this allows us to call order with shapes in
	 * addition to cookies and stop short if possible.
	 */
	if( tshape(p, cook &(~(FOREFF|FORREW|INTEMP))) )return;

	first:
# ifndef BUG4
	if( odebug ){
		printf( "order( %o, ", p );
		prcook( cookie );
		printf( " )\n" );
		fwalk( p, eprint, 0 );
		}
# endif

	o = p->in.op;
	ty = optype(o);

	/* first of all, for most ops, see if it is in the table */

	/* look for ops */

	switch( m = p->in.op ){

	default:
		/* look for op in table */
		for(;;){
			if( (m = match( p, cookie ) ) == MDONE ) goto cleanup;
			else if( m == MNOPE ){
				if( !(cookie = nextcook( p, cookie ) ) ) goto nomat;
				continue;
				}
			else break;
			}
		break;

	case COMOP:
	case FORCE:
	case CBRANCH:
	case QUEST:
	case ANDAND:
	case OROR:
	case NOT:
	case UNARY CALL:
	case CALL:
	case UNARY STCALL:
	case STCALL:
	case UNARY FORTCALL:
	case FORTCALL:
		/* don't even go near the table... */
		;

		}
	/* get here to do rewriting if no match or
	   fall through from above for hard ops */

	p1 = p->in.left;
	if( ty == BITYPE ) p2 = p->in.right;
	else p2 = NIL;
	
# ifndef BUG4
	if( odebug ){
		printf( "order( %o, ", p );
		prcook( cook );
		printf( " ), cookie " );
		prcook( cookie );
		printf( ", rewrite %s\n", opst[m] );
		}
# endif
	switch( m ){
	default:
		nomat:
		printf( "order( %o, ", p );
		prcook( cookie );
		printf( " )\n" );
		fwalk( p, eprint, 0 );
		cerror( "no table entry for op %s", opst[p->in.op] );

	case COMOP:
		codgen( p1, FOREFF );
		p2->in.rall = p->in.rall;
		codgen( p2, cookie );
		ncopy( p, p2 );
		p2->in.op = FREE;
		goto cleanup;

	case FORCE:
		/* recurse, letting the work be done by rallo */
		if ((p->in.left->in.type==DOUBLE||p->in.left->in.type==FLOAT) && p->in.left->in.su!=0)
		  order( p->in.left, INTEMP );
		p = p->in.left;
		cook = INTAREG;
		goto again;

	case CBRANCH:
		o = p2->tn.lval;
		cbranch( p1, -1, o );
		p2->in.op = FREE;
		p->in.op = FREE;
		return;

	case QUEST:
		cbranch( p1, -1, m=getlab() );
		p2->in.left->in.rall = p->in.rall;
		codgen( p2->in.left, INTAREG );
		/* force right to compute result into same reg used by left */
		p2->in.right->in.rall = p2->in.left->tn.rval|MUSTDO;
		reclaim( p2->in.left, RNULL, 0 );
		cbgen( 0, m1 = getlab(), 'I' );
		deflab( m );
		codgen( p2->in.right, INTAREG );
		deflab( m1 );
		p->in.op = REG;  /* set up node describing result */
		p->tn.lval = 0;
		p->tn.rval = p2->in.right->tn.rval;
		p->in.type = p2->in.right->in.type;
		tfree( p2->in.right );
		p2->in.op = FREE;
		goto cleanup;

	case ANDAND:
	case OROR:
	case NOT:  /* logical operators */
		/* if here, must be a logical operator for 0-1 value */
		cbranch( p, -1, m=getlab() );
		p->in.op = CCODES;
		p->bn.label = m;
		order( p, INTAREG );
		goto cleanup;

	case FLD:	/* fields of funny type */
		if ( p1->in.op == UNARY MUL ){
			offstar( p1->in.left, cookie );
			goto again;
			}

	case UNARY MINUS:
		order( p1, (p1->in.type==DOUBLE||p1->in.type==FLOAT) ? INTEMP : INTAREG );
		goto again;

	case NAME:
		/* all leaves end up here ... */
		if( o == REG ) goto nomat;
		order( p, (p->in.type==DOUBLE||p->in.type==FLOAT) ? INTEMP : INTAREG );
		goto again;

	case INIT:
		uerror( "illegal initialization" );
		return;

	case UNARY FORTCALL:
		p->in.right = NIL;
	case FORTCALL:
		o = p->in.op = UNARY FORTCALL;
		if( genfcall( p, cookie ) ) goto nomat;
		goto cleanup;

	case UNARY CALL:
		p->in.right = NIL;
	case CALL:
		o = p->in.op = UNARY CALL;
		if( gencall( p, cookie ) ) goto nomat;
		goto cleanup;

	case UNARY STCALL:
		p->in.right = NIL;
	case STCALL:
		o = p->in.op = UNARY STCALL;
		if( genscall( p, cookie ) ) goto nomat;
		goto cleanup;

		/* if arguments are passed in register, care must be taken that reclaim
		/* not throw away the register which now has the result... */

	case UNARY MUL:
		if( cook == FOREFF ){
			/* do nothing */
			order( p->in.left, FOREFF );
			p->in.op = FREE;
			return;
			}
		offstar( p->in.left, cookie );
		goto again;

	case INCR:  /* INCR and DECR */
		if( setincr(p, cookie) ) goto again;

		/* x++ becomes (x += 1) -1; */

		if( cook & FOREFF ){  /* result not needed so inc or dec and be done with it */
			/* x++ => x += 1 */
			p->in.op = (p->in.op==INCR)?ASG PLUS:ASG MINUS;
			goto again;
			}

		p1 = tcopy(p);
		reclaim( p->in.left, RNULL, 0 );
		p->in.left = p1;
		p1->in.op = (p->in.op==INCR)?ASG PLUS:ASG MINUS;
		p->in.op = (p->in.op==INCR)?MINUS:PLUS;
		goto again;

	case STASG:
		if( setstr( p, cookie ) ) goto again;
		goto nomat;

	case ASG PLUS:  /* and other assignment ops */
		if( setasop(p, cookie) ) goto again;

		/* there are assumed to be no side effects in LHS */

		p2 = tcopy(p);
		p->in.op = ASSIGN;
		reclaim( p->in.right, RNULL, 0 );
		p->in.right = p2;
		canon(p);
		rallo( p, p->in.rall );

# ifndef BUG4
		if( odebug ) fwalk( p, eprint, 0 );
# endif

		order( p2->in.left, INTAREG );
		order( p2, INTAREG );
		goto again;

	case ASSIGN:
		if( setasg( p, cookie ) ) goto again;
		goto nomat;


	case BITYPE:
		if( setbin( p, cookie ) ) goto again;
		/* try to replace binary ops by =ops */
		switch(o){

		case PLUS:
		case MINUS:
		case MUL:
		case DIV:
		case MOD:
		case AND:
		case OR:
		case ER:
		case LS:
		case RS:
			p->in.op = ASG o;
			goto again;
			}
		goto nomat;

		}

	cleanup:

	/* if it is not yet in the right state, put it there */

	if( cook & FOREFF ){
		reclaim( p, RNULL, 0 );
		return;
		}

	if( p->in.op==FREE ) return;

	if( tshape( p, cook ) ) return;

	if( (m=match(p,cook) ) == MDONE ) return;

	/* we are in bad shape, try one last chance */
	if( lastchance( p, cook ) ) goto again;

	goto nomat;
	}

int callflag;
int fregs;

store( p ) register NODE *p; {

	/* find a subtree of p which should be stored */

	register o, ty;

	o = p->in.op;
	ty = optype(o);

	if( ty == LTYPE ) return;

	switch( o ){

	case ASG MUL:
	case ASG DIV:
	case ASG MOD:
		return;

	case UNARY CALL:
	case UNARY FORTCALL:
	case UNARY STCALL:
		++callflag;
		break;

	case UNARY MUL:
		if( asgop(p->in.left->in.op) ) stoasg( p->in.left, UNARY MUL );
		break;

	case CALL:
	case FORTCALL:
	case STCALL:
		store( p->in.left );
		stoarg( p->in.right, o );
		++callflag;
		return;

	case COMOP:
		markcall( p->in.right );
		if( p->in.right->in.su > fregs ) SETSTO( p, INTEMP );
		store( p->in.left );
		return;

	case ANDAND:
	case OROR:
	case QUEST:
		markcall( p->in.right );
		if( p->in.right->in.su > fregs ) SETSTO( p, INTEMP );
	case CBRANCH:   /* to prevent complicated expressions on the LHS from being stored */
	case NOT:
		constore( p->in.left );
		return;

		}

	if( ty == UTYPE ){
		store( p->in.left );
		return;
		}

	if( asgop( p->in.right->in.op ) ) stoasg( p->in.right, o );

	if( p->in.su>fregs ){ /* must store */
		mkadrs( p );  /* set up stotree and stocook to subtree
				 that must be stored */
		}

	store( p->in.right );
	store( p->in.left );
	}

constore( p ) register NODE *p; {

	/* store conditional expressions */
	/* the point is, avoid storing expressions in conditional
	   conditional context, since the evaluation order is predetermined */

	switch( p->in.op ) {

	case ANDAND:
	case OROR:
	case QUEST:
		markcall( p->in.right );
	case NOT:
		constore( p->in.left );
		return;

		}

	store( p );
	}

markcall( p ) register NODE *p; {  /* mark off calls below the current node */

	again:
	switch( p->in.op ){

	case UNARY CALL:
	case UNARY STCALL:
	case UNARY FORTCALL:
	case CALL:
	case STCALL:
	case FORTCALL:
		++callflag;
		return;

		}

	switch( optype( p->in.op ) ){

	case BITYPE:
		markcall( p->in.right );
	case UTYPE:
		p = p->in.left;
		/* eliminate recursion (aren't I clever...) */
		goto again;
	case LTYPE:
		return;
		}

	}

stoarg( p, calltype ) register NODE *p; {
	/* arrange to store the args */

	if( p->in.op == CM ){
		stoarg( p->in.left, calltype );
		p = p->in.right ;
		}
	if( calltype == CALL ){
		STOARG(p);
		}
	else if( calltype == STCALL ){
		STOSTARG(p);
		}
	else {
		STOFARG(p);
		}
	callflag = 0;
	store(p);
# ifndef NESTCALLS
	if( callflag ){ /* prevent two calls from being active at once  */
		SETSTO(p,INTEMP);
		store(p); /* do again to preserve bottom up nature....  */
		}
#endif
	}

int negrel[] = { NE, EQ, GT, GE, LT, LE, UGT, UGE, ULT, ULE } ;  /* negatives of relationals */

cbranch( p, true, false ) NODE *p; {
	/* evaluate p for truth value, and branch to true or false
	/* accordingly: label <0 means fall through */

	register o, lab, flab, tlab;

	lab = -1;

	switch( o=p->in.op ){

	case ULE:
	case ULT:
	case UGE:
	case UGT:
	case EQ:
	case NE:
	case LE:
	case LT:
	case GE:
	case GT:
		if( true < 0 ){
			o = p->in.op = negrel[ o-EQ ];
			true = false;
			false = -1;
			}
#ifndef NOOPT
		if( p->in.right->in.op == ICON && p->in.right->tn.lval == 0 && p->in.right->in.name[0] == '\0' && p->in.right->in.type!=LONG && p->in.right->in.type!=ULONG){
			switch( o ){

			case UGT:
			case ULE:
				o = p->in.op = (o==UGT)?NE:EQ;
			case EQ:
			case NE:
			case LE:
			case LT:
			case GE:
			case GT:
				if( logop(p->in.left->in.op) ){
					/* strange situation: e.g., (a!=0) == 0 */
					/* must prevent reference to p->in.left->lable, so get 0/1 */
					/* we could optimize, but why bother */
					codgen( p->in.left, INAREG );
					}
				codgen( p->in.left, FORCC );
				cbgen( o, true, 'I' );
				break;

			case UGE:
				codgen(p->in.left, FORCC);
				cbgen( 0, true, 'I' );  /* unconditional branch */
				break;
			case ULT:
				codgen(p->in.left, FORCC);
				}
			}
		else
#endif
			{
			p->bn.label = true;
			codgen( p, FORCC );
			}
		if( false>=0 ) cbgen( 0, false, 'I' );
		reclaim( p, RNULL, 0 );
		return;

	case ANDAND:
		lab = false<0 ? getlab() : false ;
		cbranch( p->in.left, -1, lab );
		cbranch( p->in.right, true, false );
		if( false < 0 ) deflab( lab );
		p->in.op = FREE;
		return;

	case OROR:
		lab = true<0 ? getlab() : true;
		cbranch( p->in.left, lab, -1 );
		cbranch( p->in.right, true, false );
		if( true < 0 ) deflab( lab );
		p->in.op = FREE;
		return;

	case NOT:
		cbranch( p->in.left, false, true );
		p->in.op = FREE;
		break;

	case COMOP:
		codgen( p->in.left, FOREFF );
		p->in.op = FREE;
		cbranch( p->in.right, true, false );
		return;

	case QUEST:
		flab = false<0 ? getlab() : false;
		tlab = true<0 ? getlab() : true;
		cbranch( p->in.left, -1, lab = getlab() );
		cbranch( p->in.right->in.left, tlab, flab );
		deflab( lab );
		cbranch( p->in.right->in.right, true, false );
		if( true < 0 ) deflab( tlab);
		if( false < 0 ) deflab( flab );
		p->in.right->in.op = FREE;
		p->in.op = FREE;
		return;

	case ICON:
		if( p->in.type != FLOAT && p->in.type != DOUBLE ){

			if( p->tn.lval || p->in.name[0] ){
				/* addresses of C objects are never 0 */
				if( true>=0 ) cbgen( 0, true, 'I' );
				}
			else if( false>=0 ) cbgen( 0, false, 'I' );
			p->in.op = FREE;
			return;
			}
		/* fall through to default with other strange constants */

	default:
		/* get condition codes */
		codgen( p, FORCC );
		if( true >= 0 ) cbgen( NE, true, 'I' );
		if( false >= 0 ) cbgen( true >= 0 ? 0 : EQ, false, 'I' );
		reclaim( p, RNULL, 0 );
		return;

		}

	}

rcount(){ /* count recursions */
	if( ++nrecur > NRECUR ){
		cerror( "expression causes compiler loop: try simplifying" );
		}

	}

# ifndef BUG4
eprint( p, down, a, b ) NODE *p; int *a, *b; {

	*a = *b = down+1;
	while( down >= 2 ){
		printf( "\t" );
		down -= 2;
		}
	if( down-- ) printf( "    " );


	printf( "%o) %s", p, opst[p->in.op] );
	switch( p->in.op ) { /* special cases */

	case REG:
		printf( " %s", rnames[p->tn.rval] );
		break;

	case ICON:
	case NAME:
	case OREG:
		printf( " " );
		adrput( p );
		break;

	case STCALL:
	case UNARY STCALL:
	case STARG:
	case STASG:
		printf( " size=%d", p->stn.stsize );
		printf( " align=%d", p->stn.stalign );
		break;
		}

	printf( ", " );
	tprint( p->in.type );
	printf( ", " );
	if( p->in.rall == NOPREF ) printf( "NOPREF" );
	else {
		if( p->in.rall & MUSTDO ) printf( "MUSTDO " );
		else printf( "PREF " );
		printf( "%s", rnames[p->in.rall&~MUSTDO]);
		}
	printf( ", SU= %d\n", p->in.su );

	}
# endif

# ifndef NOMAIN
NODE *
eread(){

	/* call eread recursively to get subtrees, if any */

	register NODE *p;
	register i, c;
	register char *pc;
	register j;

	i = rdin( 10 );

	p = talloc();

	p->in.op = i;

	i = optype(i);

	if( i == LTYPE ) p->tn.lval = rdin( 10 );
	if( i != BITYPE ) p->tn.rval = rdin( 10 );

	p->in.type = rdin(8 );
	p->in.rall = NOPREF;  /* register allocation information */

	if( p->in.op == STASG || p->in.op == STARG || p->in.op == STCALL || p->in.op == UNARY STCALL ){
		p->stn.stsize = (rdin( 10 ) + (SZCHAR-1) )/SZCHAR;
		p->stn.stalign = rdin(10) / SZCHAR;
		if( getchar() != '\n' ) cerror( "illegal \n" );
		}
	else {   /* usual case */
		if( p->in.op == REG ) rbusy( p->tn.rval, p->in.type );  /* non usually, but sometimes justified */
		for( pc=p->in.name,j=0; ( c = getchar() ) != '\n'; ++j ){
			if( j < NCHNAM ) *pc++ = c;
			}
		if( j < NCHNAM ) *pc = '\0';
		}

	/* now, recursively read descendents, if any */

	if( i != LTYPE ) p->in.left = eread();
	if( i == BITYPE ) p->in.right = eread();

	return( p );

	}

CONSZ
rdin( base ){
	register sign, c;
	CONSZ val;

	sign = 1;
	val = 0;

	while( (c=getchar()) > 0 ) {
		if( c == '-' ){
			if( val != 0 ) cerror( "illegal -");
			sign = -sign;
			continue;
			}
		if( c == '\t' ) break;
		if( c>='0' && c<='9' ) {
			val *= base;
			if( sign > 0 )
				val += c-'0';
			else
				val -= c-'0';
			continue;
			}
		cerror( "illegal character `%c' on intermediate file", c );
		break;
		}

	if( c <= 0 ) {
		cerror( "unexpected EOF");
		}
	return( val );
	}
# endif

#ifndef FIELDOPS
	/* do this if there is no special hardware support for fields */

ffld( p, down, down1, down2 ) NODE *p; int *down1, *down2; {
	 /* look for fields that are not in an lvalue context, and rewrite them... */
	register NODE *shp;
	register s, o, v, ty;

	*down1 =  asgop( p->in.op );
	*down2 = 0;

	if( !down && p->in.op == FLD ){ /* rewrite the node */

		if( !rewfld(p) ) return;

		ty = (szty(p->in.type) == 2)? LONG: INT;
		v = p->tn.rval;
		s = UPKFSZ(v);
# ifdef RTOLBYTES
		o = UPKFOFF(v);  /* amount to shift */
# else
		o = szty(p->in.type)*SZINT - s - UPKFOFF(v);  /* amount to shift */
#endif

		/* make & mask part */

		p->in.left->in.type = ty;

		p->in.op = AND;
		p->in.right = talloc();
		p->in.right->in.op = ICON;
		p->in.right->in.rall = NOPREF;
		p->in.right->in.type = ty;
		p->in.right->tn.lval = 1;
		p->in.right->tn.rval = 0;
		p->in.right->in.name[0] = '\0';
		p->in.right->tn.lval <<= s;
		p->in.right->tn.lval--;

		/* now, if a shift is needed, do it */

		if( o != 0 ){
			shp = talloc();
			shp->in.op = RS;
			shp->in.rall = NOPREF;
			shp->in.type = ty;
			shp->in.left = p->in.left;
			shp->in.right = talloc();
			shp->in.right->in.op = ICON;
			shp->in.right->in.rall = NOPREF;
			shp->in.right->in.type = ty;
			shp->in.right->tn.rval = 0;
			shp->in.right->tn.lval = o;  /* amount to shift */
			shp->in.right->in.name[0] = '\0';
			p->in.left = shp;
			/* whew! */
			}
		}
	}
#endif

oreg2( p ) register NODE *p; {

	/* look for situations where we can turn * into OREG */

	NODE *q;
	register i;
	register r;
	register char *cp;
	register NODE *ql, *qr;
	CONSZ temp;

	if( p->in.op == UNARY MUL ){
		q = p->in.left;
		if( q->in.op == REG ){
			temp = q->tn.lval;
			r = q->tn.rval;
			cp = q->in.name;
			goto ormake;
			}

		if( q->in.op != PLUS && q->in.op != MINUS ) return;
		ql = q->in.left;
		qr = q->in.right;

#ifdef R2REGS

		/* look for doubly indexed expressions */

		if( q->in.op==PLUS && qr->in.op==REG && ql->in.op==REG &&
				(szty(ql->in.type)==1||szty(qr->in.type)==1) ) {
			temp = 0;
			cp = ql->in.name;
			if( *cp ){
				if( *qr->in.name ) return;
				}
			else {
				cp = qr->in.name;
				}
			if( szty(qr->in.type)>1) r = R2PACK(qr->tn.rval,ql->tn.rval);
			else r = R2PACK(ql->tn.rval,qr->tn.rval);
			goto ormake;
			}

		if( (q->in.op==PLUS||q->in.op==MINUS) && qr->in.op==ICON && ql->in.op==PLUS &&
				ql->in.left->in.op==REG &&
				ql->in.right->in.op==REG ){
			temp = qr->tn.lval;
			cp = qr->in.name;
			if( q->in.op == MINUS ){
				if( *cp ) return;
				temp = -temp;
				}
			if( *cp ){
				if( *ql->in.name ) return;
				}
			else {
				cp = ql->in.name;
				}
			r = R2PACK(ql->in.left->tn.rval,ql->in.right->tn.rval);
			goto ormake;
			}

#endif

		if( (q->in.op==PLUS || q->in.op==MINUS) && qr->in.op == ICON &&
				ql->in.op==REG && szty(qr->in.type)==1) {
			temp = qr->tn.lval;
			if( q->in.op == MINUS ) temp = -temp;
			r = ql->tn.rval;
			temp += ql->tn.lval;
			cp = qr->in.name;
			if( *cp && ( q->in.op == MINUS || *ql->in.name ) ) return;
			if( !*cp ) cp = ql->in.name;

			ormake:
			if( notoff( p->in.type, r, temp, cp ) ) return;
			p->in.op = OREG;
			p->tn.rval = r;
			p->tn.lval = temp;
			for( i=0; i<NCHNAM; ++i )
				p->in.name[i] = *cp++;
			tfree(q);
			return;
			}
		}

	}

canon(p) NODE *p; {
	/* put p in canonical form */
	int oreg2(), sucomp();

#ifndef FIELDOPS
	int ffld();
	fwalk( p, ffld, 0 ); /* look for field operators */
# endif
	walkf( p, oreg2 );  /* look for and create OREG nodes */
#ifdef MYCANON
	MYCANON(p);  /* your own canonicalization routine(s) */
#endif
	walkf( p, sucomp );  /* do the Sethi-Ullman computation */

	}

= OREG;
			p->tn.rval = r;
			p->tn.lval = temp;
			for( i=0; i<NCHNAM; ++i )
				p->in.name[i] = *cp++;
			tfree(q);
			rc86/scan.c                                                                                             444      26      12        44701  2537050424   5575                                                                                                                                                                                                                                                                                                                                                                      # include "mfile1"
# include <ctype.h>
	/* temporarily */

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 100
char yytext[LXTSZ];
char * lxgcp;


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

	register i;
	register char *cp;
	extern int idebug, bdebug, tdebug, edebug, ddebug, xdebug;
	extern unsigned int offsz;

	offsz = caloff();
	for( i=1; i<argc; ++i ){
		if( *(cp=argv[i]) == '-' && *++cp == 'X' ){
			while( *++cp ){
				switch( *cp ){

				case 'd':
					++ddebug;
					break;
				case 'i':
					++idebug;
					break;
				case 'b':
					++bdebug;
					break;
				case 't':
					++tdebug;
					break;
				case 'e':
					++edebug;
					break;
				case 'x':
					++xdebug;
					break;
					}
				}
			}
		}

# ifdef ONEPASS
	p2init( argc, argv );
# endif

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

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

	lineno = 1;

	/* dimension table initialization */

	dimtab[NULL] = 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();

	ejobcode( nerrors ? 1 : 0 );
	return(nerrors?1:0);

	}

# ifdef ibm

# define CSMASK 0377
# define CSSZ 256

# else

# define CSMASK 0177
# define CSSZ 128

# endif

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;
			}
		}
	ungetc(c,stdin);
	*(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;

	/* 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 */
	lxtitle();

	}

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

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

	register c;
	register val;
	register i;

	i=0;
	while( (c=getchar()) != lxmatch ){
		switch( c ) {

		case EOF:
			uerror( "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 ungetc( c ,stdin);
					}
				else ungetc( c ,stdin);

				goto mkcc1;

				}
		default:
			val =c;
		mkcc:
			val = CCTRANS(val);
		mkcc1:
			if( lxmatch == '\'' ){
				val = CHARCAST(val);  /* it is, after all, a "character" constant */
				makecc( val, i );
				}
			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( "unexpected EOF" );
			return;

		case '\n':
			++lineno;

		default:
			continue;

		case '*':
			if( (c = getchar()) == '/' ) return;
			else ungetc( c ,stdin);
			continue;

# ifdef LINT
		case 'V':
			lxget( c, LEXLET|LEXDIG );
			{
				extern int vaflag;
				int i;
				i = yytext[7]?yytext[7]-'0':0;
				yytext[7] = '\0';
				if( strcmp( yytext, "VARARGS" ) ) continue;
				vaflag = i;
				continue;
				}
		case 'L':
			lxget( c, LEXLET );
			if( strcmp( yytext, "LINTLIBRARY" ) ) continue;
			{
				extern int libflag;
				libflag = 1;
				}
			continue;

		case 'A':
			lxget( c, LEXLET );
			if( strcmp( yytext, "ARGSUSED" ) ) continue;
			{
				extern int argflag, vflag;
				argflag = 1;
				vflag = 0;
				}
			continue;

		case 'N':
			lxget( c, LEXLET );
			if( strcmp( yytext, "NOTREACHED" ) ) continue;
			reached = 0;
			continue;
# endif
			}
		}
	}

yylex(){
	for(;;){

		register lxchar;
		register struct lxdope *p;
		register struct symtab *sp;
		int id;

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

		onechar:
			ungetc( lxchar ,stdin);

		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, check for reserved word, and return */
			lxget( lxchar, LEXLET|LEXDIG );
			if( (lxchar=lxres()) > 0 ) return( lxchar ); /* reserved word */
			if( lxchar== 0 ) continue;
			id = lookup( 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 */
				{
					register char *cp;
					for( cp = yytext+2; *cp; ++cp ){
						/* this code won't work for all wild 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:
				/* criterion for longness for hex and octal constants is that it
				   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,stdin);
						lxchar = 'e';
						}
					lxmore( lxchar, LEXDIG );
					/* now have the whole thing... */
					}
				else {  /* no exponent */
					ungetc( lxchar ,stdin);
					}
				return( isitfloat( yytext ) );

			default:
				ungetc( lxchar ,stdin);
				if( yytext[0] == '0' ){
					/* convert in octal */
					register char *cp;
					for( cp = yytext+1; *cp; ++cp ){
						lastcon <<= 3;
						lastcon += *cp - '0';
						}
					goto hexlong;
					}
				else {
					/* convert in decimal */
					register char *cp;
					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 plus an extended sign, it is int; otherwise long */
				/* if there is an l or L following, all bets are off... */

				{	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 ,stdin);
				return( ICON );
				}

		case A_DOT:
			/* look for a dot: if followed by a digit, floating point */
			lxchar = getchar();
			if( lxmask[lxchar+1] & LEXDIG ){
				ungetc(lxchar,stdin);
				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_BCD:
			{
				register i;
				int j;
				for( i=0; i<LXTSZ; ++i ){
					if( ( j = getchar() ) == '`' ) break;
					if( j == '\n' ){
						uerror( "newline in BCD constant" );
						break;
						}
					yytext[i] = j;
					}
				yytext[i] = '\0';
				if( i>6 ) uerror( "BCD constant exceeds 6 characters" );
# ifdef gcos
				else strtob( yytext, &lastcon, i );
				lastcon >>= 6*(6-i);
# else
				uerror( "gcos BCD constant illegal" );
# endif
				yylval.intval = 0;  /* not long */
				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 );

			case '+':
				yylval.intval = ASG PLUS;
				break;

			case '-':
				yylval.intval = ASG MINUS;

			warn:
				if( lxmask[ (lxchar=getchar())+1] & (LEXLET|LEXDIG|LEXDOT) ){
					werror( "ambiguous assignment: assignment op taken" );
					}
				ungetc( lxchar ,stdin);
				break;

			case '*':
				yylval.intval = ASG MUL;
				goto warn;

			case '/':
				yylval.intval = ASG DIV;
				break;

			case '%':
				yylval.intval = ASG MOD;
				break;

			case '&':
				yylval.intval = ASG AND;
				break;

			case '|':
				yylval.intval = ASG OR;
				break;

			case '^':
				yylval.intval = ASG ER;
				break;

			case '<':
				if( (lxchar=getchar()) != '<' ){
					uerror( "=<%c illegal", lxchar );
					}
				yylval.intval = ASG LS;
				break;

			case '>':
				if( (lxchar=getchar()) != '>' ){
					uerror( "=>%c illegal", lxchar );
					}
				yylval.intval = ASG RS;
				break;

			default:
				goto onechar;

				}

			return( ASOP );

		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 lxract;	/* reserved word action */
	short lxrval;	/* value to be returned */
	} lxrdope[] = {

	"asm",		AR_A,	0,
	"auto",		AR_CL,	AUTO,
	"break",	AR_RW,	BREAK,
	"char",		AR_TY,	CHAR,
	"case",		AR_RW,	CASE,
	"continue",	AR_RW,	CONTINUE,
	"double",	AR_TY,	DOUBLE,
	"default",	AR_RW,	DEFAULT,
	"do",		AR_RW,	DO,
	"extern",	AR_CL,	EXTERN,
	"else",		AR_RW,	ELSE,
	"enum",		AR_E,	ENUM,
	"for",		AR_RW,	FOR,
	"float",	AR_TY,	FLOAT,
	"fortran",	AR_CL,	FORTRAN,
	"goto",		AR_RW,	GOTO,
	"if",		AR_RW,	IF,
	"int",		AR_TY,	INT,
	"long",		AR_TY,	LONG,
	"return",	AR_RW,	RETURN,
	"register",	AR_CL,	REGISTER,
	"switch",	AR_RW,	SWITCH,
	"struct",	AR_S,	0,
	"sizeof",	AR_RW,	SIZEOF,
	"short",	AR_TY,	SHORT,
	"static",	AR_CL,	STATIC,
	"typedef",	AR_CL,	TYPEDEF,
	"unsigned",	AR_TY,	UNSIGNED,
	"union",	AR_U,	0,
	"void",		AR_TY,	UNDEF, /* tymerge adds FTN */
	"while",	AR_RW,	WHILE,
	"",		0,	0,	/* to stop the search */
	};

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

	register c, ch;
	register struct lxrdope *p;

	ch = yytext[0];

	if( !islower(ch) ) return( -1 );

	switch( ch ){

	case 'a':
		c=0; break;
	case 'b':
		c=2; break;
	case 'c':
		c=3; break;
	case 'd':
		c=6; break;
	case 'e':
		c=9; break;
	case 'f':
		c=12; break;
	case 'g':
		c=15; break;
	case 'i':
		c=16; break;
	case 'l':
		c=18; break;
	case 'r':
		c=19; break;
	case 's':
		c=21; break;
	case 't':
		c=26; break;
	case 'u':
		c=27; break;
	case 'v':
		c=29; break;
	case 'w':
		c=30; break;

	default:
		return( -1 );
		}

	for( p= lxrdope+c; p->lxrch[0] == ch; ++p ){
		if( !strcmp( yytext, p->lxrch ) ){ /* match */
			switch( p->lxract ){

			case AR_TY:
				/* type word */
				stwart = instruct;
				yylval.nodep = mkty( (TWORD)p->lxrval, 0, p->lxrval );
				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;
# ifndef ONEPASS
# ifndef LINT
				putchar(')');
# endif
# endif
				while( (c=getchar()) != '"' ){
					if( c=='\n' || c==EOF ) goto badasm;
# ifndef LINT
					putchar(c);
# endif
					}
				lxget( ' ', LEXWS );
				if( getchar() != ')' ) goto badasm;
# ifndef LINT
				putchar('\n');
# endif
				return( 0 );

			badasm:
				uerror( "bad asm construction" );
				return( 0 );

			default:
				cerror( "bad AR_?? action" );
				}
			}
		}
	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 */
		if( (c=getchar()) != '#' ){
			if( c != EOF ) ungetc(c,stdin);
			return;
			}

		lxget( ' ', LEXWS );
		val = 0;
		for( c=getchar(); isdigit(c); c=getchar() ){
			val = val*10+ c - '0';
			}
		ungetc( c, stdin );
		lineno = val;
		lxget( ' ', LEXWS );
		if( (c=getchar()) != '\n' ){
			for( cp=ftitle; c!='\n'; c=getchar(),++cp ){
				*cp = c;
				}
			*cp = '\0';
			}
		}
	}
line; set linenumber and file name */

	register c, val;
	regisc86/table.c                                                                                            666      26      12        46233  3326552000   5742                                                                                                                                                                                                                                                                                                                                                                      # include "mfile2"

# define EA	SNAME|SOREG|SCON|SAREG|SBREG
# define EREG	SAREG|SBREG
# define FEA	SNAME|SOREG|SCON

struct optab  table[] = {

ASSIGN, INAREG|FOREFF,		/* can't do movb's from SI or DI */	
	EA,	TCHAR|TUCHAR,
	SBREG,	TINT|TPOINT|TUNSIGNED,
		0,	RLEFT,
		"	mov	cx,AR\n	movb	AL,cx\n",

ASSIGN,	INAREG|FOREFF,
	EA,	TPOINT|TINT|TUNSIGNED|TCHAR|TUCHAR,
	EREG|SCON,TPOINT|TINT|TUNSIGNED|TCHAR|TUCHAR,
		0,	RRIGHT,
		"	movZB	AL,AR\n",

ASSIGN,	INAREG|FOREFF,
	EREG,	TPOINT|TINT|TUNSIGNED,
	EA,	TPOINT|TINT|TUNSIGNED,
		0,	RLEFT,
		"	mov	AL,AR\n",

ASSIGN,	INAREG|FOREFF,
	EREG,	TCHAR|TUCHAR,
	EA,	TCHAR|TUCHAR,
		0,	RLEFT,
		"	movb	AL,AR\n",

ASSIGN,	FOREFF,
	EA,	TCHAR|TUCHAR,
	EA,	TCHAR|TUCHAR,
		NAREG|NASR,	RNULL,
		"	movb	A1,AR\n	movb	AL,A1\n",

ASSIGN, INAREG|FOREFF,
	EA,	TLONG|TULONG,
	SCON,	TLONG|TULONG|TINT,
		0,	RRIGHT,
		"	mov	AL,AR\n	mov	UL,UR\n",

ASSIGN,	INAREG|FOREFF,
	EA,	TLONG|TULONG,
	EREG,	TLONG|TULONG,
		0,	RRIGHT,
		"	mov	AL,AR\n	mov	UL,UR\n",

ASSIGN,	INAREG|FOREFF,
	EREG,	TLONG|TULONG,
	EA,	TLONG|TULONG,
		0,	RLEFT,
		"	mov	AL,AR\n	mov	UL,UR\n",
#ifndef	X8087
ASSIGN,	FOREFF,
	FEA,	TFLOAT,
	FEA,	TFLOAT,
		0,	RLEFT,
		"	mov	AL,AR\n	mov	UL,UR\n",

ASSIGN,	FOREFF,
	FEA,	TDOUBLE,
	FEA,	TDOUBLE,
		0,	RLEFT,
		"ZD",

#endif

#ifdef X8087
ASSIGN,	FOREFF,
	FEA,	TDOUBLE|TFLOAT,
	FEA,	TDOUBLE|TFLOAT,
		0,	RLEFT,
		"	fldZr	AR\n	fstpZl	AL\n",

ASSIGN,	INTEMP,
	FEA,	TDOUBLE|TFLOAT,
	FEA,	TDOUBLE|TFLOAT,
		4*NTEMP,	RESC1,
		"	fldZr	AR\n	fstZl	AL\n	fstpZl	A1\n",
#endif

ASSIGN, INAREG|FOREFF,
	SFLD,	TANY,
	SZERO,	TANY,
		0,	RRIGHT,
		"	and	AL,#~M\n",

ASSIGN, INTAREG|INAREG|FOREFF,
	SFLD,	TANY,
	STAREG,	TANY,
		0,	RRIGHT,
		"F\tpush\tAR\n\tmov\tcl,*H\n\tshl\tAR,cl\n\tand\tAR,#M\n\tand\tAL,#~M\n\tor\tAL,AR\nF\tpop\tAR\n",

ASSIGN, INAREG|FOREFF,
	SFLD,	TANY,
	EA,	TANY,
		NAREG,	RRIGHT,
		"\tmov\tA1,AR\n\tmov\tcl,*H\n\tshl\tA1,cl\n\tand\tA1,#M\n\tand\tAL,#~M\n\tor\tAL,A1\n",

/* put this here so UNARY MUL nodes match OPLTYPE when appropriate */
OPLTYPE,	FOREFF,
	SANY,	TANY,
	EA,	TANY,
		0,	RRIGHT,
		"",   /* this entry throws away computations which don't do anything */

OPLTYPE,	INAREG,
	SANY,	TANY,
	SAREG,	TANY,
		0,	RRIGHT,
		"",

OPLTYPE,	INTAREG|INAREG,
	SANY,	TANY,
	EA,	TINT|TUNSIGNED|TPOINT,
		NAREG|NASR,	RESC1,
		"	mov	A1,AR\n",

OPLTYPE,	INTAREG|INAREG,
	SANY,	TANY,
	EA,	TLONG|TULONG,
		NAREG,	RESC1,
		"	mov	A1,AR\n	mov	U1,UR\n",

OPLTYPE,	INTBREG|INBREG,
	SANY,	TANY,
	EA,	TINT|TUNSIGNED|TPOINT,
		NBREG|NBSR,	RESC1,
		"	mov	A1,AR\n",

OPLTYPE,	INTEMP,
	SANY,	TANY,
	EREG,	TINT|TUNSIGNED|TPOINT,
		NTEMP,	RESC1,
		"	mov	A1,AR\n",

OPLTYPE,	INTEMP,
	SANY,	TANY,
	EREG,	TLONG|TULONG,
		2*NTEMP,	RESC1,
		"	mov	A1,AR\n	mov	U1,UR\n",

OPLTYPE,	FORCC,
	SANY,	TANY,
	EREG,	TINT|TUNSIGNED|TPOINT,
		0,	RESCC,
		"	or	AR,AR\n",

OPLTYPE,	FORCC,
	SANY,	TANY,
	EREG,	TLONG|TULONG,
		0,	RESCC,
		"	or	UR,UR\n	jne	.+4\n	or	AR,AR\n",

OPLTYPE,	FORCC,
	SANY,	TANY,
	SNAME|SOREG|SAREG|SBREG,	TINT|TUNSIGNED|TPOINT|TCHAR|TUCHAR,
		0,	RESCC,
		"	cmpZB	AR,*0\n",

OPLTYPE,	FORCC,		/* only good for eq/neq comparisons... */
	SANY,	TANY,
	SNAME|SOREG|SAREG|SBREG,	TLONG|TULONG,
		0,	RESCC,
		"	cmp	UR,*0\n	jne Zx\n	cmp	AR,*0\nZz",

OPLTYPE,	FORCC,
	SANY,	TANY,
	SCON,	TINT|TUNSIGNED|TPOINT|TCHAR|TUCHAR,
		NAREG|NASR,	RESCC,
		"	mov	A1,AR\n	or	A1,A1\n",

OPLTYPE,	FORARG,
	SANY,	TANY,
	SNAME|SOREG|SAREG|SBREG,	TINT|TUNSIGNED|TPOINT,
		0,	RNULL,
		"	push	AR\nZ-",

OPLTYPE,	FORARG,
	SANY,	TANY,
	SNAME|SOREG|SAREG|SBREG,	TLONG|TULONG,
		0,	RNULL,
		"	push	UR\nZ-	push	AR\nZ-",

#ifndef X8087
OPLTYPE,	FORARG,
	SANY,	TANY,
	FEA,	TDOUBLE,
		NBREG|NBSR,	RNULL,
		"\tlea\tA1,AL\n\tpush\t*6(A1)\n\tpush\t*4(A1)\n\tpush\t*2(A1)\n\tpush\t(A1)\nZ4",
#endif

#ifdef X8087
OPLTYPE,	FORARG,
	SANY,	TANY,
	FEA,	TDOUBLE|TFLOAT,
		NBREG|NBSR,	RNULL,
		"\tfldZB	AR\n	sub	sp,*8\n	mov	A1,sp\n	fstpd	(A1)\nZ4",

OPLTYPE,	INTEMP,
	SANY,	TANY,
	FEA,	TDOUBLE|TFLOAT,
		4*NTEMP,	RESC1,
		"	fldZB	AR\n	fstpZB	A1\n",

OPLTYPE,	INTAREG,
	SANY,	TANY,
	FEA,	TDOUBLE|TFLOAT,
		NAREG,	RESC1,
		"	fldZB	AL\n",
#endif

OPLTYPE,	INTAREG|INAREG,
	SANY,	TANY,
	SCCON,	TANY,
		NAREG|NASR,	RESC1,
		"	mov	A1,AR\n",

OPLTYPE,	INTAREG|INAREG,
	SANY,	TANY,
	EA,	TCHAR,
		NAREG|NASR,	RESC1,
		"	movb	A1,AR\nZe\n",

OPLTYPE,	INTAREG|INAREG,
	SANY,	TANY,
	EA,	TUCHAR,
		NAREG|NASR,	RESC1,
		"	movb	A1,AR\n	and	A1,#255\n",

OPLOG,	FORCC,
	EREG,	TPOINT|TINT|TUNSIGNED,
	EA,	TPOINT|TINT|TUNSIGNED,
		0,	RESCC,
		"	cmp	AL,AR\nZI",

OPLOG,	FORCC,
	SNAME|SOREG|SAREG|SBREG,	TPOINT|TINT|TUNSIGNED,
	EREG|SCON,	TPOINT|TINT|TUNSIGNED,
		0,	RESCC,
		"	cmp	AL,AR\nZI",

OPLOG,	FORCC,
	EREG,	TCHAR|TUCHAR,
	EA,	TCHAR|TUCHAR,
		0,	RESCC,
		"	cmpb	AL,AR\nZI",

OPLOG,	FORCC,
	EA,	TCHAR|TUCHAR,
	EREG,	TCHAR|TUCHAR,
		0,	RESCC,
		"	cmpb	AL,AR\nZI",

OPLOG,	FORCC,
	EA,	TCHAR|TUCHAR,
	SCCON,	TINT,
		0,	RESCC,
		"	cmpb	AL,AR\nZI",

OPLOG,	FORCC,
	EREG,	TLONG|TULONG,
	EA,	TLONG|TULONG,
		0,	RESCC,
		"ZCZI",

OPLOG,	FORCC,
	SNAME|SOREG|SAREG|SBREG,	TLONG|TULONG,
	EREG|SCON,	TLONG|TULONG,
		0,	RESCC,
		"ZCZI",

#ifdef X8087
OPLOG,	FORCC,
	FEA,	TDOUBLE|TFLOAT,
	FEA,	TDOUBLE|TFLOAT,
		NTEMP,	RESCC,
		"\tfldZl\tAL\n\tfcompZr\tAR\n\tfstsw\tA1\n\tfwait\n\txchg\tah,Z1\n\tsahf\n\txchg\tah,Z1\nZF",
#endif

CCODES,	INTAREG|INAREG,
	SANY,	TANY,
	SANY,	TINT|TUNSIGNED|TPOINT|TCHAR|TUCHAR,
		NAREG,	RESC1,
		"	mov	A1,*1\nZN",

CCODES,	INTAREG|INAREG,
	SANY,	TANY,
	SANY,	TLONG|TULONG,
		NAREG,	RESC1,
		"	mov	A1,*1\n	mov	U1,*0\nZN",

UNARY MINUS,	INTAREG|INAREG,
	STAREG,	TINT|TUNSIGNED,
	SANY,	TANY,
		0,	RLEFT,
		"	neg	AL\n",

UNARY MINUS,	INTAREG|INAREG,
	STAREG,	TLONG|TULONG,
	SANY,	TANY,
		0,	RLEFT,
		"	neg	UL\n	neg	AL\n	sbb	UL,*0\n",

UNARY MINUS,	INTEMP,
	FEA,	TDOUBLE|TFLOAT,
	SANY,	TANY,
		4*NTEMP,	RESC1,
		"	fldZl	AL\n	fchs\n	fstpZB	A1\n",

COMPL,	INTAREG|INAREG,
	STAREG,	TINT|TUNSIGNED,
	SANY,	TANY,
		0,	RLEFT,
		"	not	AL\n",

COMPL,	INTAREG|INAREG,
	STAREG,	TLONG|TULONG,
	SANY,	TANY,
		0,	RLEFT,
		"	not	AL\n	not	UL\n",

INCR,	INTAREG|INAREG|FOREFF,
	EA,	TINT|TUNSIGNED|TPOINT,
	SONE,	TANY,
		NAREG,	RESC1,
		"F	mov	A1,AL\n	inc	AL\n",

INCR,	INTAREG|INAREG|FOREFF,
	EA,	TCHAR|TUCHAR,
	SONE,	TANY,
		NAREG,	RESC1,
		"F	movb	A1,AL\nFZe\n	incb	AL\n",

DECR,	INTAREG|INAREG|FOREFF,
	EA,	TINT|TUNSIGNED|TPOINT,
	SONE,	TANY,
		NAREG,	RESC1,
		"F	mov	A1,AL\n	dec	AL\n",

DECR,	INTAREG|INAREG|FOREFF,
	EA,	TCHAR|TUCHAR,
	SONE,	TANY,
		NAREG,	RESC1,
		"F	movb	A1,AL\nFZe\n	decb	AL\n",

INCR,	INTAREG|INAREG|FOREFF,
	EA,	TINT|TUNSIGNED|TPOINT,
	SCON,	TANY,
		NAREG,	RESC1,
		"F	mov	A1,AL\n	add	AL,AR\n",

DECR,	INTAREG|INAREG|FOREFF,
	EA,	TINT|TUNSIGNED|TPOINT,
	SCON,	TANY,
		NAREG,	RESC1,
		"F	mov	A1,AL\n	sub	AL,AR\n",

INCR,	INTBREG|INBREG|FOREFF,
	EA,	TINT|TUNSIGNED|TPOINT|TCHAR|TUCHAR,
	SONE,	TANY,
		NBREG,	RESC1,
		"F	movZB	A1,AL\n	incZB	AL\n",

DECR,	INTBREG|INBREG|FOREFF,
	EA,	TINT|TUNSIGNED|TPOINT|TCHAR|TUCHAR,
	SONE,	TANY,
		NBREG,	RESC1,
		"F	movZB	A1,AL\n	decZB	AL\n",

INCR,	INTBREG|INBREG|FOREFF,
	EA,	TINT|TUNSIGNED|TPOINT,
	SCON,	TANY,
		NBREG,	RESC1,
		"F	mov	A1,AL\n	add	AL,AR\n",

DECR,	INTBREG|INBREG|FOREFF,
	EA,	TINT|TUNSIGNED|TPOINT,
	SCON,	TANY,
		NBREG,	RESC1,
		"F	mov	A1,AL\n	sub	AL,AR\n",

INCR,	INTAREG|INAREG|FOREFF,
	EA,	TLONG|TULONG,
	SCON,	TANY,
		NAREG,	RESC1,
		"F	mov	A1,AL\nF	mov	U1,UL\n	add	AL,AR\n	adc	UL,UR\n",

DECR,	INTAREG|INAREG|FOREFF,
	EA,	TLONG|TULONG,
	SCON,	TANY,
		NAREG,	RESC1,
		"F	mov	A1,AL\nF	mov	U1,UL\n	sub	AL,AR\n	sbb	UL,UR\n",

AND,	FORCC,
	EA,	TINT|TUNSIGNED|TPOINT,
	SCON,	TANY,
		0,	RESCC,
		"	test	AL,AR\n",

AND,	FORCC,
	EREG,	TINT|TUNSIGNED|TPOINT,
	EA,	TANY,
		0,	RESCC,
		"	test	AL,AR\n",

ASG MUL,	INTAREG,
	STAREG,	TINT|TCHAR,
	SOREG|SNAME|SAREG|SBREG,	TINT|TCHAR,
		NAREG|NASR,	RLEFT,
		"	imulZB	AR\n",

ASG DIV,	INTAREG,
	STAREG,	TINT,
	SCON,	TINT,
		NAREG,	RLEFT,
		"ZV	mov	cx,AR\n	idiv	cx\n",  /* since lhs must be in r1 */

ASG DIV,	INTAREG,
	STAREG,	TINT,
	SOREG|SNAME|SAREG|SBREG,	TINT,
		NAREG,	RLEFT,
		"ZV	idiv	AR\n",  /* since lhs must be in r1 */

ASG MOD,	INTAREG,
	STAREG,	TINT,
	SCON,	TINT,
		NAREG,	RESC1,
		"ZV	mov	cx,AR\n	idiv	cx\n",  /* since lhs must be in r1 */

ASG MOD,	INTAREG,
	STAREG,	TINT,
	SOREG|SNAME|SAREG|SBREG,	TINT,
		NAREG,	RESC1,
		"ZV	idiv	AR\n",  /* since lhs must be in r1 */

ASG MUL,	INTAREG,
	STAREG,	TINT|TUNSIGNED|TPOINT,
	SOREG|SNAME|SAREG|SBREG,	TINT|TUNSIGNED|TPOINT,
		NAREG|NASL,	RLEFT,
		"	mul	AR\n",

ASG DIV,	INTAREG,
	STAREG,	TINT|TUNSIGNED|TPOINT,
	SCON,	TINT|TUNSIGNED|TPOINT,
		NAREG,	RLEFT,
		"ZV	mov	cx,AR\n	div	cx\n",  /* since lhs must be in r1 */

ASG DIV,	INTAREG,
	STAREG,	TINT|TUNSIGNED|TPOINT,
	SOREG|SNAME|SAREG|SBREG,	TINT|TUNSIGNED|TPOINT,
		NAREG,	RLEFT,
		"ZV	div	AR\n",  /* since lhs must be in r1 */

ASG MOD,	INTAREG,
	STAREG,	TINT|TUNSIGNED|TPOINT,
	SCON,	TINT|TUNSIGNED|TPOINT,
		NAREG,	RESC1,
		"ZV	mov	cx,AR\n	div	cx\n",  /* since lhs must be in r1 */

ASG MOD,	INTAREG,
	STAREG,	TINT|TUNSIGNED|TPOINT,
	SOREG|SNAME|SAREG|SBREG,	TINT|TUNSIGNED|TPOINT,
		NAREG,	RESC1,
		"ZV	div	AR\n",  /* since lhs must be in r1 */

MINUS,		INTAREG,
	SBREG,	TINT|TUNSIGNED|TPOINT,
	SXCON,	TINT|TUNSIGNED|TPOINT,
		NAREG|NASL,	RESC1,
		"	lea	A1,ZM(AL)\n",
		
MINUS,		INTBREG,
	SBREG,	TINT|TUNSIGNED|TPOINT,
	SXCON,	TINT|TUNSIGNED|TPOINT,
		NBREG|NBSL,	RESC1,
		"	lea	A1,ZM(AL)\n",

PLUS,		INTAREG,
	SBREG,	TINT|TUNSIGNED|TPOINT,
	SCON,	TINT|TUNSIGNED|TPOINT,
		NAREG|NASL,	RESC1,
		"	lea	A1,Zc(AL)\n",
		
PLUS,		INTBREG,
	SBREG,	TINT|TUNSIGNED|TPOINT,
	SCON,	TINT|TUNSIGNED|TPOINT,
		NBREG|NBSL,	RESC1,
		"	lea	A1,Zc(AL)\n",

ASG PLUS,	INAREG,
	EA,	TINT|TUNSIGNED|TPOINT|TCHAR|TUCHAR,
	SONE,	TINT,
		0,	RLEFT|RESCC,
		"	incZB	AL\n",

ASG MINUS,	INAREG,
	EA,	TINT|TUNSIGNED|TPOINT|TCHAR|TUCHAR,
	SONE,	TINT,
		0,	RLEFT|RESCC,
		"	decZB	AL\n",

ASG PLUS,	INAREG,
	EA,	TLONG|TULONG,
	SONE,	TINT,
		0,	RLEFT|RESCC,
		"	add	AL,*1\n	adc	UL,*0\n",

ASG MINUS,	INAREG,
	EA,	TLONG|TULONG,
	SONE,	TINT,
		0,	RLEFT|RESCC,
		"	sub	AL,*1\n	sbb	UL,*0\n",

ASG OPSIMP,	INAREG|FORCC,		/* can't do byte ops on SI and DI */
	EA,	TCHAR|TUCHAR,
	SBREG,	TINT|TUNSIGNED|TPOINT,
		0,	RLEFT|RESCC,
		"	mov	cx,AR\n	OIZB	AL,cx\n",

ASG OPSIMP,	INAREG|FORCC,
	EA,	TINT|TUNSIGNED|TPOINT|TCHAR|TUCHAR,
	EREG|SCON,	TINT|TUNSIGNED|TPOINT|TCHAR|TUCHAR,
		0,	RLEFT|RESCC,
		"	OIZB	AL,AR\n",

ASG OPSIMP,	INAREG|FORCC,
	EREG,	TINT|TUNSIGNED|TPOINT|TCHAR|TUCHAR,
	EA,	TINT|TUNSIGNED|TPOINT|TCHAR|TUCHAR,
		0,	RLEFT|RESCC,
		"	OIZB	AL,AR\n",

/*ASG OPSIMP,	INTAREG|FORCC,
	STAREG,	TINT|TUNSIGNED|TPOINT|TCHAR|TUCHAR,
	EA,	TINT|TUNSIGNED|TPOINT|TCHAR|TUCHAR,
		0,	RLEFT|RESCC,
		"	OIZB	AL,AR\n",

ASG OPSIMP,	INTAREG|FORCC,
	EA,	TINT|TUNSIGNED|TPOINT,
	EREG|SCON,	TINT|TUNSIGNED|TPOINT,
		NAREG|NASR,	RESC1|RESCC,
		"	OIZB	AL,AR\n	mov	A1,AL\n",

ASG OPSIMP,	INTAREG|FORCC,
	EA,	TCHAR|TUCHAR,
	EREG|SCON,	TINT|TUNSIGNED|TPOINT,
		NAREG|NASR,	RESC1|RESCC,
		"	OIZB	AL,AR\n	movb	A1,AL\nZe\n",
*/
ASG PLUS,	INAREG,
	EA,	TLONG|TULONG,
	EREG|SCON,	TLONG|TULONG,
		0,	RLEFT,
		"	add	AL,AR\n	adc	UL,UR\n",

ASG PLUS,	INAREG,
	EREG,	TLONG|TULONG,
	EA,	TLONG|TULONG,
		0,	RLEFT,
		"	add	AL,AR\n	adc	UL,UR\n",

ASG PLUS,	INTAREG,
	STAREG,	TLONG|TULONG,
	EA,	TLONG|TULONG,
		0,	RLEFT,
		"	add	AL,AR\n	adc	UL,UR\n",

ASG MINUS,	INAREG,
	EA,	TLONG|TULONG,
	EREG|SCON,	TLONG|TULONG,
		0,	RLEFT,
		"	sub	AL,AR\n	sbb	UL,UR\n",

ASG MINUS,	INAREG,
	EREG,	TLONG|TULONG,
	EA,	TLONG|TULONG,
		0,	RLEFT,
		"	sub	AL,AR\n	sbb	UL,UR\n",

ASG MINUS,	INTAREG,
	STAREG,	TLONG|TULONG,
	EA,	TLONG|TULONG,
		0,	RLEFT,
		"	sub	AL,AR\n	sbb	UL,UR\n",

ASG OPSIMP,	INAREG,
	EA,	TLONG|TULONG,
	EREG|SCON,	TLONG|TULONG,
		0,	RLEFT,
		"	OI	AL,AR\n	OI	UL,UR\n",

ASG OPSIMP,	INAREG,
	EREG,	TLONG|TULONG,
	EA,	TLONG|TULONG,
		0,	RLEFT,
		"	OI	AL,AR\n	OI	UL,UR\n",

ASG OPSIMP,	INTAREG,
	STAREG,	TLONG|TULONG,
	EA,	TLONG|TULONG,
		0,	RLEFT,
		"	OI	AL,AR\n	OI	UL,UR\n",

#ifdef X8087
OPFLOAT,	INTEMP,
	FEA,	TDOUBLE|TFLOAT,
	FEA,	TDOUBLE|TFLOAT,
		4*NTEMP,	RESC1,
		"	fldZl	AL\n	ZOZr	AR\n	fstpd	A1\n",

ASG OPFLOAT,	FOREFF|INAREG,
	FEA,	TDOUBLE|TFLOAT,
	FEA,	TDOUBLE|TFLOAT,
		0,	RLEFT,
		"	fldZl	AL\n	ZOZr	AR\n	fstpZl	AL\n",
#endif

LS, 	INTBREG,
	STBREG,	TINT|TUNSIGNED|TPOINT,
	SONE,	TINT,
		0,	RLEFT,
		"	sal	AL,*1\n",

LS, 	INTBREG,
	STBREG,	TINT|TUNSIGNED|TPOINT,
	SCON,	TINT,
		0,	RLEFT,
		"	mov	cx,AR\n	sal	AL,cl\n",

LS, 	INTAREG|INAREG,
	EA,	TINT|TUNSIGNED|TPOINT,
	SONE,	TINT,
		NAREG|NASL,	RESC1,
		"	mov	A1,AL\n	sal	A1,*1\n",

LS, 	INTAREG|INAREG,
	EA,	TINT|TUNSIGNED|TPOINT,
	SCON,	TINT,
		NAREG|NASL,	RESC1,
		"	mov	A1,AL\n	mov	cx,AR\n	sal	A1,cl\n",

LS, 	INTBREG,
	EA,	TINT|TUNSIGNED|TPOINT,
	SONE,	TINT,
		NBREG|NBSL,	RESC1,
		"	mov	A1,AL\n	sal	A1,*1\n",

LS, 	INTBREG,
	EA,	TINT|TUNSIGNED|TPOINT,
	SCON,	TINT,
		NBREG|NBSL,	RESC1,
		"	mov	A1,AL\n	mov	cx,AR\n	sal	A1,cl\n",

ASG LS, 	FOREFF|INAREG,
	EA,	TINT|TUNSIGNED|TPOINT|TCHAR|TUCHAR,
	SONE,	TINT,
		0,	RLEFT,
		"	salZB	AL,*1\n",

ASG LS, 	INAREG|FOREFF,
	EA,	TINT|TUNSIGNED|TPOINT|TCHAR|TUCHAR,
	EA,	TINT|TUNSIGNED,
		0,	RLEFT,
		"	mov	cx,AR\n	salZB	AL,cl\n",

ASG LS, 	INTAREG,
	STAREG,	TINT|TUNSIGNED|TPOINT|TCHAR|TUCHAR,
	SONE,	TINT,
		0,	RLEFT,
		"	salZB	AL,*1\n",

ASG LS, 	INTAREG,
	STAREG,	TINT|TUNSIGNED|TPOINT|TCHAR|TUCHAR,
	EA,	TINT|TUNSIGNED,
		0,	RLEFT,
		"	mov	cx,AR\n	salZB	AL,cl\n",

ASG LS,		INAREG|FOREFF,
	EA,	TLONG|TULONG,
	SONE,	TINT,
		0,	RLEFT,
		"	shl	AL,*1\n	rcl	UL,*1\n",

ASG LS,		INAREG|FOREFF,
	EA,	TLONG|TULONG,
	EA,	TINT|TUNSIGNED,
		0,	RLEFT,
		"\tmov\tcx,AR\n\tjcxz\tZY\nZX\tshl\tAL,*1\n\trcl\tUL,*1\n\tloop\tZy\nZs",

ASG LS,		INTAREG|FOREFF,
	STAREG,	TLONG|TULONG,
	EA,	TINT|TUNSIGNED,
		0,	RLEFT,
		"\tmov\tcx,AR\n\tjcxz\tZY\nZX\tshl\tAL,*1\n\trcl\tUL,*1\n\tloop\tZy\nZs",

ASG RS, 	INAREG|FOREFF,
	EA,	TINT|TCHAR,
	SONE,	TINT,
		0,	RLEFT,
		"	sarZB	AL,*1\n",

ASG RS, 	INAREG|FOREFF,
	EA,	TINT|TCHAR,
	EA,	TINT|TUNSIGNED,
		0,	RLEFT,
		"	mov	cx,AR\n	sarZB	AL,cl\n",

ASG RS, 	INAREG|FOREFF,
	EA,	TUNSIGNED|TPOINT|TUCHAR,
	SONE,	TINT|TUNSIGNED,
		0,	RLEFT,
		"	shrZB	AL,*1\n",

ASG RS, 	INAREG|FOREFF,
	EA,	TUNSIGNED|TPOINT|TUCHAR,
	EA,	TINT|TUNSIGNED,
		0,	RLEFT,
		"	mov	cx,AR\n	shrZB	AL,cl\n",

ASG RS, 	INTAREG,
	STAREG,	TINT|TCHAR,
	SONE,	TINT,
		0,	RLEFT,
		"	sarZB	AL,*1\n",

ASG RS, 	INTAREG,
	STAREG,	TINT|TCHAR,
	EA,	TINT|TUNSIGNED,
		0,	RLEFT,
		"	mov	cx,AR\n	sarZB	AL,cl\n",

ASG RS, 	INTAREG,
	STAREG,	TUNSIGNED|TPOINT|TUCHAR,
	SONE,	TINT,
		0,	RLEFT,
		"	shrZB	AL,*1\n",

ASG RS, 	INTAREG,
	STAREG,	TUNSIGNED|TPOINT|TUCHAR,
	EA,	TINT|TUNSIGNED,
		0,	RLEFT,
		"	mov	cx,AR\n	shrZB	AL,cl\n",

ASG RS,		INAREG|FOREFF,
	EA,	TULONG,
	SONE,	TINT,
		0,	RLEFT,
		"	sar	UL,*1\n	rcr	AL,*1\n",

ASG RS,		INAREG|FOREFF,
	EA,	TULONG,
	EA,	TINT|TUNSIGNED,
		0,	RLEFT,
		"\tmov\tcx,AR\n\tjcxz\tZY\nZX\tsar\tUL,*1\n\trcr\tAL,*1\n\tloop\tZy\nZs",

ASG RS,		INTAREG|FOREFF,
	STAREG,	TULONG,
	EA,	TINT|TUNSIGNED,
		0,	RLEFT,
		"\tmov\tcx,AR\n\tjcxz\tZY\nZX\tsar\tUL,*1\n\trcr\tAL,*1\n\tloop\tZy\nZs",

ASG RS,		INAREG|FOREFF,
	EA,	TLONG,
	SONE,	TINT,
		0,	RLEFT,
		"	sar	UL,*1\n	rcr	AL,*1\n",

ASG RS,		INAREG|FOREFF,
	EA,	TLONG,
	EA,	TINT|TUNSIGNED,
		0,	RLEFT,
		"\tmov\tcx,AR\n\tjcxz\tZY\nZX\tsar\tUL,*1\n\trcr\tAL,*1\n\tloop\tZy\nZs",

UNARY CALL,	INTAREG,
	SCON,	TANY,
	SANY,	TINT|TUNSIGNED|TPOINT|TCHAR|TUCHAR|TLONG|TULONG,
		NAREG|NASL,	RESC1, /* should be register 0 */
		"	call	Zd\n",

UNARY CALL,	INTAREG,
	SAREG|SNAME|SOREG,	TANY,
	SANY,	TINT|TUNSIGNED|TPOINT|TCHAR|TUCHAR|TLONG|TULONG,
		NAREG|NASL,	RESC1, /* should be register 0 */
		"	call	@AL\n",

#ifdef X8087
UNARY CALL,	INTEMP,
	SCON,	TANY,
	SANY,	TDOUBLE,
		4*NTEMP,	RESC1,
		"	call	Zd\n	fstpd	A1\n",

UNARY CALL,	INTEMP,
	SAREG|SNAME|SOREG,	TANY,
	SANY,	TDOUBLE,
		4*NTEMP,	RESC1,
		"	call	@AL\n	fstpd	A1\n",
#endif

#ifndef X8087
UNARY CALL,	INTEMP,
	SCON,	TANY,
	SANY,	TDOUBLE,
		4*NTEMP,	RESC1,
		"\tcall	Zd\n\tpush\tsi\n\tpush\tdi\n\tlea\tsi,Dreg\n\tlea\tdi,A1\n\tmov\tcx,#4\n\tcld\n\trepz\n\tmovw\n\tpop\tdi\n\tpop\tsi\n",

UNARY CALL,	INTEMP,
	SAREG|SNAME|SOREG,	TANY,
	SANY,	TDOUBLE,
		4*NTEMP,	RESC1,
		"\tcall	@AL\n\tpush\tsi\n\tpush\tdi\n\tlea\tsi,Dreg\n\tlea\tdi,A1\n\tmov\tcx,#4\n\tcld\n\trepz\n\tmovw\n\tpop\tdi\n\tpop\tsi\n",

#endif
SCONV,	INTAREG,
	STAREG,	TINT|TUNSIGNED|TPOINT|TCHAR|TUCHAR,
	SANY,	TUCHAR,
		0,	RLEFT,
		"	and	AL,#255\n",

SCONV,	INTAREG,
	EA,	TINT|TUNSIGNED|TPOINT|TCHAR|TUCHAR,
	SANY,	TCHAR,
		NAREG|NASL,	RESC1,
		"	mov	A1,AL\nZe\n",

SCONV,	INAREG,
	EA,	TLONG|TULONG,
	SANY,	TINT|TUNSIGNED|TPOINT|TCHAR|TUCHAR,
		0,	RLEFT,
		"ZT",

SCONV,	INTAREG,
	STAREG,	TLONG|TULONG,
	SANY,	TINT|TUNSIGNED|TPOINT|TCHAR|TUCHAR,
		0,	RLEFT,
		"ZT",

SCONV,	INTBREG,
	EA,	TLONG|TULONG,
	SANY,	TINT|TUNSIGNED|TPOINT,
		NBREG|NBSL,	RESC1,
		"	mov	A1,AL\n",

SCONV,	INTAREG,
	EA,	TUCHAR,
	SANY,	TLONG|TULONG,
		NAREG|NASL,	RESC1,
		"	movb	A1,AL\n	and	A1,#255\n	mov	U1,*0\n",

SCONV,	INTAREG,
	EA,	TCHAR,
	SANY,	TLONG|TULONG,
		NAREG|NASL,	RESC1,
		"	mov	A1,AL\nZe\n",

SCONV,	INTAREG,
	EA,	TINT,
	SANY,	TLONG|TULONG,
		NAREG|NASL,	RESC1,
		"	mov	A1,AL\nZE",

SCONV,	INTAREG,
	EA,	TUNSIGNED|TPOINT,
	SANY,	TLONG|TULONG,
		NAREG|NASL,	RESC1,
		"	mov	A1,AL\n	mov	U1,*0\n",

SCONV,	INTAREG,
	STAREG, TINT|TUNSIGNED|TPOINT,
	SANY,	TINT|TUNSIGNED|TPOINT,
		0,	RLEFT,
		"",

SCONV,	INTBREG,
	STAREG, TINT|TUNSIGNED|TPOINT,
	SANY,	TINT|TUNSIGNED|TPOINT,
		NBREG|NBSL,	RESC1,
		"	mov	A1,AL\n",

SCONV,	INTAREG,
	STAREG, TCHAR|TUCHAR,
	SANY,	TCHAR|TUCHAR,
		0,	RLEFT,
		"",

SCONV,	INTAREG,
	STAREG, TLONG|TULONG,
	SANY,	TLONG|TULONG,
		0,	RLEFT,
		"",

#ifdef X8087
SCONV,	INAREG|INTEMP,
	FEA,	TDOUBLE|TFLOAT,
	SANY,	TINT|TUNSIGNED|TPOINT|TCHAR|TUCHAR,
		NTEMP,	RESC1,
		"	fldZl	AL\n	fstpi	A1\n	fwait\n",

SCONV,	INAREG|INTEMP,
	FEA,	TDOUBLE|TFLOAT,
	SANY,	TLONG|TULONG,
		2*NTEMP,	RESC1,
		"	fldZl	AL\n	fstpl	A1\n	fwait\n",

SCONV,	INTEMP,
	FEA,	TLONG|TULONG,
	SANY,	TDOUBLE|TFLOAT,
		4*NTEMP,	RESC1,
		"	fldl	AL\n	fstpZB	A1\n",

SCONV,	INTEMP,
	EREG,	TLONG|TULONG,
	SANY,	TDOUBLE|TFLOAT,
		4*NTEMP,	RESC1,
		"	mov	A1,AL\n	mov	U1,UL\n	fldl	A1\n	fstpZB	A1\n",

SCONV,	INTEMP,
	FEA,	TINT|TUNSIGNED,
	SANY,	TDOUBLE|TFLOAT,
		4*NTEMP,	RESC1,
		"	fldi	AL\n	fstpZB	A1\n",

SCONV,	INTEMP,
	EREG,	TINT|TUNSIGNED,
	SANY,	TDOUBLE|TFLOAT,
		4*NTEMP,	RESC1,
		"	mov	A1,AL\n	fldi	A1\n	fstpZB	A1\n",
#endif

PCONV,	INTAREG,
	EA,	TUCHAR,
	SANY,	TPOINT,
		NAREG|NASL,	RESC1,
		"	movb	A1,AL\n	and	A1,#255\n",

PCONV,	INTAREG,
	EA,	TCHAR,
	SANY,	TPOINT,
		NAREG|NASL,	RESC1,
		"	mov	A1,AL\nZe\n",

PCONV,	INAREG,
	EA,	TLONG|TULONG,
	SANY,	TPOINT,
		0,	RLEFT,
		"ZT",

STASG,	FOREFF,
	EA,	TANY,
	EA,	TANY,
		0,	RNOP,
		"ZS",

/*STASG,	FOREFF,
	SNAME|SOREG,	TANY,
	SCON|SAREG|SBREG,	TANY,
		0,	RNOP,
		"ZS",

STASG,	INTAREG|INAREG,
	SNAME|SOREG,	TANY,
	STAREG|STBREG,	TANY,
		0,	RRIGHT,
		"ZS",

STASG, INAREG|INTAREG,
	SNAME|SOREG,	TANY,
	SCON|SAREG|SBREG,	TANY,
		NAREG|NASR,	RESC1,
		"ZS	mov	A1,AR\n",*/

INIT,	FOREFF,
	SCON,	TANY,
	SANY,	TINT|TUNSIGNED|TPOINT,
		0,	RNOP,
		"	.word	ZL\n",

INIT,	FOREFF,
	SCON,	TANY,
	SANY,	TLONG|TULONG,
		0,	RNOP,
		"	.long	ZL\n",

INIT,	FOREFF,
	SCON,	TANY,
	SANY,	TCHAR|TUCHAR,
		0,	RNOP,
		"	.byte	ZL\n",

	/* for the use of fortran only */

GOTO,	FOREFF,
	SCON,	TANY,
	SANY,	TANY,
		0,	RNOP,
		"	jbr	CL\n",

GOTO,	FOREFF,
	SNAME,	TLONG|TULONG,
	SANY,	TANY,
		0,	RNOP,
		"	jmp	*UL\n",

GOTO,	FOREFF,
	SNAME,	TINT|TUNSIGNED|TCHAR|TUCHAR|TPOINT,
	SANY,	TANY,
		0,	RNOP,
		"	jmp	*AL\n",

	/* Default actions for hard trees ... */

# define DF(x) FORREW,SANY,TANY,SANY,TANY,REWRITE,x,""

UNARY MUL, DF( UNARY MUL ),

INCR, DF(INCR),

DECR, DF(INCR),

ASSIGN, DF(ASSIGN),

STASG, DF(STASG),

OPLEAF, DF(NAME),

OPLOG,	FORCC,
	SANY,	TANY,
	SANY,	TANY,
		REWRITE,	BITYPE,
		"",

OPLOG,	DF(NOT),

COMOP, DF(COMOP),

INIT, DF(INIT),

OPUNARY, DF(UNARY MINUS),


ASG OPANY, DF(ASG PLUS),

OPANY, DF(BITYPE),

FREE,	FREE,	FREE,	FREE,	FREE,	FREE,	FREE,	FREE,	"help; I'm in trouble\n" };
NOP,
		"	jmp	*AL\n",

	/* Default actions for hard trees ... */

# define DF(x) FORREW,SANY,TANY,SANY,TANY,REWRITE,x,""

UNARY MUL, DF( UNARY MUL ),

INCR, DF(INCR),

DECR, DF(INCR),

ASSIGN, DF(ASSIGN),

STASG, DF(STASG),

OPLEAF, DF(NAME),

OPLOG,	FORCC,
	SANY,	TANY,
	SANY,	TANY,
		REWRITE,	BITYPE,
		"",

OPLOG,	DF(NOT),

COMOP, DF(COMOP),

INIT, DF(INIc86/trees.c                                                                                            444      26      12        74665  3227134403   6004                                                                                                                                                                                                                                                                                                                                                                      # include "mfile1"

	    /* corrections when in violation of lint */

/*	some special actions, used in finding the type of nodes */
# define NCVT 01
# define PUN 02
# define TYPL 04
# define TYPR 010
# define TYMATCH 040
# define LVAL 0100
# define CVTO 0200
# define CVTL 0400
# define CVTR 01000
# define PTMATCH 02000
# define OTHER 04000
# define NCVTR 010000

/* node conventions:

	NAME:	rval>0 is stab index for external
		rval<0 is -inlabel number
		lval is offset in bits
	ICON:	lval has the value
		rval has the STAB index, or - label number,
			if a name whose address is in the constant
		rval = NONAME means no name
	REG:	rval is reg. identification cookie

	*/

int bdebug = 0;
extern ddebug;

NODE *
buildtree( o, l, r ) register NODE *l, *r; {
	register NODE *p, *q;
	register actions;
	register opty;
	register struct symtab *sp;
	register NODE *lr, *ll;
	int i;
	extern int eprint();

# ifndef BUG1
	if( bdebug ) printf( "buildtree( %s, %o, %o )\n", opst[o], l, r );
# endif
	opty = optype(o);

	/* check for constants */

	if( opty == UTYPE && l->in.op == ICON ){

		switch( o ){

		case NOT:
			if( hflag ) werror( "constant argument to NOT" );
		case UNARY MINUS:
		case COMPL:
			if( conval( l, o, l ) ) return(l);
			break;

			}
		}

	else if( o==UNARY MINUS && l->in.op==FCON ){
		l->fpn.dval = -l->fpn.dval;
		return(l);
		}

	else if( o==QUEST && l->in.op==ICON ) {
		l->in.op = FREE;
		r->in.op = FREE;
		if( l->tn.lval ){
			tfree( r->in.right );
			return( r->in.left );
			}
		else {
			tfree( r->in.left );
			return( r->in.right );
			}
		}

	else if( (o==ANDAND || o==OROR) && (l->in.op==ICON||r->in.op==ICON) ) goto ccwarn;

	else if( opty == BITYPE && l->in.op == ICON && r->in.op == ICON ){

		switch( o ){

		case ULT:
		case UGT:
		case ULE:
		case UGE:
		case LT:
		case GT:
		case LE:
		case GE:
		case EQ:
		case NE:
		case ANDAND:
		case OROR:
		case CBRANCH:

		ccwarn:
			if( hflag ) werror( "constant in conditional context" );

		case PLUS:
		case MINUS:
		case MUL:
		case DIV:
		case MOD:
		case AND:
		case OR:
		case ER:
		case LS:
		case RS:
			if( conval( l, o, r ) ) {
				r->in.op = FREE;
				return(l);
				}
			break;
			}
		}

	else if( opty == BITYPE && (l->in.op==FCON||l->in.op==ICON) &&
		(r->in.op==FCON||r->in.op==ICON) ){
		switch(o){
		case PLUS:
		case MINUS:
		case MUL:
		case DIV:
			if( l->in.op == ICON ){
				l->fpn.dval = l->tn.lval;
				}
			if( r->in.op == ICON ){
				r->fpn.dval = r->tn.lval;
				}
			l->in.op = FCON;
			l->in.type = l->fn.csiz = DOUBLE;
			r->in.op = FREE;
			switch(o){
			case PLUS:
				l->fpn.dval += r->fpn.dval;
				return(l);
			case MINUS:
				l->fpn.dval -= r->fpn.dval;
				return(l);
			case MUL:
				l->fpn.dval *= r->fpn.dval;
				return(l);
			case DIV:
				if( r->fpn.dval == 0 ) uerror( "division by 0." );
				else l->fpn.dval /= r->fpn.dval;
				return(l);
				}
			}
		}

	/* its real; we must make a new node */

	p = block( o, l, r, INT, 0, INT );

	actions = opact(p);

	if( actions&LVAL ){ /* check left descendent */
		if( notlval(p->in.left) ) {
			uerror( "illegal lhs of assignment operator" );
			}
		}

	if( actions & NCVTR ){
		p->in.left = pconvert( p->in.left );
		}
	else if( !(actions & NCVT ) ){
		switch( opty ){

		case BITYPE:
			p->in.right = pconvert( p->in.right );
		case UTYPE:
			p->in.left = pconvert( p->in.left );

			}
		}

	if( (actions&PUN) && (o!=CAST||cflag) ){
		chkpun(p);
		}

	if( actions & (TYPL|TYPR) ){

		q = (actions&TYPL) ? p->in.left : p->in.right;

		p->in.type = q->in.type;
		p->fn.cdim = q->fn.cdim;
		p->fn.csiz = q->fn.csiz;
		}

	if( actions & CVTL ) p = convert( p, CVTL );
	if( actions & CVTR ) p = convert( p, CVTR );
	if( actions & TYMATCH ) p = tymatch(p);
	if( actions & PTMATCH ) p = ptmatch(p);

	if( actions & OTHER ){
		l = p->in.left;
		r = p->in.right;

		switch(o){

		case NAME:
			sp = &stab[idname];
			if( sp->stype == UNDEF ){
				uerror( "%.*s undefined", NCHNAM, sp->sname );
				/* make p look reasonable */
				p->in.type = p->fn.cdim = p->fn.csiz = INT;
				p->tn.rval = idname;
				p->tn.lval = 0;
				defid( p, SNULL );
				break;
				}
			p->in.type = sp->stype;
			p->fn.cdim = sp->dimoff;
			p->fn.csiz = sp->sizoff;
			p->tn.lval = 0;
			p->tn.rval = idname;
			/* special case: MOETY is really an ICON... */
			if( p->in.type == MOETY ){
				p->tn.rval = NONAME;
				p->tn.lval = sp->offset;
				p->fn.cdim = 0;
				p->in.type = ENUMTY;
				p->in.op = ICON;
				}
			break;

		case ICON:
			p->in.type = INT;
			p->fn.cdim = 0;
			p->fn.csiz = INT;
			break;

		case STRING:
			p->in.op = NAME;
			p->in.type = CHAR+ARY;
			p->tn.lval = 0;
			p->tn.rval = NOLAB;
			p->fn.cdim = curdim;
			p->fn.csiz = CHAR;
			break;

		case FCON:
			p->tn.lval = 0;
			p->tn.rval = 0;
			p->in.type = DOUBLE;
			p->fn.cdim = 0;
			p->fn.csiz = DOUBLE;
			break;

		case STREF:
			/* p->x turned into *(p+offset) */
			/* rhs must be a name; check correctness */

			i = r->tn.rval;
			if( i<0 || ((sp= &stab[i])->sclass != MOS && sp->sclass != MOU && !(sp->sclass&FIELD)) ){
				uerror( "member of structure or union required" );
				}else
			/* if this name is non-unique, find right one */
			if( stab[i].sflags & SNONUNIQ &&
				(l->in.type==PTR+STRTY || l->in.type == PTR+UNIONTY) &&
				(l->fn.csiz +1) >= 0 ){
				/* nonunique name && structure defined */
				char * memnam, * tabnam;
				register k;
				int j;
				int memi;
				j=dimtab[l->fn.csiz+1];
				for( ; (memi=dimtab[j]) >= 0; ++j ){
					tabnam = stab[memi].sname;
					memnam = stab[i].sname;
# ifndef BUG1
					if( ddebug>1 ){
						printf("member %.*s==%.*s?\n",
							NCHNAM, memnam, NCHNAM, tabnam);
						}
# endif
					if( stab[memi].sflags & SNONUNIQ ){
						for( k=0; k<NCHNAM; ++k ){
							if(*memnam++!=*tabnam)
								goto next;
							if(!*tabnam++) break;
							}
						r->tn.rval = i = memi;
						break;
						}
					next: continue;
					}
				if( memi < 0 )
					uerror("illegal member use: %.*s",
						NCHNAM, stab[i].sname);
				}
			else {
				register j;
				if( l->in.type != PTR+STRTY && l->in.type != PTR+UNIONTY ){
					if( stab[i].sflags & SNONUNIQ ){
						uerror( "nonunique name demands struct/union or struct/union pointer" );
						}
					else werror( "struct/union or struct/union pointer required" );
					}
				else if( (j=l->fn.csiz+1)<0 ) cerror( "undefined structure or union" );
				else if( !chkstr( i, dimtab[j], DECREF(l->in.type) ) ){
					werror( "illegal member use: %.*s", NCHNAM, stab[i].sname );
					}
				}

			p = stref( p );
			break;

		case UNARY MUL:
			if( l->in.op == UNARY AND ){
				p->in.op = l->in.op = FREE;
				p = l->in.left;
				}
			if( !ISPTR(l->in.type))uerror("illegal indirection");
			p->in.type = DECREF(l->in.type);
			p->fn.cdim = l->fn.cdim;
			p->fn.csiz = l->fn.csiz;
			break;

		case UNARY AND:
			switch( l->in.op ){

			case UNARY MUL:
				p->in.op = l->in.op = FREE;
				p = l->in.left;
			case NAME:
				p->in.type = INCREF( l->in.type );
				p->fn.cdim = l->fn.cdim;
				p->fn.csiz = l->fn.csiz;
				break;

			case COMOP:
				lr = buildtree( UNARY AND, l->in.right, NIL );
				p->in.op = l->in.op = FREE;
				p = buildtree( COMOP, l->in.left, lr );
				break;

			case QUEST:
				lr = buildtree( UNARY AND, l->in.right->in.right, NIL );
				ll = buildtree( UNARY AND, l->in.right->in.left, NIL );
				p->in.op = l->in.op = l->in.right->in.op = FREE;
				p = buildtree( QUEST, l->in.left, buildtree( COLON, ll, lr ) );
				break;

# ifdef ADDROREG
			case OREG:
				/* OREG was built in clocal()
				 * for an auto or formal parameter
				 * now its address is being taken
				 * local code must unwind it
				 * back to PLUS/MINUS REG ICON
				 * according to local conventions
				 */
				{
				extern NODE * addroreg();
				p->in.op = FREE;
				p = addroreg( l );
				}
				break;

# endif
			default:
				uerror( "unacceptable operand of &" );
				break;
				}
			break;

		case LS:
		case RS:
		case ASG LS:
		case ASG RS:
			if(tsize(p->in.right->in.type, p->in.right->fn.cdim, p->in.right->fn.csiz) > SZINT)
				p->in.right = makety(p->in.right, INT, 0, INT );
			break;

		case RETURN:
		case ASSIGN:
		case CAST:
			/* structure assignment */
			/* take the addresses of the two sides; then make an
			/* operator using STASG and
			/* the addresses of left and right */

			{
				register TWORD t;
				register d, s;

				if( l->fn.csiz != r->fn.csiz ) uerror( "assignment of different structures" );

				r = buildtree( UNARY AND, r, NIL );
				t = r->in.type;
				d = r->fn.cdim;
				s = r->fn.csiz;

				l = block( STASG, l, r, t, d, s );

				if( o == RETURN ){
					p->in.op = FREE;
					p = l;
					break;
					}

				p->in.op = UNARY MUL;
				p->in.left = l;
				p->in.right = NIL;
				break;
				}
		case COLON:
			/* structure colon */

			if( l->fn.csiz != r->fn.csiz ) uerror( "type clash in conditional" );
			break;

		case CALL:
			p->in.right = r = strargs( p->in.right );
		case UNARY CALL:
			if( !ISPTR(l->in.type)) uerror("illegal function");
			p->in.type = DECREF(l->in.type);
			if( !ISFTN(p->in.type)) uerror("illegal function");
			p->in.type = DECREF( p->in.type );
			p->fn.cdim = l->fn.cdim;
			p->fn.csiz = l->fn.csiz;
			if( l->in.op == UNARY AND && l->in.left->in.op == NAME &&
				l->in.left->tn.rval >= 0 && l->in.left->tn.rval != NONAME &&
				( (i=stab[l->in.left->tn.rval].sclass) == FORTRAN || i==UFORTRAN ) ){
				p->in.op += (FORTCALL-CALL);
				}
			if( p->in.type == STRTY || p->in.type == UNIONTY ){
				/* function returning structure */
				/*  make function really return ptr to str., with * */

				p->in.op += STCALL-CALL;
				p->in.type = INCREF( p->in.type );
				p = buildtree( UNARY MUL, p, NIL );

				}
			break;

		default:
			cerror( "other code %d", o );
			}

		}

	if( actions & CVTO ) p = oconvert(p);
	p = clocal(p);

# ifndef BUG1
	if( bdebug ) fwalk( p, eprint, 0 );
# endif

	return(p);

	}

NODE *
strargs( p ) register NODE *p;  { /* rewrite structure flavored arguments */

	if( p->in.op == CM ){
		p->in.left = strargs( p->in.left );
		p->in.right = strargs( p->in.right );
		return( p );
		}

	if( p->in.type == STRTY || p->in.type == UNIONTY ){
		p = block( STARG, p, NIL, p->in.type, p->fn.cdim, p->fn.csiz );
		p->in.left = buildtree( UNARY AND, p->in.left, NIL );
		p = clocal(p);
		}
	return( p );
	}

chkstr( i, j, type ) TWORD type; {
	/* is the MOS or MOU at stab[i] OK for strict reference by a ptr */
	/* i has been checked to contain a MOS or MOU */
	/* j is the index in dimtab of the members... */
	int k, kk;

	extern int ddebug;

# ifndef BUG1
	if( ddebug > 1 ) printf( "chkstr( %.*s(%d), %d )\n", NCHNAM, stab[i].sname, i, j );
# endif
	if( (k = j) < 0 ) uerror( "undefined structure or union" );
	else {
		for( ; (kk = dimtab[k] ) >= 0; ++k ){
			if( kk >= SYMTSZ ){
				cerror( "gummy structure" );
				return(1);
				}
			if( kk == i ) return( 1 );
			switch( stab[kk].stype ){

			case STRTY:
			case UNIONTY:
				if( type == STRTY ) continue;  /* no recursive looking for strs */
				if( hflag && chkstr( i, dimtab[stab[kk].sizoff+1], stab[kk].stype ) ){
					if( stab[kk].sname[0] == '$' ) return(0);  /* $FAKE */
					werror(
					"illegal member use: perhaps %.*s.%.*s?",
					NCHNAM,stab[kk].sname, NCHNAM,stab[i].sname );
					return(1);
					}
				}
			}
		}
	return( 0 );
	}

conval( p, o, q ) register NODE *p, *q; {
	/* apply the op o to the lval part of p; if binary, rhs is val */
	int i, u;
	CONSZ val;

	val = q->tn.lval;
	u = ISUNSIGNED(p->in.type) || ISUNSIGNED(q->in.type);
	if( u && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE);

	if( p->tn.rval != NONAME && q->tn.rval != NONAME ) return(0);
	if( q->tn.rval != NONAME && o!=PLUS ) return(0);
	if( p->tn.rval != NONAME && o!=PLUS && o!=MINUS ) return(0);

	switch( o ){

	case PLUS:
		p->tn.lval += val;
		if( p->tn.rval == NONAME ){
			p->tn.rval = q->tn.rval;
			p->in.type = q->in.type;
			}
		break;
	case MINUS:
		p->tn.lval -= val;
		break;
	case MUL:
		p->tn.lval *= val;
		break;
	case DIV:
		if( val == 0 ) uerror( "division by 0" );
		else p->tn.lval /= val;
		break;
	case MOD:
		if( val == 0 ) uerror( "division by 0" );
		else p->tn.lval %= val;
		break;
	case AND:
		p->tn.lval &= val;
		break;
	case OR:
		p->tn.lval |= val;
		break;
	case ER:
		p->tn.lval ^=  val;
		break;
	case LS:
		i = val;
		p->tn.lval = p->tn.lval << i;
		break;
	case RS:
		i = val;
		p->tn.lval = p->tn.lval >> i;
		break;

	case UNARY MINUS:
		p->tn.lval = - p->tn.lval;
		break;
	case COMPL:
		p->tn.lval = ~p->tn.lval;
		break;
	case NOT:
		p->tn.lval = !p->tn.lval;
		break;
	case LT:
		p->tn.lval = p->tn.lval < val;
		break;
	case LE:
		p->tn.lval = p->tn.lval <= val;
		break;
	case GT:
		p->tn.lval = p->tn.lval > val;
		break;
	case GE:
		p->tn.lval = p->tn.lval >= val;
		break;
	case ULT:
		p->tn.lval = (p->tn.lval-val)<0;
		break;
	case ULE:
		p->tn.lval = (p->tn.lval-val)<=0;
		break;
	case UGE:
		p->tn.lval = (p->tn.lval-val)>=0;
		break;
	case UGT:
		p->tn.lval = (p->tn.lval-val)>0;
		break;
	case EQ:
		p->tn.lval = p->tn.lval == val;
		break;
	case NE:
		p->tn.lval = p->tn.lval != val;
		break;
	default:
		return(0);
		}
	return(1);
	}

chkpun(p) register NODE *p; {

	/* checks p for the existance of a pun */

	/* this is called when the op of p is ASSIGN, RETURN, CAST, COLON, or relational */

	/* one case is when enumerations are used: this applies only to lint */
	/* in the other case, one operand is a pointer, the other integer type */
	/* we check that this integer is in fact a constant zero... */

	/* in the case of ASSIGN, any assignment of pointer to integer is illegal */
	/* this falls out, because the LHS is never 0 */

	register NODE *q;
	register t1, t2;
	register d1, d2;

	t1 = p->in.left->in.type;
	t2 = p->in.right->in.type;

	if( t1==ENUMTY || t2==ENUMTY ) { /* check for enumerations */
		if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE ) {
			uerror( "illegal comparison of enums" );
			return;
			}
		if( t1==ENUMTY && t2==ENUMTY && p->in.left->fn.csiz==p->in.right->fn.csiz ) return;
		werror( "enumeration type clash, operator %s", opst[p->in.op] );
		return;
		}

	if( ISPTR(t1) || ISARY(t1) ) q = p->in.right;
	else q = p->in.left;

	if( !ISPTR(q->in.type) && !ISARY(q->in.type) ){
		if( q->in.op != ICON || q->tn.lval != 0 ){
			combo( "pointer/integer", p );
			}
		}
	else {
		d1 = p->in.left->fn.cdim;
		d2 = p->in.right->fn.cdim;
		for( ;; ){
			if( t1 == t2 ) {;
				if(p->in.left->fn.csiz!=p->in.right->fn.csiz) {
					combo( "structure pointer", p );
					}
				return;
				}
			if( ISARY(t1) || ISPTR(t1) ){
				if( !ISARY(t2) && !ISPTR(t2) ) break;
				if( ISARY(t1) && ISARY(t2) &&
					dimtab[d1] != dimtab[d2] ){
					combo( "array size", p );
					return;
					}
				if( ISARY(t1) ) ++d1;
				if( ISARY(t2) ) ++d2;
				}
			else break;
			t1 = DECREF(t1);
			t2 = DECREF(t2);
			}
		combo( "pointer", p );
		}

	}

combo( s, p ) char *s; register NODE *p; {
	char buf[100];
	sprintf( buf, "illegal %s combination, op %s", s, opst[p->tn.op] );
	werror( buf );
	}

NODE *
stref( p ) register NODE *p; {

	TWORD t;
	int d, s, dsc, align;
	OFFSZ off;
	register struct symtab *q;

	/* make p->x */
	/* this is also used to reference automatic variables */

	q = &stab[p->in.right->tn.rval];
	p->in.right->in.op = FREE;
	p->in.op = FREE;
	p = pconvert( p->in.left );

	/* make p look like ptr to x */

	if( !ISPTR(p->in.type)){
		p->in.type = PTR+UNIONTY;
		}

	t = INCREF( q->stype );
	d = q->dimoff;
	s = q->sizoff;

	p = makety( p, t, d, s );

	/* compute the offset to be added */

	off = q->offset;
	dsc = q->sclass;

	if( dsc & FIELD ) {  /* normalize offset */
		switch(q->stype) {

		case CHAR:
		case UCHAR:
			align = ALCHAR;
			s = CHAR;
			break;

		case SHORT:
		case USHORT:
			align = ALSHORT;
			s = SHORT;
			break;

		case INT:
		case UNSIGNED:
			align = ALINT;
			s = INT;
			break;

# ifdef LONGFIELDS
		case LONG:
		case ULONG:
			align = ALLONG;
			s = LONG;
			break;
# endif

		default:
			cerror( "undefined bit field type" );
			}
		off = (off/align)*align;
		}
	if( off != 0 ) p = clocal( block( PLUS, p, offcon( off, t, d, s ), t, d, s ) );

	p = buildtree( UNARY MUL, p, NIL );

	/* if field, build field info */

	if( dsc & FIELD ){
		p = block( FLD, p, NIL, q->stype, 0, q->sizoff );
		p->tn.rval = PKFIELD( dsc&FLDSIZ, q->offset%align );
		}

	return( clocal(p) );
	}

notlval(p) register NODE *p; {

	/* return 0 if p an lvalue, 1 otherwise */

	again:

	switch( p->in.op ){

	case FLD:
		p = p->in.left;
		goto again;

	case UNARY MUL:
		/* fix the &(a=b) bug, given that a and b are structures */
		if( p->in.left->in.op == STASG ) return( 1 );
		/* and the f().a bug, given that f returns a structure */
		if( p->in.left->in.op == UNARY STCALL ||
		    p->in.left->in.op == STCALL ) return( 1 );
	case NAME:
	case OREG:
		if( ISARY(p->in.type) || ISFTN(p->in.type) ) return(1);
	case REG:
		return(0);

	default:
		return(1);

		}

	}

NODE *
bcon( i ){ /* make a constant node with value i */
	register NODE *p;

	p = block( ICON, NIL, NIL, INT, 0, INT );
	p->tn.lval = i;
	p->tn.rval = NONAME;
	return( clocal(p) );
	}

NODE *
bpsize(p) register NODE *p; {
	return( offcon( psize(p), p->in.type, p->fn.cdim, p->fn.csiz ) );
	}

OFFSZ
psize( p ) NODE *p; {
	/* p is a node of type pointer; psize returns the
	   size of the thing pointed to */

	if( !ISPTR(p->in.type) ){
		uerror( "pointer required");
		return( SZINT );
		}
	/* note: no pointers to fields */
	return( tsize( DECREF(p->in.type), p->fn.cdim, p->fn.csiz ) );
	}

NODE *
convert( p, f )  register NODE *p; {
	/*  convert an operand of p
	    f is either CVTL or CVTR
	    operand has type int, and is converted by the size of the other side
	    */

	register NODE *q, *r;

	q = (f==CVTL)?p->in.left:p->in.right;

	r = block( PMCONV,
		q, bpsize(f==CVTL?p->in.right:p->in.left), INT, 0, INT );
	r = clocal(r);
	if( f == CVTL )
		p->in.left = r;
	else
		p->in.right = r;
	return(p);

	}

econvert( p ) register NODE *p; {

	/* change enums to ints, or appropriate types */

	register TWORD ty;

	if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) {
		if( dimtab[ p->fn.csiz ] == SZCHAR ) ty = CHAR;
		else if( dimtab[ p->fn.csiz ] == SZINT ) ty = INT;
		else if( dimtab[ p->fn.csiz ] == SZSHORT ) ty = SHORT;
		else ty = LONG;
		ty = ctype( ty );
		p->fn.csiz = ty;
		MODTYPE(p->in.type,ty);
		if( p->in.op == ICON && ty != LONG ) p->in.type = p->fn.csiz = INT;
		}
	}

NODE *
pconvert( p ) register NODE *p; {

	/* if p should be changed into a pointer, do so */

	if( ISARY( p->in.type) ){
		p->in.type = DECREF( p->in.type );
		++p->fn.cdim;
		return( buildtree( UNARY AND, p, NIL ) );
		}
	if( ISFTN( p->in.type) )
		return( buildtree( UNARY AND, p, NIL ) );

	return( p );
	}

NODE *
oconvert(p) register NODE *p; {
	/* convert the result itself: used for pointer and unsigned */

	switch(p->in.op) {

	case LE:
	case LT:
	case GE:
	case GT:
		if( ISUNSIGNED(p->in.left->in.type) || ISUNSIGNED(p->in.right->in.type) )  p->in.op += (ULE-LE);
	case EQ:
	case NE:
		return( p );

	case MINUS:
		return(  clocal( block( PVCONV,
			p, bpsize(p->in.left), INT, 0, INT ) ) );
		}

	cerror( "illegal oconvert: %d", p->in.op );

	return(p);
	}

NODE *
ptmatch(p)  register NODE *p; {

	/* makes the operands of p agree; they are
	   either pointers or integers, by this time */
	/* with MINUS, the sizes must be the same */
	/* with COLON, the types must be the same */

	TWORD t1, t2, t;
	int o, d2, d, s2, s;

	o = p->in.op;
	t = t1 = p->in.left->in.type;
	t2 = p->in.right->in.type;
	d = p->in.left->fn.cdim;
	d2 = p->in.right->fn.cdim;
	s = p->in.left->fn.csiz;
	s2 = p->in.right->fn.csiz;

	switch( o ){

	case ASSIGN:
	case RETURN:
	case CAST:
		{  break; }

	case MINUS:
		{  if( psize(p->in.left) != psize(p->in.right) ){
			uerror( "illegal pointer subtraction");
			}
		   break;
		   }
	case COLON:
		{  if( t1 != t2 ) uerror( "illegal types in :");
		   break;
		   }
	default:  /* must work harder: relationals or comparisons */

		if( !ISPTR(t1) ){
			t = t2;
			d = d2;
			s = s2;
			break;
			}
		if( !ISPTR(t2) ){
			break;
			}

		/* both are pointers */
		if( talign(t2,s2) < talign(t,s) ){
			t = t2;
			s = s2;
			}
		break;
		}

	p->in.left = makety( p->in.left, t, d, s );
	p->in.right = makety( p->in.right, t, d, s );
	if( o!=MINUS && !logop(o) ){

		p->in.type = t;
		p->fn.cdim = d;
		p->fn.csiz = s;
		}

	return(clocal(p));
	}

int tdebug = 0;

NODE *
tymatch(p)  register NODE *p; {

	/* satisfy the types of various arithmetic binary ops */

	/* rules are:
		if assignment, op, type of LHS
		if any float or doubles, make double
		if any longs, make long
		otherwise, make int
		if either operand is unsigned, the result is...
	*/

	register TWORD t1, t2, t, tu;
	register o, u;

	o = p->in.op;

	t1 = p->in.left->in.type;
	t2 = p->in.right->in.type;
	if( (t1==UNDEF || t2==UNDEF) && o!=CAST )
		uerror("void type illegal in expression");

	u = 0;
	if( ISUNSIGNED(t1) ){
		u = 1;
		t1 = DEUNSIGN(t1);
		}
	if( ISUNSIGNED(t2) ){
		u = 1;
		t2 = DEUNSIGN(t2);
		}

	if( ( t1 == CHAR || t1 == SHORT ) && o!= RETURN ) t1 = INT;
	if( t2 == CHAR || t2 == SHORT ) t2 = INT;

	if( t1==DOUBLE || t1==FLOAT || t2==DOUBLE || t2==FLOAT ) t = DOUBLE;
	else if( t1==LONG || t2==LONG ) t = LONG;
	else t = INT;

	if( asgop(o) ){
		tu = p->in.left->in.type;
		t = t1;
		}
	else {
		tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t;
		}

	/* because expressions have values that are at least as wide
	   as INT or UNSIGNED, the only conversions needed
	   are those involving FLOAT/DOUBLE, and those
	   from LONG to INT and ULONG to UNSIGNED */

	if( t != t1 ) p->in.left = makety( p->in.left, tu, 0, (int)tu );

	if( t != t2 || o==CAST ) p->in.right = makety( p->in.right, tu, 0, (int)tu );

	if( asgop(o) ){
		p->in.type = p->in.left->in.type;
		p->fn.cdim = p->in.left->fn.cdim;
		p->fn.csiz = p->in.left->fn.csiz;
		}
	else if( !logop(o) ){
		p->in.type = tu;
		p->fn.cdim = 0;
		p->fn.csiz = t;
		}

# ifndef BUG1
	if( tdebug ) printf( "tymatch(%o): %o %s %o => %o\n",p,t1,opst[o],t2,tu );
# endif

	return(p);
	}

NODE *
makety( p, t, d, s ) register NODE *p; TWORD t; {
	/* make p into type t by inserting a conversion */

	if( p->in.type == ENUMTY && p->in.op == ICON ) econvert(p);
	if( t == p->in.type ){
		p->fn.cdim = d;
		p->fn.csiz = s;
		return( p );
		}

	if( t & TMASK ){
		/* non-simple type */
		return( block( PCONV, p, NIL, t, d, s ) );
		}

	if( p->in.op == ICON ){
		if( t==DOUBLE||t==FLOAT ){
			p->in.op = FCON;
			if( ISUNSIGNED(p->in.type) ){
				p->fpn.dval = /* (unsigned CONSZ) */ p->tn.lval;
				}
			else {
				p->fpn.dval = p->tn.lval;
				}

			p->in.type = p->fn.csiz = t;
			return( clocal(p) );
			}
		}

	return( block( SCONV, p, NIL, t, d, s ) );

	}

NODE *
block( o, l, r, t, d, s ) register NODE *l, *r; TWORD t; {

	register NODE *p;

	p = talloc();
	p->in.op = o;
	p->in.left = l;
	p->in.right = r;
	p->in.type = t;
	p->fn.cdim = d;
	p->fn.csiz = s;
	return(p);
	}

icons(p) register NODE *p; {
	/* if p is an integer constant, return its value */
	int val;

	if( p->in.op != ICON ){
		uerror( "constant expected");
		val = 1;
		}
	else {
		val = p->tn.lval;
		if( val != p->tn.lval ) uerror( "constant too big for cross-compiler" );
		}
	tfree( p );
	return(val);
	}

/* 	the intent of this table is to examine the
	operators, and to check them for
	correctness.

	The table is searched for the op and the
	modified type (where this is one of the
	types INT (includes char and short), LONG,
	DOUBLE (includes FLOAT), and POINTER

	The default action is to make the node type integer

	The actions taken include:
		PUN	  check for puns
		CVTL	  convert the left operand
		CVTR	  convert the right operand
		TYPL	  the type is determined by the left operand
		TYPR	  the type is determined by the right operand
		TYMATCH	  force type of left and right to match, by inserting conversions
		PTMATCH	  like TYMATCH, but for pointers
		LVAL	  left operand must be lval
		CVTO	  convert the op
		NCVT	  do not convert the operands
		OTHER	  handled by code
		NCVTR	  convert the left operand, not the right...

	*/

# define MINT 01  /* integer */
# define MDBI 02   /* integer or double */
# define MSTR 04  /* structure */
# define MPTR 010  /* pointer */
# define MPTI 020  /* pointer or integer */
# define MENU 040 /* enumeration variable or member */

opact( p )  NODE *p; {

	register mt12, mt1, mt2, o;

	mt12 = 0;

	switch( optype(o=p->in.op) ){

	case BITYPE:
		mt12=mt2 = moditype( p->in.right->in.type );
	case UTYPE:
		mt12 &= (mt1 = moditype( p->in.left->in.type ));

		}

	switch( o ){

	case NAME :
	case STRING :
	case ICON :
	case FCON :
	case CALL :
	case UNARY CALL:
	case UNARY MUL:
		{  return( OTHER ); }
	case UNARY MINUS:
		if( mt1 & MDBI ) return( TYPL );
		break;

	case COMPL:
		if( mt1 & MINT ) return( TYPL );
		break;

	case UNARY AND:
		{  return( NCVT+OTHER ); }
	case INIT:
	case CM:
	case NOT:
	case CBRANCH:
	case ANDAND:
	case OROR:
		return( 0 );

	case MUL:
	case DIV:
		if( mt12 & MDBI ) return( TYMATCH );
		break;

	case MOD:
	case AND:
	case OR:
	case ER:
		if( mt12 & MINT ) return( TYMATCH );
		break;

	case LS:
	case RS:
		if( mt12 & MINT ) return( TYMATCH+OTHER );
		break;

	case EQ:
	case NE:
	case LT:
	case LE:
	case GT:
	case GE:
		if( (mt1&MENU)||(mt2&MENU) ) return( PTMATCH+PUN+NCVT );
		if( mt12 & MDBI ) return( TYMATCH+CVTO );
		else if( mt12 & MPTR ) return( PTMATCH+PUN );
		else if( mt12 & MPTI ) return( PTMATCH+PUN );
		else break;

	case QUEST:
	case COMOP:
		if( mt2&MENU ) return( TYPR+NCVTR );
		return( TYPR );

	case STREF:
		return( NCVTR+OTHER );

	case FORCE:
		return( TYPL );

	case COLON:
		if( mt12 & MENU ) return( NCVT+PUN+PTMATCH );
		else if( mt12 & MDBI ) return( TYMATCH );
		else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN );
		else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN );
		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN );
		else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER );
		break;

	case ASSIGN:
	case RETURN:
		if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER );
	case CAST:
		if(o==CAST && mt1==0)return(TYPL+TYMATCH);
		if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH );
		else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN );
		else if( mt12 == 0 ) break;
		else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN );
		else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
		break;

	case ASG LS:
	case ASG RS:
		if( mt12 & MINT ) return( TYPL+LVAL+OTHER );
		break;

	case ASG MUL:
	case ASG DIV:
		if( mt12 & MDBI ) return( LVAL+TYMATCH );
		break;

	case ASG MOD:
	case ASG AND:
	case ASG OR:
	case ASG ER:
		if( mt12 & MINT ) return( LVAL+TYMATCH );
		break;

	case ASG PLUS:
	case ASG MINUS:
	case INCR:
	case DECR:
		if( mt12 & MDBI ) return( TYMATCH+LVAL );
		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR );
		break;

	case MINUS:
		if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN );
		if( mt2 & MPTR ) break;
	case PLUS:
		if( mt12 & MDBI ) return( TYMATCH );
		else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+CVTR );
		else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL );

		}
	uerror( "operands of %s have incompatible types", opst[o] );
	return( NCVT );
	}

moditype( ty ) TWORD ty; {

	switch( ty ){

	case TVOID:
	case UNDEF:
		return(0); /* type is void */
	case ENUMTY:
	case MOETY:
		return( MENU );

	case STRTY:
	case UNIONTY:
		return( MSTR );

	case CHAR:
	case SHORT:
	case UCHAR:
	case USHORT:
		return( MINT|MPTI|MDBI );
	case UNSIGNED:
	case ULONG:
	case INT:
	case LONG:
		return( MINT|MDBI|MPTI );
	case FLOAT:
	case DOUBLE:
		return( MDBI );
	default:
		return( MPTR|MPTI );

		}
	}

NODE *
doszof( p )  register NODE *p; {
	/* do sizeof p */
	int i;

	/* whatever is the meaning of this if it is a bitfield? */
	i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR;

	tfree(p);
	if( i <= 0 ) werror( "sizeof returns 0" );
	return( bcon( i ) );
	}

# ifndef BUG2
eprint( p, down, a, b ) register NODE *p; int *a, *b; {
	register ty;

	*a = *b = down+1;
	while( down > 1 ){
		printf( "\t" );
		down -= 2;
		}
	if( down ) printf( "    " );

	ty = optype( p->in.op );

	printf("%o) %s, ", p, opst[p->in.op] );
	if( ty == LTYPE ){
		printf( CONFMT, p->tn.lval );
		printf( ", %d, ", p->tn.rval );
		}
	tprint( p->in.type );
	printf( ", %d, %d\n", p->fn.cdim, p->fn.csiz );
	}
# endif

prtdcon( p ) register NODE *p; {
	int i;

	if( p->in.op == FCON ){
		locctr( STRNG );
		defalign( ALDOUBLE );
		deflab( i = getlab() );
		fincode( p->fpn.dval, SZDOUBLE );
		p->tn.lval = 0;
		p->tn.rval = -i;
		p->in.type = DOUBLE;
		p->in.op = NAME;
		}
	}


int edebug = 0;
ecomp( p ) register NODE *p; {
# ifndef BUG2
	if( edebug ) fwalk( p, eprint, 0 );
# endif
	if( !reached ){
		werror( "statement not reached" );
		reached = 1;
		}
	p = optim(p);
	walkf( p, prtdcon );
	locctr( PROG );
	ecode( p );
	tfree(p);
	}

# ifdef STDPRTREE
# ifndef ONEPASS

prtree(p) register NODE *p; {

	register struct symtab *q;
	register ty;

# ifdef MYPRTREE
	MYPRTREE(p);  /* local action can be taken here; then return... */
#endif

	ty = optype(p->in.op);

	printf( "%d\t", p->in.op );

	if( ty == LTYPE ) {
		printf( CONFMT, p->tn.lval );
		printf( "\t" );
		}
	if( ty != BITYPE ) {
		if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" );
		else printf( "%d\t", p->tn.rval );
		}

	printf( "%o\t", p->in.type );

	/* handle special cases */

	switch( p->in.op ){

	case NAME:
	case ICON:
		/* print external name */
		if( p->tn.rval == NONAME ) printf( "\n" );
		else if( p->tn.rval >= 0 ){
			q = &stab[p->tn.rval];
			printf(  "%s\n", exname(q->sname) );
			}
		else { /* label */
			printf( LABFMT, -p->tn.rval );
			}
		break;

	case STARG:
	case STASG:
	case STCALL:
	case UNARY STCALL:
		/* print out size */
		/* use lhs size, in order to avoid hassles with the structure `.' operator */

		/* note: p->in.left not a field... */
		printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) );
		printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) );
		break;

	default:
		printf(  "\n" );
		}

	if( ty != LTYPE ) prtree( p->in.left );
	if( ty == BITYPE ) prtree( p->in.right );

	}

# else

p2tree(p) register NODE *p; {
	register ty;

# ifdef MYP2TREE
	MYP2TREE(p);  /* local action can be taken here; then return... */
# endif

	ty = optype(p->in.op);

	switch( p->in.op ){

	case NAME:
	case ICON:
		if( p->tn.rval == NONAME ) p->in.name[0] = '\0';
		else if( p->tn.rval >= 0 ){ /* copy name from exname */
			register char *cp;
			register i;
			cp = exname( stab[p->tn.rval].sname );
			for( i=0; i<NCHNAM; ++i ) p->in.name[i] = *cp++;
			}
		else sprintf( p->in.name, LABFMT, -p->tn.rval );
		break;

	case STARG:
	case STASG:
	case STCALL:
	case UNARY STCALL:
		/* set up size parameters */
		p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim,p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR;
		p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR;
		break;

	case REG:
		rbusy( p->tn.rval, p->in.type );
	default:
		p->in.name[0] = '\0';
		}

	p->in.rall = NOPREF;

	if( ty != LTYPE ) p2tree( p->in.left );
	if( ty == BITYPE ) p2tree( p->in.right );
	}

# endif
# endif
f( p->in.name, LABFMT, -p->tn.rval );
		break;

	case STARG:
	case STASG:
	c86/xdefs.c                                                                                            444      26      12         5066  2537050424   5743                                                                                                                                                                                                                                                                                                                                                                      # include "mfile1"

/*	communication between lexical routines	*/

char	ftitle[100] = "";   	/* title of the file */
int	lineno;		/* line number of the input file */

CONSZ lastcon;  /* the last constant read by the lexical analyzer */
double dcon;   /* the last double read by the lexical analyzer */


/*	symbol table maintainence */

struct symtab stab[SYMTSZ+1];  /* one extra slot for scratch */

int	curftn;  /* "current" function */
int	ftnno;  /* "current" function number */

int	curclass,	  /* current storage class */
	instruct,	/* "in structure" flag */
	stwart,		/* for accessing names which are structure members or names */
	blevel,		/* block level: 0 for extern, 1 for ftn args, >=2 inside function */
	curdim;		/* current offset into the dimension table */
	
int	dimtab[ DIMTABSZ ];

int	paramstk[ PARAMSZ ];  /* used in the definition of function parameters */
int	paramno;	  /* the number of parameters */
int	autooff,	/* the next unused automatic offset */
	argoff,	/* the next unused argument offset */
	strucoff;	/*  the next structure offset position */
int	regvar;		/* the next free register for register variables */
int	minrvar;	/* the smallest that regvar gets witing a function */
OFFSZ	inoff;		/* offset of external element being initialized */
int	brkflag = 0;	/* complain about break statements not reached */

struct sw swtab[SWITSZ];  /* table for cases within a switch */
struct sw *swp;  /* pointer to next free entry in swtab */
int swx;  /* index of beginning of cases for current switch */

/* debugging flag */
int xdebug = 0;

int strflg;  /* if on, strings are to be treated as lists */

int reached;	/* true if statement can be reached... */

int idname;	/* tunnel to buildtree for name id's */


NODE node[TREESZ];

int cflag = 0;  /* do we check for funny casts */
int hflag = 0;  /* do we check for various heuristics which may indicate errors */
int pflag = 0;  /* do we check for portable constructions */

int brklab;
int contlab;
int flostat;
int retlab = NOLAB;
int retstat;

/* save array for break, continue labels, and flostat */

int asavbc[BCSZ];
int *psavbc = asavbc ;

# ifndef BUG1
static char *
ccnames[] = { /* names of storage classes */
	"SNULL",
	"AUTO",
	"EXTERN",
	"STATIC",
	"REGISTER",
	"EXTDEF",
	"LABEL",
	"ULABEL",
	"MOS",
	"PARAM",
	"STNAME",
	"MOU",
	"UNAME",
	"TYPEDEF",
	"FORTRAN",
	"ENAME",
	"MOE",
	"UFORTRAN",
	"USTATIC",
	};

char * scnames( c ) register c; {
	/* return the name for storage class c */
	static char buf[12];
	if( c&FIELD ){
		sprintf( buf, "FIELD[%d]", c&FLDSIZ );
		return( buf );
		}
	return( ccnames[c] );
	}
# endif
nt *psavbc = asavbc ;

# ifndef BUG1
static char *
ccnames[] = { /* names of storage classes */
	"SNULL",
	"AUTO",
	"EXTERN",
	"STATIC",
	"REGISTER",
	"EXTDEF",
	"LABEL",
	"ULABEL",
	"MOS",
	"PARAM",
	"STNAME",
	"MOU",
	"UNAME",
	"TYPEDEF",
	"FORTRAN",
	"ENAME",
	"MOE",
	"UFORTRAN",
	"USTATIC",
	};

char * scnames( c ) register c; {
	/* return the name for storage class c */
	static char buf[12];
	if( c&FIELD ){
		sprintf( buf, "FIELD[%d]", c&FLDSIZ );
	c86/common                                                                                             666     140      12        13271  3356562600   5745                                                                                                                                                                                                                                                                                                                                                                      # ifndef EXIT
# define EXIT exit
# endif

int nerrors = 0;  /* number of errors */

unsigned int offsz;

unsigned caloff(){
	register i;
	unsigned int temp;
	unsigned int off;
	temp = 1;
	i = 0;
	do {
		temp <<= 1;
		++i;
		} while( temp > 0 );
	off = 1 << (i-1);
	return (off);
	}

NODE *lastfree;  /* pointer to last free node; (for allocator) */

	/* VARARGS1 */


uerror( s, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 )
 char *s; { /* nonfatal error message */

	/* Modified 9/28/84 by JSP to correct non-printing bug... 	*/
	/* an inelegant, but workable solution.				*/

	/* the routine where is different for pass 1 and pass 2;
	/*  it tells where the error took place */

	++nerrors;
	where('u');
	fprintf( stderr, s, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 );
	fprintf( stderr, "\n" );
	if( nerrors > 30 ) cerror( "too many errors");
	}

	/* VARARGS1 */
cerror( s, a, b, c ) char *s; { /* compiler error: die */
	where('c');
	if( nerrors && nerrors <= 30 ){ /* give the compiler the benefit of the doubt */
		fprintf( stderr, "cannot recover from earlier errors: goodbye!\n" );
		}
	else {
		fprintf( stderr, "compiler error: " );
		fprintf( stderr, s, a, b, c );
		fprintf( stderr, "\n" );
		}
	EXIT(1);
	}

	/* VARARGS1 */
werror( s, a, b ) char *s; {  /* warning */
	where('w');
	fprintf( stderr, "warning: " );
	fprintf( stderr, s, a, b );
	fprintf( stderr, "\n" );
	}

tinit(){ /* initialize expression tree search */

	NODE *p;

	for( p=node; p<= &node[TREESZ-1]; ++p ) p->in.op = FREE;
	lastfree = node;

	}

# define TNEXT(p) (p== &node[TREESZ-1]?node:p+1)

NODE *
talloc(){
	NODE *p, *q;

	q = lastfree;
	for( p = TNEXT(q); p!=q; p= TNEXT(p))
		if( p->in.op ==FREE ) return(lastfree=p);

	cerror( "out of tree space; simplify expression");
	/* NOTREACHED */
	}

tcheck(){ /* ensure that all nodes have been freed */

	NODE *p;

	if( !nerrors )
		for( p=node; p<= &node[TREESZ-1]; ++p )
			if( p->in.op != FREE ) cerror( "wasted space: %o", p );
	tinit();
	}
tfree( p )  NODE *p; {
	/* free the tree p */
	extern tfree1();

	if( p->in.op != FREE ) walkf( p, tfree1 );

	}

tfree1(p)  NODE *p; {
	if( p == 0 ) cerror( "freeing blank tree!");
	else p->in.op = FREE;
	}

fwalk( t, f, down ) register NODE *t; int (*f)(); {

	int down1, down2;

	more:
	down1 = down2 = 0;

	(*f)( t, down, &down1, &down2 );

	switch( optype( t->in.op ) ){

	case BITYPE:
		fwalk( t->in.left, f, down1 );
		t = t->in.right;
		down = down2;
		goto more;

	case UTYPE:
		t = t->in.left;
		down = down1;
		goto more;

		}
	}

walkf( t, f ) register NODE *t;  int (*f)(); {
	register opty;

	opty = optype(t->in.op);

	if( opty != LTYPE ) walkf( t->in.left, f );
	if( opty == BITYPE ) walkf( t->in.right, f );
	(*f)( t );
	}



int dope[ DSIZE ];
char *opst[DSIZE];

struct dopest { int dopeop; char opst[8]; int dopeval; } indope[] = {

	NAME, "NAME", LTYPE,
	STRING, "STRING", LTYPE,
	REG, "REG", LTYPE,
	OREG, "OREG", LTYPE,
	ICON, "ICON", LTYPE,
	FCON, "FCON", LTYPE,
	CCODES, "CCODES", LTYPE,
	UNARY MINUS, "U-", UTYPE,
	UNARY MUL, "U*", UTYPE,
	UNARY AND, "U&", UTYPE,
	UNARY CALL, "UCALL", UTYPE|CALLFLG,
	UNARY FORTCALL, "UFCALL", UTYPE|CALLFLG,
	NOT, "!", UTYPE|LOGFLG,
	COMPL, "~", UTYPE,
	FORCE, "FORCE", UTYPE,
	INIT, "INIT", UTYPE,
	SCONV, "SCONV", UTYPE,
	PCONV, "PCONV", UTYPE,
	PLUS, "+", BITYPE|FLOFLG|SIMPFLG|COMMFLG,
	ASG PLUS, "+=", BITYPE|ASGFLG|ASGOPFLG|FLOFLG|SIMPFLG|COMMFLG,
	MINUS, "-", BITYPE|FLOFLG|SIMPFLG,
	ASG MINUS, "-=", BITYPE|FLOFLG|SIMPFLG|ASGFLG|ASGOPFLG,
	MUL, "*", BITYPE|FLOFLG|MULFLG,
	ASG MUL, "*=", BITYPE|FLOFLG|MULFLG|ASGFLG|ASGOPFLG,
	AND, "&", BITYPE|SIMPFLG|COMMFLG,
	ASG AND, "&=", BITYPE|SIMPFLG|COMMFLG|ASGFLG|ASGOPFLG,
	QUEST, "?", BITYPE,
	COLON, ":", BITYPE,
	ANDAND, "&&", BITYPE|LOGFLG,
	OROR, "||", BITYPE|LOGFLG,
	CM, ",", BITYPE,
	COMOP, ",OP", BITYPE,
	ASSIGN, "=", BITYPE|ASGFLG,
	DIV, "/", BITYPE|FLOFLG|MULFLG|DIVFLG,
	ASG DIV, "/=", BITYPE|FLOFLG|MULFLG|DIVFLG|ASGFLG|ASGOPFLG,
	MOD, "%", BITYPE|DIVFLG,
	ASG MOD, "%=", BITYPE|DIVFLG|ASGFLG|ASGOPFLG,
	LS, "<<", BITYPE|SHFFLG,
	ASG LS, "<<=", BITYPE|SHFFLG|ASGFLG|ASGOPFLG,
	RS, ">>", BITYPE|SHFFLG,
	ASG RS, ">>=", BITYPE|SHFFLG|ASGFLG|ASGOPFLG,
	OR, "|", BITYPE|COMMFLG|SIMPFLG,
	ASG OR, "|=", BITYPE|COMMFLG|SIMPFLG|ASGFLG|ASGOPFLG,
	ER, "^", BITYPE|COMMFLG|SIMPFLG,
	ASG ER, "^=", BITYPE|COMMFLG|SIMPFLG|ASGFLG|ASGOPFLG,
	INCR, "++", BITYPE|ASGFLG,
	DECR, "--", BITYPE|ASGFLG,
	STREF, "->", BITYPE,
	CALL, "CALL", BITYPE|CALLFLG,
	FORTCALL, "FCALL", BITYPE|CALLFLG,
	EQ, "==", BITYPE|LOGFLG,
	NE, "!=", BITYPE|LOGFLG,
	LE, "<=", BITYPE|LOGFLG,
	LT, "<", BITYPE|LOGFLG,
	GE, ">", BITYPE|LOGFLG,
	GT, ">", BITYPE|LOGFLG,
	UGT, "UGT", BITYPE|LOGFLG,
	UGE, "UGE", BITYPE|LOGFLG,
	ULT, "ULT", BITYPE|LOGFLG,
	ULE, "ULE", BITYPE|LOGFLG,
	ARS, "A>>", BITYPE,
	TYPE, "TYPE", LTYPE,
	LB, "[", BITYPE,
	CBRANCH, "CBRANCH", BITYPE,
	FLD, "FLD", UTYPE,
	PMCONV, "PMCONV", BITYPE,
	PVCONV, "PVCONV", BITYPE,
	RETURN, "RETURN", BITYPE|ASGFLG|ASGOPFLG,
	CAST, "CAST", BITYPE|ASGFLG|ASGOPFLG,
	GOTO, "GOTO", UTYPE,
	STASG, "STASG", BITYPE|ASGFLG,
	STARG, "STARG", UTYPE,
	STCALL, "STCALL", BITYPE|CALLFLG,
	UNARY STCALL, "USTCALL", UTYPE|CALLFLG,

-1,	0
};

mkdope(){
	register struct dopest *q;

	for( q = indope; q->dopeop >= 0; ++q ){
		dope[q->dopeop] = q->dopeval;
		opst[q->dopeop] = q->opst;
		}
	}
# ifndef BUG4
tprint( t )  TWORD t; { /* output a nice description of the type of t */

	static char * tnames[] = {
		"undef",
		"farg",
		"char",
		"short",
		"int",
		"long",
		"float",
		"double",
		"strty",
		"unionty",
		"enumty",
		"moety",
		"uchar",
		"ushort",
		"unsigned",
		"ulong",
		"?", "?"
		};

	for(;; t = DECREF(t) ){

		if( ISPTR(t) ) printf( "PTR " );
		else if( ISFTN(t) ) printf( "FTN " );
		else if( ISARY(t) ) printf( "ARY " );
		else {
			printf( "%s", tnames[t] );
			return;
			}
		}
	}
# endif
G4
tprint( t )  TWORD t; { /* output a nice description of the type of t */

	static char * tnames[] = {
		"undef",
		"farg",
		"char",
		"short",
		"int",
		"long",
		"float",
		"double",
		"strty",
		"unionty",
		"enumty",
		"moety",
		"uchar",
		"ushort",
		"unsigned",
		"ulong",
		"?", "?"
		};

	for(;; t = DECREF(t) ){

c86/manifest                                                                                           666      26      12        14501  3227134504   6236                                                                                                                                                                                                                                                                                                                                                                      
# include <stdio.h>
/*	manifest constant file for the lex/yacc interface */

# define ERROR 1
# define NAME 2
# define STRING 3
# define ICON 4
# define FCON 5
# define PLUS 6
# define MINUS 8
# define MUL 11
# define AND 14
# define OR 17
# define ER 19
# define QUEST 21
# define COLON 22
# define ANDAND 23
# define OROR 24

/*	special interfaces for yacc alone */
/*	These serve as abbreviations of 2 or more ops:
	ASOP	=, = ops
	RELOP	LE,LT,GE,GT
	EQUOP	EQ,NE
	DIVOP	DIV,MOD
	SHIFTOP	LS,RS
	ICOP	ICR,DECR
	UNOP	NOT,COMPL
	STROP	DOT,STREF

	*/
# define ASOP 25
# define RELOP 26
# define EQUOP 27
# define DIVOP 28
# define SHIFTOP 29
# define INCOP 30
# define UNOP 31
# define STROP 32

/*	reserved words, etc */
# define TYPE 33
# define CLASS 34
# define STRUCT 35
# define RETURN 36
# define GOTO 37
# define IF 38
# define ELSE 39
# define SWITCH 40
# define BREAK 41
# define CONTINUE 42
# define WHILE 43
# define DO 44
# define FOR 45
# define DEFAULT 46
# define CASE 47
# define SIZEOF 48
# define ENUM 49


/*	little symbols, etc. */
/*	namely,

	LP	(
	RP	)

	LC	{
	RC	}

	LB	[
	RB	]

	CM	,
	SM	;

	*/

# define LP 50
# define RP 51
# define LC 52
# define RC 53
# define LB 54
# define RB 55
# define CM 56
# define SM 57
# define ASSIGN 58

/*	END OF YACC */

/*	left over tree building operators */
# define COMOP 59
# define DIV 60
# define MOD 62
# define LS 64
# define RS 66
# define DOT 68
# define STREF 69
# define CALL 70
# define FORTCALL 73
# define NOT 76
# define COMPL 77
# define INCR 78
# define DECR 79
# define EQ 80
# define NE 81
# define LE 82
# define LT 83
# define GE 84
# define GT 85
# define ULE 86
# define ULT 87
# define UGE 88
# define UGT 89
# define SETBIT 90
# define TESTBIT 91
# define RESETBIT 92
# define ARS 93
# define REG 94
# define OREG 95
# define CCODES 96
# define FREE 97
# define STASG 98
# define STARG 99
# define STCALL 100

/*	some conversion operators */
# define FLD 103
# define SCONV 104
# define PCONV 105
# define PMCONV 106
# define PVCONV 107

/*	special node operators, used for special contexts */
# define FORCE 108
# define CBRANCH 109
# define INIT 110
# define CAST 111

/*	node types */
# define LTYPE 02
# define UTYPE 04
# define BITYPE 010

	/* DSIZE is the size of the dope array */
# define DSIZE CAST+1

/*	type names, used in symbol table building */
# define TNULL PTR    /* pointer to UNDEF */
# define TVOID FTN	/* function returning UNDEF (for void) */
# define UNDEF 0
# define FARG 1
# define CHAR 2
# define SHORT 3
# define INT 4
# define LONG 5
# define FLOAT 6
# define DOUBLE 7
# define STRTY 8
# define UNIONTY 9
# define ENUMTY 10
# define MOETY 11
# define UCHAR 12
# define USHORT 13
# define UNSIGNED 14
# define ULONG 15

# define ASG 1+
# define UNARY 2+
# define NOASG (-1)+
# define NOUNARY (-2)+

/*	various flags */
# define NOLAB (-1)

/* type modifiers */

# define PTR  020
# define FTN  040
# define ARY  060

/* type packing constants */

# define TMASK 060
# define TMASK1 0300
# define TMASK2  0360
# define BTMASK 017
# define BTSHIFT 4
# define TSHIFT 2

/*	macros	*/

# define MODTYPE(x,y) x = (x&(~BTMASK))|y  /* set basic type of x to y */
# define BTYPE(x)  (x&BTMASK)   /* basic type of x */
# define ISUNSIGNED(x) ((x)<=ULONG&&(x)>=UCHAR)
# define UNSIGNABLE(x) ((x)<=LONG&&(x)>=CHAR)
# define ENUNSIGN(x) ((x)+(UNSIGNED-INT))
# define DEUNSIGN(x) ((x)+(INT-UNSIGNED))
# define ISPTR(x) ((x&TMASK)==PTR)
# define ISFTN(x)  ((x&TMASK)==FTN)  /* is x a function type */
# define ISARY(x)   ((x&TMASK)==ARY)   /* is x an array type */
# define INCREF(x) (((x&~BTMASK)<<TSHIFT)|PTR|(x&BTMASK))
# define DECREF(x) (((x>>TSHIFT)&~BTMASK)|(x&BTMASK))
# define SETOFF(x,y)   if( x%y != 0 ) x = ( (x/y + 1) * y)
		/* advance x to a multiple of y */
# define NOFIT(x,y,z)   ( (x%z + y) > z )
		/* can y bits be added to x without overflowing z */
	/* pack and unpack field descriptors (size and offset) */
# define PKFIELD(s,o) ((o<<6)|s)
# define UPKFSZ(v)  (v&077)
# define UPKFOFF(v) (v>>6)

/*	operator information */

# define TYFLG 016
# define ASGFLG 01
# define LOGFLG 020

# define SIMPFLG 040
# define COMMFLG 0100
# define DIVFLG 0200
# define FLOFLG 0400
# define LTYFLG 01000
# define CALLFLG 02000
# define MULFLG 04000
# define SHFFLG 010000
# define ASGOPFLG 020000

# define SPFLG 040000

#define optype(o) (dope[o]&TYFLG)
#define asgop(o) (dope[o]&ASGFLG)
#define logop(o) (dope[o]&LOGFLG)
#define callop(o) (dope[o]&CALLFLG)

/*	table sizes	*/

# define BCSZ 100 /* size of the table to save break and continue labels */
# define SYMTSZ 450 /* size of the symbol table */
# define DIMTABSZ 800 /* size of the dimension/size table */
# define PARAMSZ 150 /* size of the parameter stack */
# ifndef FORT
# define TREESZ 350 /* space for building parse tree */
# else
# define TREESZ 1000
# endif
# define SWITSZ 250 /* size of switch table */

# define NCHNAM 32  /* number of characters in a name */

/*	common defined variables */

extern int nerrors;  /* number of errors seen so far */

typedef union ndu NODE;
typedef unsigned int TWORD;
# define NIL (NODE *)0
extern int dope[];  /* a vector containing operator information */
extern char *opst[];  /* a vector containing names for ops */

# ifdef ONEPASS
	/* in one-pass operation, define the tree nodes */

union ndu {

	struct {
		int op;
		int rall;
		TWORD type;
		int su;
		char name[NCHNAM];
		NODE *left;
		NODE *right;
		}in; /* interior node */
	
	struct {
		int op;
		int rall;
		TWORD type;
		int su;
		char name[NCHNAM];
		CONSZ lval;
		int rval;
		}tn; /* terminal node */
	
	struct {
		int op, rall;
		TWORD type;
		int su;
		int label;  /* for use with branching */
		}bn; /* branch node */

	struct {
		int op, rall;
		TWORD type;
		int su;
		int stsize;  /* sizes of structure objects */
		int stalign;  /* alignment of structure objects */
		}stn; /* structure node */

	struct {
		int op;
		int cdim;
		TWORD type;
		int csiz;
		}fn; /* front node */
	
	struct {
		/* this structure is used when a floating point constant
		   is being computed */
		int op;
		int cdim;
		TWORD type;
		int csiz;
		double dval;
		}fpn; /* floating point node */

	};
# endif
# ifdef BUG2
# define BUG1
# endif
# ifdef BUG3
# define BUG2
# define BUG1
# endif
# ifdef BUG4
# define BUG1
# define BUG2
# define BUG3
# endif
# ifndef ONEPASS

# ifndef EXPR
# define EXPR '.'
# endif
# ifndef BBEG
# define BBEG '['
# endif
# ifndef BEND
# define BEND ']'
# endif

# endif
nt node */
	
	struct {
		/* this structure is used when a floating point constant
		   is being computed */
		int op;
		int cdim;
		TWORD type;
		int csiz;
		double dval;
		}fpn; /* floating c86/macdefs                                                                                            666      26      12         2325  2650465726   6027                                                                                                                                                                                                                                                                                                                                                                      # define makecc(val,i)  lastcon = i ? (val<<8)|lastcon : val  

# define  ARGINIT 32 
# define  AUTOINIT 32
# define  SZCHAR 8
# define  SZINT 16
# define  SZFLOAT 32
# define  SZDOUBLE 64
# define  SZLONG 32
# define  SZSHORT 16
# define SZPOINT 16
# define ALCHAR 8
# define ALINT 16
# define ALFLOAT 16
# define ALDOUBLE 16
# define ALLONG 16
# define ALSHORT 16
# define ALPOINT 16
# define ALSTRUCT 16
# define  ALSTACK 16 

/*	size in which constants are converted */
/*	should be long if feasable */

# define CONSZ long
# define CONFMT "%ld"

/*	size in which offsets are kept
/*	should be large enough to cover address space in bits
*/

# define OFFSZ long

/* 	character set macro */

# define  CCTRANS(x) x

/* register cookie for stack poINTer */

# define  STKREG 6
# define ARGREG 6

/*	maximum and minimum register variables */

# define MAXRVAR 4
# define MINRVAR 3

	/* various standard pieces of code are used */
# define STDPRTREE
# define LABFMT "L%d"

/* definition indicates automatics and/or temporaries
   are on a negative growing stack */

# define BACKAUTO
# define BACKTEMP

# define RTOLBYTES
# ifndef FORT
# define ONEPASS
# endif

# ifndef FORT
# define EXIT dexit
# endif

# define ENUMSIZE(high,low) INT
ister cookie for stack poINTer */

# define  STKREG 6
# define ARGREG 6

/*	maximum and minimum register variables */

# define MAXRVAR 4
# define MINRVAR 3

	/* various standard pieces of code are used */
# define STDPRTREE
# define LABFMT "L%d"

/* definition indicates automatics and/or temporaric86/mac2defs                                                                                           444      26      12         1654  2744123466   6103                                                                                                                                                                                                                                                                                                                                                                      /*	PDP11 Registers */

	/* scratch registers */
# define AX 0
# define DX 1
# define BX 2

	/* register variables */
# define SI 3
# define DI 4

	/* special purpose */
# define CX 5
# define BP 6
# define SP 7

# define SAVEREGION 6 /* number of bytes for save area */

# define BYTEOFF(x) ((x)&01)
# define wdal(k) (BYTEOFF(k)==0)
# define BITOOR(x) ((x)>>3)  /* bit offset to oreg offset */

# define REGSZ 8

# define TMPREG BP


# define STOARG(p)     /* just evaluate the arguments, and be done with it... */
# define STOFARG(p)
# define STOSTARG(p)
# define genfcall(a,b) gencall(a,b)


	/* shape for constants between -128 and 127 */
# define SCCON (SPECIAL+100)
	/* shape for constants between 0 and 32767 */
# define SICON (SPECIAL+101)
	/* shape for constants with no name component */
# define SXCON (SPECIAL+102)

# define MYREADER(p) myreader(p)
extern int fltused;
	/* calls can be nested on the PDP-11 */
# define NESTCALLS
 BP


# define STOARG(p)     /* just evaluate the arguments, and be done with it... c86/mfile1                                                                                             666      26      12        10316  3227134465   5613                                                                                                                                                                                                                                                                                                                                                                      # include "macdefs"
# include "manifest"

/*	storage classes  */
# define SNULL 0
# define AUTO 1
# define EXTERN 2
# define STATIC 3
# define REGISTER 4
# define EXTDEF 5
# define LABEL 6
# define ULABEL 7
# define MOS 8
# define PARAM 9
# define STNAME 10
# define MOU 11
# define UNAME 12
# define TYPEDEF 13
# define FORTRAN 14
# define ENAME 15
# define MOE 16
# define UFORTRAN 17
# define USTATIC 18
	/* field size is ORed in */
# define FIELD 0100
# define FLDSIZ 077
# ifndef BUG1
extern char *scnames();
# endif

/*	location counters */
# define PROG 0
# define DATA 1
# define ADATA 2
# define STRNG 3
# define ISTRNG 4
# define STAB 5


/* symbol table flags */
# define SMOS 01
# define SHIDDEN 02
# define SHIDES 04
# define SSET 010
# define SREF 020
# define SNONUNIQ 040
# define STAG 0100

# ifndef FIXDEF
# define FIXDEF(p)
#endif
# ifndef FIXARG
# define FIXARG(p)
# endif
# ifndef FIXSTRUCT
# define FIXSTRUCT(a,b)
# endif

	/* alignment of initialized quantities */
# ifndef AL_INIT
#	define	AL_INIT ALINT
# endif

struct symtab {
	char sname[NCHNAM];
	TWORD stype;  /* type word */

	char sclass;  /* storage class */
	char slevel;  /* scope level */
	char sflags;  /* flags for set, use, hidden, mos, etc. */
	int offset;  /* offset or value */
	short dimoff; /* offset into the dimension table */
	short sizoff; /* offset into the size table */
	short suse;  /* line number of last use of the variable */
	};


# ifdef ONEPASS
/* NOPREF must be defined for use in first pass tree machine */
# define NOPREF 020000  /* no preference for register assignment */
#else

union ndu {
	struct {
		int op;
		TWORD type;
		int cdim, csiz;
		}fn; /* front node */
	struct {
		int op;
		TWORD type;
		int cdim, csiz;
		NODE *left;
		NODE * right;
		}in; /* interior node */
	
	struct {
		/* this structure is the same as above,
		   but is used when a value, rather than
		   address, is kept in +left */
		int op;
		TWORD type;
		int cdim, csiz;
		CONSZ lval;
		int rval;
		}tn; /* terminal node */
	
	struct {
		/* this structure is used when a floating point constant
		   is being computed */
		int op;
		TWORD type;
		int cdim, csiz;
		double dval;
		}fpn; /* floating point node */

	};
# endif

struct sw {
	CONSZ sval;
	int slab;
	};

extern struct sw swtab[];
extern struct sw *swp;
extern int swx;

extern int ftnno;
extern int blevel;
extern int instruct, stwart;

extern int lineno, nerrors;
typedef union {
	int intval;
	NODE * nodep;
	} YYSTYPE;
extern YYSTYPE yylval;

extern CONSZ lastcon;
extern double dcon;

extern char ftitle[];
extern struct symtab stab[];
extern int curftn;
extern int curclass;
extern int curdim;
extern int dimtab[];
extern int paramstk[];
extern int paramno;
extern int autooff, argoff, strucoff;
extern int regvar;
extern int minrvar;
extern int brkflag;
extern char yytext[];

extern int strflg;

extern OFFSZ inoff;

extern int reached;

/*	tunnel to buildtree for name id's */

extern int idname;

extern NODE node[];
extern NODE *lastfree;

extern int cflag, hflag, pflag;

/* various labels */
extern int brklab;
extern int contlab;
extern int flostat;
extern int retlab;
extern int retstat;
extern int asavbc[], *psavbc;

/*	flags used in structures/unions */

# define SEENAME 01
# define INSTRUCT 02
# define INUNION 04
# define FUNNYNAME 010
# define TAGNAME 020

/*	flags used in the (elementary) flow analysis ... */

# define FBRK 02
# define FCONT 04
# define FDEF 010
# define FLOOP 020

/*	flags used for return status */

# define RETVAL 1
# define NRETVAL 2

/*	used to mark a constant with no name field */

# define NONAME 040000

	/* mark an offset which is undefined */

# define NOOFFSET (-10201)

/*	declarations of various functions */

extern NODE
	*buildtree(),
	*bdty(),
	*mkty(),
	*rstruct(),
	*dclstruct(),
	*getstr(),
	*tymerge(),
	*stref(),
	*offcon(),
	*bcon(),
	*bpsize(),
	*convert(),
	*pconvert(),
	*oconvert(),
	*ptmatch(),
	*tymatch(),
	*makety(),
	*block(),
	*doszof(),
	*talloc(),
	*optim(),
	*strargs(),
	*clocal();

OFFSZ	tsize(),
	psize();

TWORD	types();


double atof();

char *exname(), *exdcon();

# define checkst(x)

# ifndef CHARCAST
/* to make character constants into character connstants */
/* this is a macro to defend against cross-compilers, etc. */
# define CHARCAST(x) (char)(x)
# endif

),
	*getstr(),
	*tymerge(),
	*stref(),
	*offcon(),
	*bcon(),
	*bpsize(),
	*convert(),
	*pconvert(),
	*oconvert(),
	*ptmatch(),
	*tymatch(),
	*makety(),
	*block(),
	*doszof(),
	*talloc(),
	*optim(),
	*strargs(),
	*clocal();

OFFSZ	tsize(),
	psize();

TWORD	types();


double atof();

char *exname(), *exdconc86/mfile2                                                                                             666      26      12        12413  2537050420   5603                                                                                                                                                                                                                                                                                                                                                                      # include "macdefs"
# include "mac2defs"
# include "manifest"

# ifdef ONEPASS

/*	bunch of stuff for putting the passes together... */
# define crslab crs2lab
# define where where2
# define xdebug x2debug
# define tdebug t2debug
# define deflab def2lab
# define edebug e2debug
# define eprint e2print
# define getlab get2lab
# define filename ftitle
# endif

/*	cookies, used as arguments to codgen */

# define FOREFF 01 /* compute for effects only */
# define INAREG 02 /* compute into a register */
# define INTAREG 04 /* compute into a scratch register */
# define INBREG 010 /* compute into a lvalue register */
# define INTBREG 020 /* compute into a scratch lvalue register */
# define FORCC 040 /* compute for condition codes only */
# define INTEMP 010000 /* compute into a temporary location */
# define FORARG 020000 /* compute for an argument of a function */
# define FORREW 040000 /* search the table, looking for a rewrite rule */

	/* OP descriptors */
	/* the ASG operator may be used on some of these */

# define OPSIMP 010000    /* +, -, &, |, ^ */
# define OPCOMM 010002  /* +, &, |, ^ */
# define OPMUL 010004  /* *, / */
# define OPDIV 010006 /* /, % */
# define OPUNARY 010010  /* unary ops */
# define OPLEAF 010012  /* leaves */
# define OPANY 010014  /* any op... */
# define OPLOG 010016 /* logical ops */
# define OPFLOAT 010020 /* +, -, *, or / (for floats) */
# define OPSHFT 010022  /* <<, >> */
# define OPLTYPE 010024  /* leaf type nodes (e.g, NAME, ICON, etc. ) */

	/* match returns */

# define MNOPE 010000
# define MDONE 010001

	/* shapes */

# define SANY 01	/* same as FOREFF */
# define SAREG 02	/* same as INAREG */
# define STAREG 04	/* same as INTAREG */
# define SBREG 010	/* same as INBREG */
# define STBREG 020	/* same as INTBREG */
# define SCC 040	/* same as FORCC */
# define SNAME 0100
# define SCON 0200
# define SFLD 0400
# define SOREG 01000
# define STARNM 02000
# define STARREG 04000
# define SWADD 040000
# define SPECIAL 0100000
# define SZERO SPECIAL
# define SONE (SPECIAL|1)
# define SMONE (SPECIAL|2)

	/* FORARG and INTEMP are carefully not conflicting with shapes */

	/* types */

# define TCHAR 01
# define TSHORT 02
# define TINT 04
# define TLONG 010
# define TFLOAT 020
# define TDOUBLE 040
# define TPOINT 0100
# define TUCHAR 0200
# define TUSHORT 0400
# define TUNSIGNED 01000
# define TULONG 02000
# define TPTRTO 04000  /* pointer to one of the above */
# define TANY 010000  /* matches anything within reason */
# define TSTRUCT 020000   /* structure or union */

	/* reclamation cookies */

# define RNULL 0    /* clobber result */
# define RLEFT 01
# define RRIGHT 02
# define RESC1 04
# define RESC2 010
# define RESC3 020
# define RESCC 04000
# define RNOP 010000   /* DANGER: can cause loops.. */

	/* needs */

# define NAREG 01
# define NACOUNT 03
# define NAMASK 017
# define NASL 04  /* share left register */
# define NASR 010 /* share right register */
# define NBREG 020
# define NBCOUNT 060
# define NBMASK 0360
# define NBSL 0100
# define NBSR 0200
# define NTEMP 0400
# define NTMASK 07400
# define REWRITE 010000


# define MUSTDO 010000   /* force register requirements */
# define NOPREF 020000  /* no preference for register assignment */


	/* register allocation */

extern int rstatus[];
extern int busy[];

extern struct respref { int cform; int mform; } respref[];

# define isbreg(r) (rstatus[r]&SBREG)
# define istreg(r) (rstatus[r]&(STBREG|STAREG))
# define istnode(p) (p->in.op==REG && istreg(p->tn.rval))

# define TBUSY 01000
# define REGLOOP(i) for(i=0;i<REGSZ;++i)

# define SETSTO(x,y) (stotree=(x),stocook=(y))
extern int stocook;
# define DELAYS 20
extern NODE *deltrees[DELAYS];
extern int deli;   /* mmmmm */

extern NODE *stotree;
extern int callflag;

extern int fregs;

# ifndef ONEPASS
union ndu {

	struct {
		int op;
		int rall;
		TWORD type;
		int su;
		char name[NCHNAM];
		NODE *left;
		NODE *right;
		}in; /* interior node */
	
	struct {
		int op;
		int rall;
		TWORD type;
		int su;
		char name[NCHNAM];
		CONSZ lval;
		int rval;
		}tn; /* terminal node */
	
	struct {
		int op, rall;
		TWORD type;
		int su;
		int label;  /* for use with branching */
		}bn; /* branch node */

	struct {
		int op, rall;
		TWORD type;
		int su;
		int stsize;  /* sizes of structure objects */
		int stalign;  /* alignment of structure objects */
		}stn; /* structure node */

	};
#endif

extern NODE node[];

extern struct optab {
	int op;
	int visit;
	int lshape;
	int ltype;
	int rshape;
	int rtype;
	int needs;
	int rewrite;
	char * cstring;
	}
	table[];

extern NODE resc[];

extern OFFSZ tmpoff;
extern OFFSZ maxoff;
extern OFFSZ baseoff;
extern OFFSZ maxtemp;
extern int maxtreg;
extern int ftnno;
extern int rtyflg;

extern int nrecur;  /* flag to keep track of recursions */

# define NRECUR (10*TREESZ)

extern NODE
	*talloc(),
	*eread(),
	*tcopy(),
	*getlr();

extern CONSZ rdin();

extern int eprint();

extern char *rnames[];

extern int lineno;
extern char filename[];
extern int fldshf, fldsz;
extern int lflag, xdebug, udebug, edebug, odebug, rdebug, radebug, tdebug, sdebug;

#ifndef callchk
#define callchk(x) allchk()
#endif

#ifndef PUTCHAR
# define PUTCHAR(x) putchar(x)
#endif

	/* macros for doing double indexing */
# define R2PACK(x,y) (0200*((x)+1)+y)
# define R2UPK1(x) ((((x)>>7)&0177)-1)
# define R2UPK2(x) ((x)&0177)
# define R2TEST(x) ((x)>=0200)
r();

extern CONSZ rdin();

extern int eprint();

extern char *rnames[];

extern int lineno;
extern char filename[];
extern int fldshf, fldsz;
extern int lflag, xdebug, udebug, edebug, odebug, rdebug, radebug, tdebug, sdebug;

#ifndef callchk
#da86/Makefile                                                                                           444      26      12          470  3227650450   6100                                                                                                                                                                                                                                                                                                                                                                      FILES = mical.h inst.h scan.c error.c init.c ins.c \
	ps.c rel.c sdi.c sym.c

OBJECTS = error.o init.o ins.o ps.o rel.o sdi.o sym.o scan.o

CFLAGS = -O

a86: $(OBJECTS)
	cc -o a86 $(OBJECTS)

$(OBJECTS): mical.h

init.o ins.o: mical.h inst.h

cvt86: cvt86.o
	cc -o cvt86 cvt86.o

ld86:	ld86.o
	cc -o ld86 ld86.o
();

extern char *rnames[];

extern int lineno;
extern char filename[];
extern int fldshf, fldsz;
extern int lflag, xdebug, udebug, edebug, odebug, rdebug, radebug/usr/src/local/Machines/8086/a86     a86/crap.c                                                                                             664      30      12          111  3355604315   5521                                                                                                                                                                                                                                                                                                                                                                      int verylongname()
 { return 5;
 }

main()
 {	return verylongname(5);
 }
m.c

OBJECTS = error.o init.o ins.o ps.o rel.o sdi.o sym.o scan.o

CFLAGS = -O

a86: $(OBJECTS)
	cc -o a86 $(OBJECTS)

$(OBJECTS): mical.h

init.o ins.o: mical.h inst.h

cvt86: cvt86.o
	cc -o cvt86 cvt86.o

ld86:	ld86.o
	cc -o ld86 ld86.o
();

extern char *rnames[];

extern int lineno;
extern char filename[];
extern int fldshf, fldsz;
extern int lflag, xdebug, udebug, edebug, odebug, rdebug, radebug/usr/src/local/Machines/8086/a86     a86/cvt86.c                                                                                            666     140      42        14464  3323103337   5646                                                                                                                                                                                                                                                                                                                                                                      #include <stdio.h>
#include <a.out.h>

/* convert a.out files into .com files for IBM Dos system */

/* Modified by LDS to provide -D option to specify relocation of data segment.
   The -O option specifies relocation of text segment (both use decimal).
   Default for text segment offset is 0x100; default for data segment is 0.
   These are the correct values for relocating an MSDOS .com file, assuming
   that the data segment register is set to the end of the code segment.
   If a negative value is specified for the data relocation, then relocation
   is done assuming that the data segment register will be equal to the
   code segment register, ie, the data will be relocated by the length
   of the code plus the relocation for the code.
*/

struct exec hdr;	/* header info from a.out file */
char zero[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

struct nlist *symtab;	/* pointer to symbol table */
FILE *infile,*outfile;

long	Offset =     0x100;	/* base of text segment */
long	DataOffset = 0x000;	/* base of data segment */
long atol();

char	LFlag;			/* -l for loud output	*/

main(argc,argv)
  char **argv;
  {	register int i;
	register char *text,*strings;
	register struct nlist *s;
	int size;
	long string_size;

	while (*(text = argv[1]) == '-')
	 {
	   argv++; argc--; switch(*++text)
		{
		  case 'O':	Offset = atol(++text); continue;
		  case 'D':	DataOffset = atol(++text); continue;
		  case 'l':	LFlag++; continue;
		  default: fprintf(stderr, "Bad option %s\r\n", argv[0]);
			   exit(-1);
		}
	 }

	if (argc != 3) {
	  fprintf(stderr,"usage: cvt86 <a.out file name> <.com file name>\n");
	  exit(1);
	}

	if ((infile = fopen(argv[1],"r")) == NULL) {
	  fprintf(stderr,"cvt86: cannot open %s for input\n",argv[1]);
	  exit(1);
	}

	if ((outfile = fopen(argv[2],"w")) == NULL) {
	  fprintf(stderr,"cvt86: cannot open %s for output\n",argv[2]);
	  exit(1);
	}

	if (fread(&hdr,sizeof(hdr),1,infile) != 1) {
	  fprintf(stderr,"cvt86: read of a.out header failed\n");
	  exit(1);
	}

	if (hdr.a_magic != OMAGIC) {
	  fprintf(stderr,"cvt86: a.out file not in 0407 format\n");
	  exit(1);
	}

	if ((text = (char *)malloc(hdr.a_text + hdr.a_data)) == NULL ||
	    fread(text,1,hdr.a_text+hdr.a_data,infile) != hdr.a_text + hdr.a_data) {
	  fprintf(stderr,"cvt86: setup failed for text and data\n");
	  exit(1);
	}

	if (DataOffset < 0)	/* Implies data segment equals code segment */
	    DataOffset = (hdr.a_text + 15 + Offset) & ~15;

	fseek(infile,N_SYMOFF(hdr),0);
	if ((symtab = (struct nlist *)malloc(hdr.a_syms)) == NULL ||
	    fread(symtab,1,hdr.a_syms,infile) != hdr.a_syms) {
	  fprintf(stderr,"cvt86: setup failed for symbols\n");
	  exit(1);
	}

	fread(&string_size,sizeof(string_size),1,infile);
	if ((strings = (char *)malloc(string_size-4)) == NULL ||
	    fread(strings,1,string_size-4,infile) != string_size-4) {
	  fprintf(stderr,"cvt86: setup failed for string data\n");
	  exit(1);
	}

	/* set up symbol string pointers, and define .comm symbols */
	for (i = hdr.a_syms/sizeof(struct nlist), s = symtab; i--; s++) {
	  if (s->n_un.n_strx != 0) s->n_un.n_name = &strings[s->n_un.n_strx-4];
	  if (s->n_type==(N_UNDF|N_EXT) && (size = s->n_value)!=0) {
	    s->n_value = hdr.a_data + hdr.a_bss;
	    s->n_type = N_BSS;
	    hdr.a_bss += size;
	  }
	}

	if (LFlag)
	 {
	   printf("Initialized data:  %ld bytes\n", hdr.a_data);
	   printf("Uninitialized BSS: %ld bytes\n", hdr.a_bss);
	   printf("Total data:        %ld bytes\n", (long)
						hdr.a_data + hdr.a_bss);
	 }


	/* define _etext, _edata, and _end if user uses them */
	for (i = hdr.a_syms/sizeof(struct nlist), s = symtab; i--; s++)
	  if (s->n_type == (N_UNDF|N_EXT)) {
	    if (strcmp(s->n_un.n_name,"_etext") == 0) {
	      s->n_value = (hdr.a_text + 15 + Offset) & ~15;
	      s->n_type = N_TEXT;
	    } else if (strcmp(s->n_un.n_name,"_edata") == 0) {
	      s->n_value = hdr.a_data + DataOffset;
	      s->n_type = N_DATA;
	    } else if (strcmp(s->n_un.n_name,"_end") == 0) {
	      s->n_value = hdr.a_data + hdr.a_bss + DataOffset;
	      s->n_type = N_BSS;
	    }
	  }

	fseek(infile,N_TXTOFF(hdr)+hdr.a_text+hdr.a_data,0);

	/* do text relocation */
	relocate(hdr.a_trsize/sizeof(struct relocation_info), text);

	/* do data relocation */
	relocate(hdr.a_drsize/sizeof(struct relocation_info), &text[hdr.a_text]);

	fwrite(text,1,hdr.a_text,outfile);
	if (hdr.a_text & 15)
	  fwrite(zero,1,16 - (hdr.a_text & 15),outfile);
	fwrite(&text[hdr.a_text],1,hdr.a_data,outfile);
	fclose(outfile);
}

/* process relocation commands */
relocate(ncmds,base)
  register int ncmds;
  register char *base;
  {	register struct nlist *s;
	struct relocation_info r;

	while (ncmds--) {
	  fread(&r,sizeof(r),1,infile);

/*	  fprintf(stderr,"addr = 0x%x, sym = %s (0x%x), pcrel = %d, length = %d, extern = %d\n",
		  r.r_address,symtab[r.r_symbolnum].n_un.n_name,r.r_symbolnum,
		  r.r_pcrel,r.r_length,r.r_extern);
*/
	  if (r.r_extern == 0) {
	    if (r.r_pcrel != 1) switch (r.r_symbolnum) {
	      case N_TEXT: put_word(&base[r.r_address],r.r_length,
			     get_word(&base[r.r_address],r.r_length) + Offset);
			   break;

	      case N_BSS:
	      case N_DATA: put_word(&base[r.r_address],r.r_length,
			     get_word(&base[r.r_address],r.r_length) 
					- hdr.a_text + DataOffset);
			   break;

	      default:	   fprintf(stderr,"cvt86: strange csect %d\n",r.r_symbolnum);
			   break;
	    }
	  } else {
	    s = &symtab[r.r_symbolnum];

/*	    fprintf(stderr,"  relocation by symbol, value = 0x%0x\n",s->n_value);
*/
	    switch (s->n_type & N_TYPE) {
	      default:	fprintf(stderr,"cvt86: relocation by undefined symbol %s ignored\n",
				s->n_un.n_name);
			break;

	      case N_ABS:
	      case N_TEXT:
	      case N_DATA:
	      case N_BSS:
			put_word(&base[r.r_address],r.r_length,
		   	  get_word(&base[r.r_address],r.r_length) + s->n_value);
			break;
	    }
	  }
	}
}

/* not portable! requires byte addressing to work for all sizes of operands */
int get_word(addr,size) 
  register char *addr;
  int size;
  {	switch (size) {
	  case 0:	return (*addr);

	  case 1:	return (*(short *)addr);

	  case 2:	return (*(long *)addr);
	}
}

/* not portable! requires byte addressing to work for all sizes of operands */
put_word(addr,size,value)
  register char *addr;
  int size, value;
  {	switch (size) {
	  case 0:	*addr = value; break;

	  case 1:	*(short *)addr = value; break;

	  case 2:	*(long *)addr = value; break;
	}
}
o work for all sizes of operands */
int get_word(addr,size) 
  register char *addr;
  int size;
  {	switch (size) {
	  case 0:	return (*addr);

	  case 1:	return (*(short *)addr);

	  case 2:	return (*(loa86/error.c                                                                                            444      26      12         6021  2652111423   5744                                                                                                                                                                                                                                                                                                                                                                      #include "mical.h"
extern char File_name[];

/*
 *
 *  Sys_Error(), Prog_Error(), and Describe_Error() for mical assembler 
 *
 */


char *E_messages[] = {
/* 0 */		"<unused>",
/* 1 */		"Missing .end statement",
/* 2 */		"Invalid character",
/* 3 */		"Multiply defined symbol",
/* 4 */		"Symbol storage exceeded",
/* 5 */		"Offset too large",
/* 6 */		"Symbol too long",
/* 7 */		"Undefined symbol",
/* 8 */		"Invalid constant",
/* 9 */		"Invalid term",
/* 10 */	"Invalid operator",
/* 11 */	"Non-relocatable expression",
/* 12 */	"Wrong type for instruction",
/* 13 */	"Invalid operand",
/* 14 */	"Invalid symbol",
/* 15 */	"Invalid assignment",
/* 16 */	"Too many labels",
/* 17 */	"Invalid op-code",
/* 18 */	"Invalid entry point",
/* 19 */	"Invalid string",
/* 20 */	"Bad filename or too many levels",
/* 21 */	"Warning--attribute ignored",
/* 22 */	".Error statement",
/* 23 */	"Too many levels: statement ignored",
/* 24 */	"Invalid condition",
/* 25 */	"Wrong number of operands",
/* 26 */	"Line too long",
/* 27 */	"Invalid register expression",
/* 28 */	"Invalid machine address",
/* 29 */	"Unimplemented directive",
/* 30 */	"Cannot open inserted file",
/* 31 */	"Invalid string",
/* 32 */	"Too many macro arguments",
/* 33 */	"Invalid macro argument",
/* 34 */	"Invalid formal argument",
/* 35 */	"Inappropriate .endc statement; ignored",
/* 36 */	"Warning--relative address may be out of range",
/* 37 */	"Warning--invalid argument; ignored",
/* 38 */	"Invalid instruction vector index",
/* 39 */	"Invalid instruction vector",
/* 40 */	"Invalid macro name",
/* 41 */	"Unable to expand time macro",
/* 42 */	"Bad csect",
/* 43 */	"Odd address",
		0
} ;

int Errors = 0;		/* Number of errors in this pass */

/* Sys_Error is called when a System Error occurs, that is, something is wrong
   with the assembler itself. Each routine of the assembler usually checks the
   arguments passed to it for validity, and calls this routine if its
   parameters are invalid. Explanation is a string suitable for a printf
   control string which explains the error, and Number is the value of the
   offending parameter.  This routine will not return.
*/
Sys_Error(Explanation,Number)
char *Explanation;
{
	fprintf(stderr, "Assembler Error-- ");
	fprintf(stderr, Explanation,Number);
	abort();
}

/* This is called whenever the assembler recognizes an error in the current
statement. It registers the error, so that an error code will be listed with
the statement, and a description of the error will be printed at the end of
the listing */

Prog_Error(code)
register int code;
{	register int i;

	if (Pass != 2) return;		/* no errors on pass 1 */
	Errors++;				/* increment error count */
	fprintf(stderr,"\"%s\", line %d: %s\n",File_name,Line_no,E_messages[code]);
}

/* Prog_Warning registers a warning on a statement. A warning is like an error,
	in that something is probably amiss, but the assembler will still try 
	to generate the .rel file. 
*/

Prog_Warning(code){
	if (Pass != 2) return;
	fprintf(stderr,"\"%s\", line %d: (warning) %s\n",
		File_name,Line_no,E_messages[code]);
}
	register int i;

	if (Pass != 2) return;		/* no errors on pass 1 */
	Errors++;				/* increment error count */
	fprintf(stderr,"\"%s\", line %d: %s\n",File_name,Line_no,E_messages[code]);
}

/* Prog_Warning registers a warning on a statement. A warning is like an error,
	in that something is probably amiss, but the assembler will still try 
	to generate the .rel file. 
*/

Prog_Warning(code){
	if (Pass != 2) return;
	fprintf(stderr,"\"%s\", line %d: (warning) %s\n",
		File_name,Line_no,E_mea86/init.c                                                                                             644      26      12        20601  2655671675   5627                                                                                                                                                                                                                                                                                                                                                                      #include "mical.h"
#include "inst.h"

char Title[STR_MAX];
char O_outfile = 0;		/* 1 if .rel file name is specified by uder */
int Pass = 0;			/* which pass we're on */
char Rel_name[STR_MAX];		/* Name of .rel file */
FILE *Rel_file;			/* and ptr to it */
struct sym_bkt *Dot_bkt ;	/* Ptr to location counter's symbol bucket */
long tsize = 0;			/* sizes of three main csects */
long dsize = 0;
long bsize = 0;
struct ins_bkt *ins_hash_tab[HASH_MAX];

/* List of 8086 op codes */
struct ins_init { char *opstr; short opnum; } op_codes[] = {
	"aaa",	i_aaa,	"aad",	i_aad,	"aam",	i_aam,
	"aas",	i_aas,	"adc",	i_adc,	"add",	i_add,
	"and",	i_and,
	"call",	i_call,	"calli",i_calli,
	"cbw",	i_cbw,	"clc",	i_clc,
	"cld",	i_cld,	"cli",	i_cli,	"cmc",	i_cmc,
	"cmp",	i_cmp,	"cmpb",	i_cmpb,	"cmpw",	i_cmpw,
	"cwd",	i_cwd,
	"daa",	i_daa,	"das",	i_das,	"dec",	i_dec,
	"div",	i_div,
	"esc",	i_esc,
	"idiv",	i_idiv,	"imul",	i_imul,	"in",	i_in,
	"inc",	i_inc,	"int",	i_int,	"into",	i_into,
	"inw",	i_inw,	"iret",	i_iret,
	"hlt",	i_hlt,
	"j",	i_j,
	"je",	i_je,	"jz",	i_je,
	"jl",	i_jl,	"jnge",	i_jl,
	"jle",	i_jle,	"jng",	i_jle,
	"jb",	i_jb,	"jnae",	i_jb,
	"jbe",	i_jbe,	"jna",	i_jbe,
	"jp",	i_jp,	"jpe",	i_jp,
	"jo",	i_jo,
	"js",	i_js,
	"jne",	i_jne,	"jnz",	i_jne,
	"jnl",	i_jnl,	"jge",	i_jnl,
	"jnle",	i_jnle,	"jg",	i_jnle,
	"jnb",	i_jnb,	"jae",	i_jnb,
	"jnbe",	i_jnbe,	"ja",	i_jnbe,
	"jnp",	i_jnp,	"jpo",	i_jnp,
	"jno",	i_jno,
	"jns",	i_jns,
	"jcxz",	i_jcxz,	"jmp",	i_jmp,	"jmpi",	i_jmpi,
	"lahf",	i_lahf,	"lds",	i_lds,	"lea",	i_lea,
	"les",	i_les,	"lock",	i_lock,	"lodb",	i_lodb,
	"lodw",	i_lodw,
	"loop",	i_loop,
	"loope",i_loope,"loopz",i_loope,
	"loopne",i_loopne,"loopnz",i_loopne,
	"mov",	i_mov,	"movb",	i_movb,	"movw",	i_movw,
	"mul",	i_mul,
	"neg",	i_neg,	"not",	i_not,
	"or",	i_or,	"out",	i_out,	"outw",	i_outw,
	"pop",	i_pop,	"popf",	i_popf,	"push",	i_push,
	"pushf",i_pushf,
	"rcl",	i_rcl,	"rcr",	i_rcr,
	"repnz",i_repnz,"repz",	i_repz,
	"ret",	i_ret,	"reti",	i_reti,
	"rol",	i_rol,	"ror",	i_ror,
	"sahf",	i_sahf,	"sal",	i_sal,	"sar",	i_sar,
	"scab",	i_scab,	"scaw",	i_scaw,	"shl",	i_sal,
	"shr",	i_shr,	"stc",	i_stc,	"seg",	i_seg,
	"std",	i_std,	"sti",	i_sti,	"stob",	i_stob,
	"stow",	i_stow,	"sub",	i_sub,	"sbb",	i_sbb,
	"test",	i_test,
	"wait",	i_wait,
	"xchg",	i_xchg,	"xlat",	i_xlat,	"xor",	i_xor,
	"beq",	i_beq,	"bne",	i_bne,	"ble",	i_ble,
	"bgt",	i_bgt,	"blt",	i_blt,	"bge",	i_bge,
	"blos",	i_blos,	"bhi",	i_bhi,	"blo",	i_blo,
	"bhis",	i_bhis,	"br",	i_br,
	"addb",	i_addb,	"adcb",	i_adcb,	"incb",	i_incb,
	"subb",	i_subb,	"sbbb",	i_sbbb, "decb",	i_decb,
	"negb", i_negb, "mulb", i_mulb, "imulb",i_imulb,
	"divb", i_divb, "idivb",i_idivb,"notb", i_notb,
	"salb", i_salb, "shlb", i_salb, "shrb", i_shrb,
	"sarb", i_sarb, "rolb", i_rolb, "rorb", i_rorb,
	"rclb", i_rclb, "rcrb", i_rcrb, "andb", i_andb,
	"testb",i_testb,"orb",  i_orb,  "xorb", i_xorb,

	"fabs", i_fabs,
	"faddf", i_faddf,
	"faddl", i_faddl,
	"faddd", i_faddd,
	"faddi", i_faddi,
	"fadd", i_fadd,
	"faddp", i_faddp,
	"fchs", i_fchs,
	"fclex", i_fclex,
	"fcomf", i_fcomf,
	"fcoml", i_fcoml,
	"fcomd", i_fcomd,
	"fcomi", i_fcomi,
	"fcom", i_fcom,
	"fcompf", i_fcompf,
	"fcompl", i_fcompl,
	"fcompd", i_fcompd,
	"fcompi", i_fcompi,
	"fcomp", i_fcomp,
	"fcompp", i_fcompp,
	"fdecstp", i_fdecstp,
	"fdisi", i_fdisi,
	"fdivf", i_fdivf,
	"fdivl", i_fdivl,
	"fdivd", i_fdivd,
	"fdivi", i_fdivi,
	"fdiv", i_fdiv,
	"fdivp", i_fdivp,
	"fdivr", i_fdivr,
	"fdivrp", i_fdivrp,
	"feni", i_feni,
	"ffree", i_ffree,
	"fincstp", i_fincstp,
	"finit", i_finit,
	"fldcw", i_fldcw,
	"fldenv", i_fldenv,
	"fldf", i_fldf,
	"fldl", i_fldl,
	"fldd", i_fldd,
	"fldi", i_fldi,
	"fld", i_fld,
	"fldlg2", i_fldlg2,
	"fldln2", i_fldln2,
	"fldl2e", i_fldl2e,
	"fldl2t", i_fldl2t,
	"fldpi", i_fldpi,
	"fldz", i_fldz,
	"fld1", i_fld1,
	"fnop", i_fnop,
	"fmulf", i_fmulf,
	"fmull", i_fmull,
	"fmuld", i_fmuld,
	"fmuli", i_fmuli,
	"fmul", i_fmul,
	"fmulp", i_fmulp,
	"fpatan", i_fpatan,
	"fprem", i_fprem,
	"fptan", i_fptan,
	"frstro", i_frstor,
	"frndint", i_frndint,
	"fsave", i_fsave,
	"fscale", i_fscale,
	"fsqrt", i_fsqrt,
	"fstf", i_fstf,
	"fstl", i_fstl,
	"fstd", i_fstd,
	"fsti", i_fsti,
	"fst", i_fst,
	"fstpf", i_fstpf,
	"fstpl", i_fstpl,
	"fstpd", i_fstpd,
	"fstpi", i_fstpi,
	"fstp", i_fstp,
	"fstcw", i_fstcw,
	"fstevn", i_fstenv,
	"fstsw", i_fstsw,
	"fsubf", i_fsubf,
	"fsubl", i_fsubl,
	"fsubd", i_fsubd,
	"fsubi", i_fsubi,
	"fsub", i_fsub,
	"fsubp", i_fsubp,
	"fsubr", i_fsubr,
	"fsubrp", i_fsubrp,
	"ftst", i_ftst,
	"fwait", i_fwait,
	"fxam", i_fxam,
	"fxch", i_fxch,
	"fxtract", i_fxtract,
	"fyl2x", i_fyl2x,
	"fylwxp1", i_fyl2xp1,
	"f2xm1", i_f2xm1,
	"fdivrf", i_fdivrf,
	"fdivrl", i_fdivrl,
	"fdivrd", i_fdivrd,
	"fdivri", i_fdivri,
	"fsubrf", i_fsubrf,
	"fsubrl", i_fsubrl,
	"fsubrd", i_fsubrd,
	"fsubri", i_fsubri,

	".long", i_long,
	".word", i_word,
	".byte", i_byte,
	".text", i_text,
	".data", i_data,
	".bss", i_bss,
	".globl", i_globl,
	".comm", i_comm,
	".even", i_even,
	".asciz", i_asciz,
	".ascii", i_ascii,
	".zerow", i_zerow,
	0 };

char *Source_name = NULL;
char File_name[STR_MAX];

Init(argc,argv)
char *argv[];
{	register int i,j;
	char *strncpy();
	char *cp1, *cp2, *end, *rindex();

	argv++;
	while (--argc > 0) {
	  if (argv[0][0] == '-') switch (argv[0][1]) {
	    case 'o':	O_outfile++;
			Concat(Rel_name,argv[1],"");
			argv++; argc--;
			break;

	    default:	fprintf(stderr,"Unknown option '%c' ignored.\n",argv[0][1]);
	  } else if (Source_name != NULL) {
	    fprintf(stderr,"Too many file names given\n");
	  } else {
	    Source_name = argv[0];
	    Concat(File_name, argv[0], ".a86");
	    if (freopen(File_name,"r",stdin) == NULL) {/* open source file */
	      if ((end = rindex(Source_name, '.')) == 0 ||
			strcmp(end, ".a86") != 0) {
	        fprintf(stderr,"Can't open source file: %s\n",File_name);
	        exit(1);
	      }
	      strncpy(File_name, argv[0], STR_MAX);
	      if (freopen(File_name,"r",stdin) == NULL) {/* open source file */
	        fprintf(stderr,"Can't open source file: %s\n",File_name);
	        exit(1);
	      }
	    }
	  }
	  argv++;
	}


/* Check to see if we can open output file */
	if(!O_outfile)
	{
		if ((end = rindex(Source_name, '.')) == 0 ||
			strcmp(end, ".a86") != 0)
			Concat(Rel_name,Source_name,".b");
		else	/* copy basename without .a86 to Rel_name */
		{
			for (cp1 = Source_name, cp2 = Rel_name; cp1 < end;)
				*cp2++ = *cp1++;
			strcpy(cp2, ".b");	/* append ".b" to basename */
		}
	}
	if ((Rel_file = fopen(Rel_name,"w")) == NULL)
	{	printf("Can't create output file: %s\n",Rel_name);
		exit(1);
	}
	fclose(Rel_file);	/* Rel_Header will open properly */

/* Initialize symbols */
	Sym_Init();
	Dot_bkt = Lookup(".");		/* make bucket for location counter */
	Dot_bkt->csect_s = Cur_csect;
	Dot_bkt->attr_s = S_DEC | S_DEF | S_LABEL; 	/* "S_LABEL" so it cant be redefined as a label */
	init_regs();			/* define register names */
	d_ins();			/* set up opcode hash table */
	Perm();
	Start_Pass();
}

d_ins()
{	register struct ins_init *p;
	register struct ins_bkt *insp;
	register int save;

	for (p = op_codes; p->opstr != 0; p++) {
		insp = (struct ins_bkt *)calloc(1,sizeof(struct ins_bkt));
		insp->text_i = p->opstr;
		insp->code_i = p->opnum;
		insp->next_i = ins_hash_tab[save = Hash(insp->text_i)];
		ins_hash_tab[save] = insp;
	}
}

struct def { char *rname; int rnum; } defregs[] = {
  "ax", 0, "cx", 1, "dx", 2, "bx", 3, "sp", 4, "bp", 5, "si", 6, "di",7,
  "al", 8, "cl", 9, "dl", 10, "bl", 11, "ah", 12, "ch", 13, "dh", 14, "bh",15,
  "es", 16, "cs", 17, "ss", 18, "ds", 19,
  "bx_si", 64, "bx_di", 65, "bp_si", 66, "bp_di", 67,
  0, 0
};

init_regs()
  {	register struct sym_bkt *sbp;
	register struct def *p = defregs;
	struct sym_bkt *Lookup();

	while (p->rname) {
	  sbp = Lookup(p->rname);	/* Make a sym_bkt for it */
	  sbp->value_s = p->rnum;	/* Load the sym_bkt */
	  sbp->csect_s = 0;
	  sbp->attr_s = S_DEC | S_DEF | S_REG;
	  p++;
	}
}

Concat(s1,s2,s3)
  register char *s1,*s2,*s3;
  {	while (*s1++ = *s2++);
	s1--;
	while (*s1++ = *s3++);
}


/*
 * Return the ptr in sp at which the character c last
 * appears; NULL if not found
*/

#define NULL 0

char *
rindex(sp, c)
register char *sp, c;
{
	register char *r;

	r = NULL;
	do {
		if (*sp == c)
			r = sp;
	} while (*sp++);
	return(r);
}


/*
 * Copy s2 to s1, truncating or null-padding to always copy n bytes
 * return s1
 */

char *
strncpy(s1, s2, n)
register char *s1, *s2;
{
	register i;
	register char *os1;

	os1 = s1;
	for (i = 0; i < n; i++)
		if ((*s1++ = *s2++) == '\0') {
			while (++i < n)
				*s1++ = '\0';
			return(os1);
		}
	return(os1);
}

 * appears; NULL if not found
*/

#define NULL 0

char *
rindex(sp, c)
register char *sp, c;
{
	register char *r;

	r = NULL;
a86/ins.c                                                                                              444      26      12        77053  3115672570   5453                                                                                                                                                                                                                                                                                                                                                                      #include "mical.h"
#include "inst.h"

#define AR 0	/* must be an areg */
#define DR 1	/* must be a dreg */

char	Code_length;		/* Number of bytes in the current instruction*/
short	*WCode = (short *)Code;
struct oper operands[OPERANDS_MAX];	/* where all the operands go */
int	numops;			/* # of operands to the current instruction */

/* Instruction  -- 8086 assembler
 * This program is called from the main loop. It checks to see if the
 * operator field is a valid instruction mnemonic. If so, it calls the
 * operand evaluator and generates the machine code for the instrucion.
 * On pass 2 it prints the listing line for the current statement 
 */
Instruction(opindex)
{	register int i,j,k;		/* gen purpose index */

	Code_length = 1;		/* always at least 2 bytes of code */
	for(i=0;i < CODE_MAX; i++) { Code[i] = 0; }
					/* Clear buffer for generated code */
	switch (opindex) {		/* dispatch to handle each inst */

	case i_mov:	move(-1); break;

	case i_add:	gen_op(0x00,0x0080,0x04,1,1,-1); break;
	case i_adc:	gen_op(0x10,0x1080,0x14,1,1,-1); break;
	case i_sub:	gen_op(0x28,0x2880,0x2C,1,1,-1); break;
	case i_sbb:	gen_op(0x18,0x1880,0x1C,1,1,-1); break;
	case i_cmp:	gen_op(0x38,0x3880,0x3C,1,1,-1); break;
	case i_and:	gen_op(0x20,0x2080,0x24,1,0,-1); break;
	case i_test:	gen_op(0x84,0x00F6,0xA8,0,0,-1); break;
	case i_or:	gen_op(0x08,0x0880,0x0C,1,0,-1); break;
	case i_xor:	gen_op(0x30,0x3080,0x34,1,0,-1); break;

	case i_addb:	gen_op(0x00,0x0080,0x04,1,1,0); break;
	case i_adcb:	gen_op(0x10,0x1080,0x14,1,1,0); break;
	case i_subb:	gen_op(0x28,0x2880,0x2C,1,1,0); break;
	case i_sbbb:	gen_op(0x18,0x1880,0x1C,1,1,0); break;
	case i_andb:	gen_op(0x20,0x2080,0x24,1,0,0); break;
	case i_testb:	gen_op(0x84,0x00F6,0xA8,0,0,0); break;
	case i_orb:	gen_op(0x08,0x0880,0x0C,1,0,0); break;
	case i_xorb:	gen_op(0x30,0x3080,0x34,1,0,0); break;

	case i_lea:	load(0x8D); break;
	case i_lds:	load(0xC5); break;
	case i_les:	load(0xC4); break;

	case i_j:	disp(0xEB); break;
	case i_je:	disp(0x74); break;
	case i_jl:	disp(0x7C); break;
	case i_jle:	disp(0x7E); break;
	case i_jb:	disp(0x72); break;
	case i_jbe:	disp(0x76); break;
	case i_jp:	disp(0x7A); break;
	case i_jo:	disp(0x70); break;
	case i_js:	disp(0x78); break;
	case i_jne:	disp(0x75); break;
	case i_jnl:	disp(0x7D); break;
	case i_jnle:	disp(0x7F); break;
	case i_jnb:	disp(0x73); break;
	case i_jnbe:	disp(0x77); break;
	case i_jnp:	disp(0x7B); break;
	case i_jno:	disp(0x71); break;
	case i_jns:	disp(0x79); break;
	case i_loop:	disp(0xE2); break;
	case i_loope:	disp(0xE1); break;
	case i_loopne:	disp(0xE0); break;
	case i_jcxz:	disp(0xE3); break;

	case i_beq:	branch(0x74,0x75); break;
	case i_bne:	branch(0x75,0x74); break;
	case i_ble:	branch(0x7E,0x7F); break;
	case i_bgt:	branch(0x7F,0x7E); break;
	case i_blt:	branch(0x7C,0x7D); break;
	case i_bge:	branch(0x7D,0x7C); break;
	case i_blos:	branch(0x76,0x77); break;
	case i_bhi:	branch(0x77,0x76); break;
	case i_blo:	branch(0x72,0x73); break;
	case i_bhis:	branch(0x73,0x72); break;
	case i_br:	branch(0xEB,0); break;

	case i_xlat:	no_ops(0xD7); break;
	case i_lahf:	no_ops(0x9F); break;
	case i_sahf:	no_ops(0x9E); break;
	case i_pushf:	no_ops(0x9C); break;
	case i_popf:	no_ops(0x9D); break;
	case i_aaa:	no_ops(0x37); break;
	case i_daa:	no_ops(0x27); break;
	case i_aas:	no_ops(0x3F); break;
	case i_das:	no_ops(0x2F); break;
	case i_cbw:	no_ops(0x98); break;
	case i_cwd:	no_ops(0x99); break;
	case i_movb:	{ if (numops==0) no_ops(0xA4); else move(0); break; }
	case i_movw:	no_ops(0xA5); break;
	case i_cmpb:	{ if (numops==0) no_ops(0xA6);
			  else gen_op(0x38,0x3880,0x3C,1,1,0); break; }
	case i_cmpw:	no_ops(0xA7); break;
	case i_scab:	no_ops(0xAE); break;
	case i_scaw:	no_ops(0xAF); break;
	case i_lodb:	no_ops(0xAC); break;
	case i_lodw:	no_ops(0xAD); break;
	case i_stob:	no_ops(0xAA); break;
	case i_stow:	no_ops(0xAB); break;
	case i_into:	no_ops(0xCE); break;
	case i_iret:	no_ops(0xCF); break;
	case i_clc:	no_ops(0xF8); break;
	case i_cmc:	no_ops(0xF5); break;
	case i_stc:	no_ops(0xF9); break;
	case i_cld:	no_ops(0xFC); break;
	case i_std:	no_ops(0xFD); break;
	case i_cli:	no_ops(0xFA); break;
	case i_sti:	no_ops(0xFB); break;
	case i_hlt:	no_ops(0xF4); break;
	case i_wait:	no_ops(0x9B); break;
	case i_lock:	no_ops(0xF0); break;
	case i_repnz:	no_ops(0xF2); break;
	case i_repz:	no_ops(0xF3); break;

	case i_aam:
	case i_aad:
		if (numops != 0)		/* no operands here */
		 { Prog_Error(E_NUMOPS); break; };
		Code_length = 2;		/* 2 byte instructions */
		Code[0] = (opindex==i_aam)?0xD6:0xD5;
		Code[1] = 0x0A;
		break;

	case i_incb:
	case i_decb:
		k = 0;				/* accept byte size operand */
		i = (opindex==i_incb)?1:0;	/* remember what op code is */
		goto incdec;

	case i_inc:
	case i_dec:
		k = -1;				/* accept any size operand */
		i = (opindex==i_inc)?1:0;	/* remember what op code is */
	incdec:	if (numops != 1)		/* only one operand allowed */
		 { Prog_Error(E_NUMOPS); break; };
		j = reg(operands);		/* see if operand is a register */
		if (j>=0 && j<8)		/* if word register, special op code */
		 Code[0] = (i?0x40:0x48) | j;
		else one_op(i?0x00FE:0x08FE,k);	/* ordinary single operand instruction */
		break;

	case i_not:	one_op(0x10F6,-1); break;
	case i_neg:	one_op(0x18F6,-1); break;
	case i_mul:	one_op(0x20F6,-1); break;
	case i_imul:	one_op(0x28F6,-1); break;
	case i_div:	one_op(0x30F6,-1); break;
	case i_idiv:	one_op(0x38F6,-1); break;

	case i_notb:	one_op(0x10F6,0); break;
	case i_negb:	one_op(0x18F6,0); break;
	case i_mulb:	one_op(0x20F6,0); break;
	case i_imulb:	one_op(0x28F6,0); break;
	case i_divb:	one_op(0x30F6,0); break;
	case i_idivb:	one_op(0x38F6,0); break;

	case i_push:
	case i_pop:
		if (numops != 1)		/* only one operand allowed */
		 { Prog_Error(E_NUMOPS); break; };
		i = (opindex==i_push)?1:0;	/* remember what op code is */
		j = reg(operands);		/* see if operand is a reg */
		opr_size(1);			/* make sure its a word operand */
		if (j == -1)			/* first handle non-reg operands */
		 { Code[0] = i ? 0xFF:0x8F;
		   Code[1] = i ? 0x30:0x00;
		   addr(operands);		/* fill in mode and r/m fields */
		   break;
		 };
		if (j>=16 && j<=19)		/* segment register */
		 { Code[0] = (i ? 0x06:0x07) | ((j&3)<<3);
		   break;
		 };
		Code[0] = (i ? 0x50:0x58) | (j&7);
		break;

	case i_xchg:
		if (numops != 2)		/* two operands required */
		 { Prog_Error(E_NUMOPS); break; };
		i = reg(operands);		/* see if first operand is a register */
		j = reg(&operands[1]);		/* same for second */
		k = opr_size(-1);		/* and finally determine size */
		Code[0] = 0x90;			/* default xchg op code */
		if (i==0 && j>=0 && j<8)	/* xchg reg with accumulator? (part 1) */
		 { Code[0] |= (j&7); break; };
		if (j==0 && i>=0 && i<8)	/* xchg reg with accumulator? (part 2) */
		 { Code[0] |= (i&7); break; };
		if (i>=0 && i<16)		/* first operand a register? */
		 { Code[0] = 0x86 | k;
		   addr(&operands[1]);		/* fill in mode and r/m fields */
		   Code[1] |= (i&7)<<3;
		   break;
		 }
		else if (j>=0 && j<16)		/* second operand a register? */
		 { Code[0] = 0x86 | k;
		   addr(operands);		/* fill in mode and r/m fields */
		   Code[1] |= (j&7)<<3;
		   break;
		 };
		Prog_Error(E_OPERAND);		/* can't do xchg */
		break;

	case i_in:	in_out(0xE4,0xEC); break;
	case i_inw:	in_out(0xE5,0xED); break;
	case i_out:	in_out(0xE6,0xEE); break;
	case i_outw:	in_out(0xE7,0xEF); break;
	case i_int:	in_out(0xCD,0xCC); break;	/* software interrupt */

	case i_sal:	shift(0x20D0,-1); break;
	case i_shr:	shift(0x28D0,-1); break;
	case i_sar:	shift(0x38D0,-1); break;
	case i_rol:	shift(0x00D0,-1); break;
	case i_ror:	shift(0x08D0,-1); break;
	case i_rcl:	shift(0x10D0,-1); break;
	case i_rcr:	shift(0x18D0,-1); break;

	case i_salb:	shift(0x20D0,0); break;
	case i_shrb:	shift(0x28D0,0); break;
	case i_sarb:	shift(0x38D0,0); break;
	case i_rolb:	shift(0x00D0,0); break;
	case i_rorb:	shift(0x08D0,0); break;
	case i_rclb:	shift(0x10D0,0); break;
	case i_rcrb:	shift(0x18D0,0); break;

	case i_jmp:	jump(0xE9,0x20FF); break;
	case i_call:	jump(0xE8,0x10FF); break;

	case i_jmpi:	jumpi(0xEA,0x28FF); break;
	case i_calli:	jumpi(0x9A,0x18FF); break;

	case i_ret:
	case i_reti:
		if (numops > 1)				/* at most one operand allowed */
		 { Prog_Error(E_NUMOPS); break; };
		i = (opindex==i_ret)?1:0;
		if (numops == 0)			/* no operands */
		 { Code[0] = i?0xC3:0xCB; break; };
		Code[0] = i?0xC2:0xCA;			/* here if adding to sp on ret */
		Code_length = 3;
		i = operands[0].value_o;		/* this is to be added */
		Code[1] = i&0377; Code[2] = i >> 8;
		if (operands[0].type_o!=t_norm		/* must be ordinary, abs expr */
		    || operands[0].sym_o!=NULL)
		 Prog_Error(E_OPERAND);			/* if not complain */
		break;

	case i_seg:
		if (numops != 1)			/* single operand... */
		 { Prog_Error(E_NUMOPS); break; };
		i = reg(operands);			/* first operand must be seg reg */
		if (i<16 || i>19)			/* if not complain */
		 { Prog_Error(E_OPERAND); break; };
		Code[0] = 0x26 | ((i&3)<<3);		/* code up prefix... */
		break;

	 case i_fabs:	fop0(0xE1D9,1); break;
	 case i_faddf:	fop1(0x00D8); break;
	 case i_faddl:	fop1(0x00DA); break;
	 case i_faddd:	fop1(0x00DC); break;
	 case i_faddi:	fop1(0x00DE); break;
	 case i_fadd:	freg(0xC0D8,1); break;
	 case i_faddp:	freg(0xC0DA,1); break;
	 case i_fchs:	fop0(0xE0D9,1); break;
	 case i_fclex:	fop0(0xE2DB,0); break;
	 case i_fcomf:	fop1(0x10D8); break;
	 case i_fcoml:	fop1(0x10DA); break;
	 case i_fcomd:	fop1(0x10DC); break;
	 case i_fcomi:	fop1(0x10DE); break;
	 case i_fcom:	freg(0xD0D8,0); break;
	 case i_fcompf:	fop1(0x18D8); break;
	 case i_fcompl:	fop1(0x18DA); break;
	 case i_fcompd:	fop1(0x18DC); break;
	 case i_fcompi:	fop1(0x18DE); break;
	 case i_fcomp:	freg(0xD8D8,0); break;
	 case i_fcompp:	fop0(0xD9DE,1); break;
	 case i_fdecstp:fop0(0xF6D9,1); break;
	 case i_fdisi:	fop0(0xE1DB,0); break;
	 case i_fdivf:	fop1(0x30D8); break;
	 case i_fdivl:	fop1(0x30DA); break;
	 case i_fdivd:	fop1(0x30DC); break;
	 case i_fdivi:	fop1(0x30DE); break;
	 case i_fdivrf:	fop1(0x38D8); break;
	 case i_fdivrl:	fop1(0x38DA); break;
	 case i_fdivrd:	fop1(0x38DC); break;
	 case i_fdivri:	fop1(0x38DE); break;
	 case i_fdiv:	freg(0xF0D8,1); break;
	 case i_fdivp:	freg(0xF0DA,1); break;
	 case i_fdivr:	freg(0xF8D8,1); break;
	 case i_fdivrp:	freg(0xF8DA,1); break;
	 case i_feni:	fop0(0xE0DB,0); break;
	 case i_ffree:	fstack(0xC0DD); break;
	 case i_fincstp:fop0(0xF7D9,1); break;
	 case i_finit:	fop0(0xE3DB,0); break;
	 case i_fldcw:	fop1(0x28D9); break;
	 case i_fldenv:	fop1(0x20D9); break;
	 case i_fldf:	fop1(0x00D9); break;
	 case i_fldl:	fop1(0x00DB); break;
	 case i_fldd:	fop1(0x00DD); break;
	 case i_fldi:	fop1(0x00DF); break;
	 case i_fld:	fstack(0xC0D9); break;
	 case i_fldlg2:	fop0(0xECD9,1); break;
	 case i_fldln2:	fop0(0xEDD9,1); break;
	 case i_fldl2e:	fop0(0xEAD9,1); break;
	 case i_fldl2t:	fop0(0xE9E9,1); break;
	 case i_fldpi:	fop0(0xEBD9,1); break;
	 case i_fldz:	fop0(0xEED9,1); break;
	 case i_fld1:	fop0(0xE8D9,1); break;
	 case i_fnop:	fop0(0xD0D9,1); break;
	 case i_fmulf:	fop1(0x08D8); break;
	 case i_fmull:	fop1(0x08DA); break;
	 case i_fmuld:	fop1(0x08DC); break;
	 case i_fmuli:	fop1(0x08DE); break;
	 case i_fmul:	freg(0xC8D8,1); break;
	 case i_fmulp:	freg(0xC8DA,1); break;
	 case i_fpatan:	fop0(0xF3D9,1); break;
	 case i_fprem:	fop0(0xF8D9,1); break;
	 case i_fptan:	fop0(0xF2D9,1); break;
	 case i_frstor:	fop1(0x20DD); break;
	 case i_frndint:fop0(0xFCD9,1); break;
	 case i_fsave:	fop1(0x30DD); break;
	 case i_fscale:	fop0(0xFDD9,1); break;
	 case i_fsqrt:	fop0(0xFAD9,1); break;
	 case i_fstf:	fop1(0x10D9); break;
	 case i_fstl:	fop1(0x10DB); break;
	 case i_fstd:	fop1(0x10DD); break;
	 case i_fsti:	fop1(0x10DF); break;
	 case i_fst:	fstack(0xD0DD); break;
	 case i_fstpf:	fop1(0x18D9); break;
	 case i_fstpl:	fop1(0x18DB); break;
	 case i_fstpd:	fop1(0x18DD); break;
	 case i_fstpi:	fop1(0x18DF); break;
	 case i_fstp:	fstack(0xD8DD); break;
	 case i_fstcw:	fop1(0x38D9); break;
	 case i_fstenv:	fop1(0x30D9); break;
	 case i_fstsw:	fop1(0x38DD); break;
	 case i_fsubf:	fop1(0x20D8); break;
	 case i_fsubl:	fop1(0x20DA); break;
	 case i_fsubd:	fop1(0x20DC); break;
	 case i_fsubi:	fop1(0x20DE); break;
	 case i_fsubrf:	fop1(0x28D8); break;
	 case i_fsubrl:	fop1(0x28DA); break;
	 case i_fsubrd:	fop1(0x28DC); break;
	 case i_fsubri:	fop1(0x28DE); break;
	 case i_fsub:	freg(0xE0D8,1); break;
	 case i_fsubp:	freg(0xE0DA,1); break;
	 case i_fsubr:	freg(0xE8D8,1); break;
	 case i_fsubrp:	freg(0xE8DA,1); break;
	 case i_ftst:	freg(0xE4D9,1); break;
	 case i_fwait:	no_ops(0x9B); break;
	 case i_fxam:	fop0(0xE5D9,1); break;
	 case i_fxch:	fstack(0xC8D9); break;
	 case i_fxtract:fop0(0xF4D9,1); break;
	 case i_fyl2x:	fop0(0xF1D9,1); break;
	 case i_fyl2xp1:fop0(0xF9D9,1); break;
	 case i_f2xm1:	fop0(0xF0D9,1); break;

	/* pseudo ops */
	case i_long:	ByteWord(L);
			goto pseudo;
	case i_word:	ByteWord(W);
			goto pseudo;
	case i_byte:	ByteWord(B); goto pseudo;
	case i_text:	New_Csect(Text_csect); goto pseudo;
	case i_data:	New_Csect(Data_csect); goto pseudo;
	case i_bss:	New_Csect(Bss_csect); goto pseudo;
	case i_globl:	Globl(); goto pseudo;
	case i_comm:	Comm(); goto pseudo;
	case i_even:	Even(); goto pseudo;
	case i_ascii:	Ascii(0); goto pseudo;
	case i_asciz:	Ascii(1); goto pseudo;
	case i_zerow:	Zerow();
			goto pseudo;

	pseudo:		Code_length = 0;
			break;

	default:	Prog_Error(E_OPCODE);
	};

	if (Code_length) {
	  Put_Text(Code,Code_length);	/* output text */
	  BC = Code_length;		/* increment LC */
	}
}

/* value(opnd,size,flg) -- puts value of operand into next bytes of Code updating
 * Code_length.  If relocatable, Put_Rel is called.
 *  If size=0, single byte value is
 * stored; otherwise full word is stored.  If flg is true (non-zero) then
 * sign-extenable operands (type=3) are stored as single bytes and the "s"
 * bit is set in the first byte of the opcode.
 */
value(opnd,size,flg)
 register struct oper *opnd;
 {	register int i,j;

	if (flg && size && opnd->type_o==t_sxt) { /* if word operation, see about sxt */
	  size = 0;			/* immediate operand only single byte */
	  Code[0] |= 2;			/* set "s" bit in opcode */
	  i = opnd->value_o & 0177600;	/* see what high 9 bits of value are */
	  if (Pass==2 && i!=0 && i!=0177600)	/* make sure its really sxt'able */
	    Prog_Warning(E_OPERAND);	/* if not complain */
	}
	j = opnd->value_o;		/* actual value */
	if (opnd->sym_o != NULL)	/* if relocatable, set stuff up correctly */
	  Put_Rel(opnd,size,Dot+Code_length,0);
	Code[Code_length++] = j & 0377;	/* store away low byte */
	if (size) Code[Code_length++] = j >> 8;	/* and then high byte */
}

/* opr_size -- returns 1 if word instruction, 0 if byte instruction.
 * Each operand is checked for consistency with other operands and with
 * the argument (-1 means don't care). The size is determined as follows:
 *  (1) if the operand type has t_short set, type is byte.
 *  (2)	if the operand is a byte register (i.e. al,cl,dl,bl,ah,ch,dh,bh)
 *	type is byte; if other register, type is word.
 *  (3)	otherwise type is undetermined.
 * If type is undetermined after examining all operands, type is word.
 */
osize(opnd)				/* return size of single operand */
 register struct oper *opnd;
 {	register int i,j;

	i = opnd->type_o;		/* get type of operand */
	if (i & t_short) return(0);	/* if short return byte size */
	if (i == t_reg)
	 return(((j = opnd->value_o)<8 || (j>=16 && j<=19))?1:0);
					/* if register then it has a size */
	return(-1);			/* don't really know yet */
}

opr_size(arg)
 {	register struct oper *opnd;	/* temp pointer to current operand */
	register int j,op;

	for (opnd=operands,op=0; op<numops; opnd++,op++) {
	  j = osize(opnd);		/* get size of operand */
	  if (j == -1) continue;	/* no info on type yet */
 	  else if (arg == -1) arg = j;	/* if undecided, remember correct answer */
	  else if (arg==0 && j==1 &&	/* if type=byte and opnd=word register */
	    opnd->type_o==t_reg &&
	    opnd->value_o<4)	/* then make it a byte register instead */
	    opnd->value_o += 8;
	  else if (arg != j) Prog_Error(E_OPERAND);
					/* all operands must have same type */
	};
	return(arg==-1 ? 1 : arg);	/* return 1 if no other indication found */
}

/* reg(opnd) -- returns -1 if opnd is not a register, otherwise returns
 * register number.
 */
reg(opnd)
 register struct oper *opnd;	/* temp operand pointer */
 {	if ((opnd->type_o & t_type) != t_reg) return(-1);
	else return(opnd->value_o);
}

/* immed() -- returns 1 if second operand is immediate, 0 otherwise */
immed()
 {	register int type;

	if ((type=(operands[1].type_o & t_type))==t_imm || type==t_sxt) return(1);
	return(0);
}

/* addr(opnd) -- sets mode and r/m fields according to info found in opnd.
 * displacement field is added where necessary and Code_length is set
 * appropriately.
 */
addr(opnd)
 register struct oper *opnd;	/* temp operand pointer */
 {	register int i;

	if (Code_length < 2) Code_length=2;	/* will fill in second byte */

	switch (opnd->type_o & t_type) {	/* dispatch on operand type */

	case t_reg:
		 i = reg(opnd);			/* get reg number */
		 if (i<0 || i>15)			/* must be ordinary reg */
		  { Prog_Error(E_REG); return; };
		 Code[1] |= 0300 | (i&7);		/* mod = 11, r/m = reg */
		 return;				/* nothing else to do */

	case t_norm:
		Code[1] |= 0006;		/* mod = 00, r/m = 110 */
		value(opnd,1,0);		/* fill in word displacement */
		return;

	index_reg:				/* here to fill in index register */
	case t_indr:
		switch (opnd->reg_o) {		/* indirect, check on reg # */
		case 3:	Code[1] |= 07;		/* (BX): r/m = 111 */
			return;

		case 5:	if ((opnd->type_o & t_type)==t_indr)
			 { Code[1] |= 0100;	/* (bp) changed to *0(bp) */
			   opnd->value_o = 0;
			   value(opnd,0,0);
			 }
			Code[1] |= 06;		/* (BP): r/m = 110 */
			return;

		case 6:	Code[1] |= 04;		/* (SI): r/m = 100 */
			return;

		case 7:	Code[1] |= 05;		/* (DI): r/m = 101 */
			return;

		case 64:Code[1] |= 00;		/* (BX_SI): r/m = 000 */
			return;

		case 65:Code[1] |= 01;		/* (BX_DI): r/m = 001 */
			return;

		case 66:Code[1] |= 02;		/* (BP_SI): r/m = 010 */
			return;

		case 67:Code[1] |= 03;		/* (BP_DI): r/m = 011 */
			return;

		index_error:			/* here if illegal register used */
		default:Prog_Error(E_REG);	/* illegal index register */
			return;
		};

	case t_ix:
		value(opnd,1,0);		/* fill in word offset for index mode */
		Code[1] |= 0200;		/* mod = 10 for full word offset */
		goto index_reg;			/* now fill in index register */

	case t_six:
		value(opnd,0,0);		/* fill in byte offset */
		Code[1] |= 0100;		/* mode = 01 for byte offset */
		goto index_reg;			/* now fill in index register */

	default:Prog_Error(E_OPERAND);		/* immediate modes not handled here */
		return;
	};
}

/* no_ops(opr) -- places opr in Code[0].  Ensures there are no operands. */

no_ops(opr)
 {	Code[0] = opr;				/* enter op code in produced code */
	if (numops != 0) Prog_Error(E_NUMOPS);	/* no operands for these instructions */
}

/* disp(opr) -- places pc-relative displacement in second byte of Code array (uses
 * first operand).  If destination is not in same CSECT or is not in range an
 * error is issued.  opr is placed in Code[0].
 */
disp(opr)
 {	register int d;				/* byte displacement */
	extern struct csect *Cur_csect;		/* pointer to current csect structure */

	Code[0] = opr;				/* remember to save op code */
	if (numops != 1)			/* check for single argument */
	 { Prog_Error(E_NUMOPS); return; };
	d = operands[0].value_o - (Dot + 2);
	if (operands[0].type_o != t_norm ||	/* must be ordinary operand */
	    operands[0].sym_o->csect_s
	     != Cur_csect ||			/* and in current csect */
	    -128>d || d>127 )			/* and within range */
	 { Prog_Error(E_RELADDR); d=0; };	/* otherwise complain */
	Code_length = 2;			/* second byte is for disp */
	Code[1] = d;				/* fill it in! */
 };

/* branch -- br is op code code for direct branch; obr is op code for opposite branch.
 * chooses either direct branch, or opposite branch around jmp based on how far away
 * destination is.
 */
branch(br,obr)
 {	int offs = 0;
	register struct oper *opp = operands;
	extern struct csect *Cur_csect;	/* pointer to current csect structure */
	extern char shortblist[];	/* it's not a char array, all we want is addr */

	if (numops != 1) Prog_Error(E_NUMOPS);
	else if ((opp->type_o & t_type) != t_norm)	/* not a direct address */
	  Prog_Error(E_OPERAND);
	else {
	  offs = opp->value_o - (Dot + 2);
	  if (opp->flags_o & O_COMPLEX) goto blong;	/* too complicated, use long branch */
	  else if (Pass == 1)
	    Code_length = makesdi(opp, obr==0 ? 3 : 5, Dot+2, shortblist);
	  else if (opp->sym_o->csect_s != Cur_csect) goto blong;
	  else if (offs >= -128 && offs <= 127) {
	    Code_length = 2;
	    Code[0] = br;
	    Code[1] = offs;
	  } else {
  blong:    if (obr == 0) {		/* just use jmp */
	      Code[0] = 0xE9;		/* stick in jmp instruction */
	      offs -= 1;		/* account for insertion of jmp */
	      if (operands[0].sym_o->csect_s != Cur_csect)
	        Put_Rel(operands,1,Dot+1,1);
	      Code_length = 3;		/* fill in displacement */
	      Code[1] = offs & 0377;
	      Code[2] = offs >> 8;
	    } else {
	      Code[0] = obr;		/* branch around jmp */
	      Code[1] = 3;		/* jmp is three bytes long */
	      Code[2] = 0xE9;		/* stick in jmp instruction */
	      offs -= 3;		/* account for insertion of jmp */
	      if (operands[0].sym_o->csect_s != Cur_csect)
	        Put_Rel(operands,1,Dot+3,1);
	      Code_length = 5;		/* fill in displacement */
	      Code[3] = offs & 0377;
	      Code[4] = offs >> 8;
	    }
	  }

	}
}

/* load - handles loads of EA or pointers to a register.  expects first argument
 * to be a register, second to be a general address.
 */
load(op)
 {	register int i,j;

	if (numops != 2)		/* make sure there are 2 operands */
	 { Prog_Error(E_NUMOPS); return; };
	opr_size(1);			/* both operands must be words */
	i = reg(operands);		/* first operands must be register */
	if (i<0 || i>7)
	 { Prog_Error(E_OPERAND); return; };
	Code[0] = op;			/* fill in opcode and register */
	Code[1] = i<<3;
	addr(&operands[1]);		/* second operand is general address */
	return;
 };

move(size)				/* subr to handle move op code */
 {	register int i,j,k;		/* some useful temps */

	if (numops != 2)		/* make sure there are 2 operands */
	 { Prog_Error(E_NUMOPS); return; };
	k = opr_size(size);		/* remember whether word or byte */
	i = reg(operands);		/* see if first operand is a reg */
	j = reg(&operands[1]);		/* and same for second operand */
	if (immed())			/* if second operand is immediate */
	 if (i != -1)			/* and first operand is a register */
	  { if (i>=16)			/* only allow regular regs here */
	     { Prog_Error(E_OPERAND); return; };
	    Code[0] = 0260 | k<<3 | i&7; /* opcode = immediate to register */
	    value(&operands[1],k,0);	/* stick in immediate value */
	    return;
	  } else			/* here if first operand not reg */
	  { Code[0] = 0306 | k;		/* opcode = immediate to reg/mem */
	    addr(operands);		/* fill in address of destination */
	    value(&operands[1],k,0);	/* stick in immediate value */
	    return;
	  };
	if ((i==0 || i==8) &&		/* if first operand is accumulator */
	    (operands[1].type_o&t_type) == t_norm)	/* and second operand is memory */
	 { Code[0] = 0240 | k;		/* opcode = memory to accumulator */
	   value(&operands[1],1,0);	/* this is memory address */
	   return;
	 };
	if ((j==0 || j==8) &&		/* if second operand is accumulator */
	    (operands[0].type_o&t_type) == t_norm)	/* and first operand is memory */
	 { Code[0] = 0242 | k;		/* opcode = accumulator to memory */
	   value(operands,1,0);		/* this is memory address */
	   return;
	 };
	if (i>=16 && i<=19)		/* if destination is seg register */
	 { Code[0] = 0216;		/* opcode = mem/reg to seg register */
	   addr(&operands[1]);		/* fill in memory address */
	   Code[1] |= (i&3)<<3;		/* and segment register number */
	   return;
	 };
	if (j>=16 && j<=19)		/* if source is seg register */
	 { Code[0] = 0214;		/* opcode = seg register to mem/reg */
	   addr(operands);		/* fill in memory address */
	   Code[1] |= (j&3)<<3;		/* and segment register number */
	   return;
	 };
	Code[0] = 0210 | k;		/* default opcode */
	if (i >= 0 && i < 16)		/* destination is register */
	 { Code[0] |= 2;		/* set direction bit */
	   addr(&operands[1]);		/* source provides gen address */
	   Code[1] |= (i&7)<<3;
	   return;
	 }
	if (j >= 0 && j < 16)		/* source is register */
	 { addr(operands);		/* destination provides gen address */
	   Code[1] |= (j&7)<<3;
	   return;
	 }
	Prog_Error(E_OPERAND);
 }

/* gen -- routine for most op codes (add, sub, etc.)
 *	op1	reg/mem with register to either
 *	op2	immediate to register/memory
 *	op3	immediate to accumulator
 * dir non-zero => instruction has direction bit in op code
 * sxt non-zero => instruction supports sign-extended bytes as word operands
 * size = 0 => byte operand, = -1 => any size operand
 */
gen_op(op1,op2,op3,dir,sxt,size)	/* subr to handle add, sub, cmp, etc. op code */
 {	register int i,j,k;		/* some useful temps */

	if (numops != 2)		/* make sure there are 2 operands */
	 { Prog_Error(E_NUMOPS); return; };
	k = opr_size(size);		/* remember whether word or byte */
	i = reg(operands);		/* see if first operand is a reg */
	j = reg(&operands[1]);		/* and same for second operand */
	if (immed())			/* if second operand is immediate */
	 if (i==0 || i==8)		/* and first operand is a accumulator */
	  { Code[0] = op3 | k;		/* opcode = immediate to accumulator */
	    value(&operands[1],k,0);	/* stick in immediate value */
	    return;
	  } else			/* here if first operand not accumulator */
	  { Code[0] = (op2 & 0377) | k;	/* opcode = immediate to reg/mem */
	    Code[1] = op2 >> 8;		/* fill in second byte of opcode */
	    addr(operands);		/* fill in address of destination */
	    value(&operands[1],k,sxt);	/* stick in immediate value */
	    return;
	  };
	Code[0] = op1 | k;		/* default opcode */
	if (i >= 0 && i < 16)		/* destination is register */
	 { if (dir) Code[0] |= 2;	/* set direction bit if possible */
	   addr(&operands[1]);		/* source provides gen address */
	   Code[1] |= (i&7)<<3;		/* set register destination */
	   return;
	 };
	if (j >= 0 && j < 16)		/* source is register */
	 { addr(operands);		/* destination provides gen address */
	   Code[1] |= (j&7)<<3;		/* set register source */
	   return;
	 };
	Prog_Error(E_OPERAND);		/* oops, can't make any sense of it */
 }

/* in_out handles the IN and OUT instructions.  op1 is used for fixed port
 * (1 operand) instructions; op2 for variable port (0 operand) instructions.
 */
in_out(op1,op2)
 {	register int v;

	if (numops > 1)			/* at most one operand... */
	 { Prog_Error(E_NUMOPS); return; };
	if (numops == 0)		/* variable port */
	 { Code[0] = op2; return; };
	if ((operands[0].type_o&t_type)!=t_norm	/* must be ordinary operand */
 	    || operands[0].sym_o!=NULL) /* and defined in ABS csect */
	 { Prog_Error(E_OPERAND); return; };
	if ((v = operands[0].value_o)&0177600)
	 Prog_Warning(E_OPERAND);
	Code[0] = op1;
	Code_length = 2;		/* we'll fill in second byte */
	Code[1] = v;
	return;
 }

/* one_op -- generates code for single operand instructions.  First argument
 * specifies 2 byte op code; routine determines w, mod, and r/m fields.
 */
one_op(op,size)
 {	if (numops != 1)		/* only one operand allowed */
	 { Prog_Error(E_NUMOPS); return; };
	Code[0] = (op&0377) | opr_size(size); /* determine size of single operand */
	Code[1] = op >> 8;		/* fill in second byte of instruction */
	addr(operands);			/* set up mod and r/m fields */
	return;
 }

/* shift - generates code for shift instructions.  sets w bit according to
 * size of operand; sets v bit to 0 if second op is #1, to 1 if second op is
 * cl (error otherwise).
 */
shift(op,size)
 {	register int i;

	if (numops != 2)			/* need 2 operands */
	 { Prog_Error(E_NUMOPS); return; };
	numops = 1;				/* only look at first operand */
	Code[0] = (op&0377) | opr_size(size);	/* remember shift op code */
	Code[1] = op >> 8;
	addr(operands);				/* set up mod and r/m fields */
	i = operands[1].type_o & t_type;	/* find out type of second operand */
	if (i==t_reg && operands[1].value_o==9)	/* if second operand is "cl" */
	 { Code[0] |= 2; return; };		/* then set v bit in first op code byte */
	if ((i==t_imm || i==t_sxt) && operands[1].sym_o==NULL
	    && operands[1].value_o==1)	/* if second operand is "#1" */
	 return;				/* just return */
	Prog_Error(E_OPERAND);			/* otherwise second operand is wrong! */
 }

/* jump -- generates code for jmp and call instructions.
 * only full-word displacements (op1) or indirect operand (op2) are allowed.
 */
jump(op1,op2)
 {	register int i,d;

	if (numops != 1)			/* single operand */
	 { Prog_Error(E_NUMOPS); return; };
	if (operands[0].type_o & t_ind)		/* indirect? */
	 { Code[0] = op2 & 0377;
	   Code[1] = op2 >> 8;
	   addr(operands);			/* fill in address of address */
	   return;
	 };
	if (((i=operands[0].type_o)&t_type) != t_norm) /* must be ordinary operand for disp */
	 Prog_Error(E_RELADDR);			/* otherwise complain */
	d = operands[0].value_o - (Dot + 3);
	if (operands[0].sym_o->csect_s != Cur_csect)
	 Put_Rel(operands,1,Dot+1,1);		/* relocate first operand */
	Code_length = 3;			/* fill in displacement */
	Code[0] = op1;
	Code[1] = d & 0377;
	Code[2] = d >> 8;
	return;
 }

/* jumpi -- generates code for intersegment jumps and calls.  First argument is
 * used as opcode when segment is given explicitly (second argument in instruction);
 * second arg is opcode when indirect address is given.
 */
jumpi(op1,op2)
 {	if (operands[0].type_o & t_ind)		/* indirect? */
	 { if (numops != 1)			/* single indirect operand */
	    { Prog_Error(E_NUMOPS); return; };
	   Code[0] = op2 & 0377;
	   Code[1] = op2 >> 8;
	   addr(operands);			/* fill in address of address */
	   return;
	 };
	if (numops != 2)			/* must be two operands for direct jump */
	 { Prog_Error(E_NUMOPS); return; };
	if ((operands[0].type_o & t_type) != t_norm)
	 { Prog_Error(E_OPERAND); return; };	/* must be ordinary operand for offset */
	Code[0] = op1;				/* use first op code for 2 arg jumpi/calli */
	value(operands,1,0);			/* save away word offset & do relocation */
	if (((operands[1].type_o & t_type) != t_norm) ||
	    (operands[1].sym_o != NULL))	/* second operand must be absolute */
	 { Prog_Error(E_OPERAND); return; };
	value(&operands[1],1,0);		/* save this value away too */
	return;
 }

/* no operands, insert wait if requested */
fop0(op,waitf)
 {	register int i = 0;		/* byte number */

	if (numops != 0) Prog_Error(E_NUMOPS);	/* no operands for these instructions */
	if (waitf) Code[i++] = 0x9B;		/* put in WAIT op code */
	Code[i++] = op & 0377;			/* enter first byte of op code */
	Code[i++] = op >> 8;			/* enter second byte of op code */
	Code_length = i;			/* adjust code length */
}

/* one operand floating operation */
fop1(op)
 {	if (numops != 1) { Prog_Error(E_NUMOPS); return; }
	Code_length = 3;
	addr(operands);		/* will fill in second byte, possibly forth and fifth */
	Code[2] = Code[1] | (op >> 8);		/* save away addr result in correct place */
	Code[1] = op & 0377;			/* enter first byte of op code */
	Code[0] = 0x9B;				/* WAIT opcode */
}

/* floating operations on stack regs */
freg(op,dirf)
 {	register int direction = 0;
	register int reg;

	if (numops != 2) { Prog_Error(E_NUMOPS); return; }
	if (operands[0].type_o!=t_norm || operands[0].sym_o!=NULL ||
	    operands[1].type_o!=t_norm || operands[1].sym_o!=NULL)
	  { Prog_Error(E_OPERAND); return; }
	if (operands[1].value_o == 0) { direction = 1; reg = operands[0].value_o & 07; }
	else reg = operands[1].value_o & 07;
	Code_length = 3;
	Code[0] = 0x9B;				/* WAIT opcode */
	Code[1] = op & 0377;			/* enter first byte of op code */
	Code[2] = (op >> 8) | reg;		/* enter second byte of op code */
	if (dirf && direction) Code[1] |= 4;	/* set direction bit if it matters */
}

/* floating stack manipulation */
fstack(op)
 {	register reg;

	if (numops != 1) { Prog_Error(E_NUMOPS); return; }
	if (operands[0].type_o!=t_norm || operands[0].sym_o!=NULL)
	  { Prog_Error(E_OPERAND); return; }
	reg = operands[0].value_o & 07;
	Code_length = 3;
	Code[0] = 0x9B;				/* WAIT opcode */
	Code[1] = op & 0377;			/* enter first byte of op code */
	Code[2] = (op >> 8) | reg;		/* enter second byte of op code */
}
ode */
	if (dirf && direction) Code[1] |= 4;	/* set direction bit if it matters */
}

/* floating stack manipulation */
fstack(op)
 {	register reg;

	if (numops != 1) { Prog_Error(E_NUMOPS); return; }
	if (operands[0].type_o!=t_norm || operands[0].sym_o!=NULL)
	  { Prog_Error(E_OPERAND); return; }
	reg = operands[0].value_o & 07;
	Code_length = 3;
	Code[0] = 0x9B;				/* WAIT opcode */
	Code[1] = op & 0377;			/* enter first byte of op code */
	Code[2] = (op >> 8) | a86/ld86.c                                                                                             444      26      12       131340  3372237604   5445                                                                                                                                                                                                                                                                                                                                                                      static	char sccsid[] = "@(#)ld.c 4.4 4/26/81";
/*
 * ld86 - string table version for 8086 (snarfed from 4.1BSD)
 */

#include <sys/param.h>
#include <signal.h>
#include <stdio.h>
#include <ctype.h>
#include <ar.h>
#include <a.out.h>
#include <ranlib.h>
#include <sys/stat.h>

#define	PAGSIZ	(DEV_BSIZE)
#define DEV_BMASK	(DEV_BSIZE - 1)


/*
 * Basic strategy:
 *
 * The loader takes a number of files and libraries as arguments.
 * A first pass examines each file in turn.  Normal files are
 * unconditionally loaded, and the (external) symbols they define and require
 * are noted in the symbol table.   Libraries are searched, and the
 * library members which define needed symbols are remembered
 * in a special data structure so they can be selected on the second
 * pass.  Symbols defined and required by library members are also
 * recorded.
 *
 * After the first pass, the loader knows the size of the basic text
 * data, and bss segments from the sum of the sizes of the modules which
 * were required.  It has computed, for each ``common'' symbol, the
 * maximum size of any reference to it, and these symbols are then assigned
 * storage locations after their sizes are appropriately rounded.
 * The loader now knows all sizes for the eventual output file, and
 * can determine the final locations of external symbols before it
 * begins a second pass.
 *
 * On the second pass each normal file and required library member
 * is processed again.  The symbol table for each such file is
 * reread and relevant parts of it are placed in the output.  The offsets
 * in the local symbol table for externally defined symbols are recorded
 * since relocation information refers to symbols in this way.
 * Armed with all necessary information, the text and data segments
 * are relocated and the result is placed in the output file, which
 * is pasted together, ``in place'', by writing to it in several
 * different places concurrently.
 */

/*
 * Internal data structures
 *
 * All internal data structures are segmented and dynamically extended.
 * The basic structures hold 1103 (NSYM) symbols, ~~200 (NROUT)
 * referenced library members, and 100 (NSYMPR) private (local) symbols
 * per object module.  For large programs and/or modules, these structures
 * expand to be up to 40 (NSEG) times as large as this as necessary.
 */
#define	NSEG	40		/* Number of segments, each data structure */
#define	NSYM	1103		/* Number of symbols per segment */
#define	NROUT	250		/* Number of library references per segment */
#define	NSYMPR	100		/* Number of private symbols per segment */

/*
 * Structure describing each symbol table segment.
 * Each segment has its own hash table.  We record the first
 * address in and first address beyond both the symbol and hash
 * tables, for use in the routine symx and the lookup routine respectively.
 * The symfree routine also understands this structure well as it used
 * to back out symbols from modules we decide that we don't need in pass 1.
 *
 * Csymseg points to the current symbol table segment;
 * csymseg->sy_first[csymseg->sy_used] is the next symbol slot to be allocated,
 * (unless csymseg->sy_used == NSYM in which case we will allocate another
 * symbol table segment first.)
 */
struct	symseg {
	struct	nlist *sy_first;	/* base of this alloc'ed segment */
	struct	nlist *sy_last;		/* end of this segment, for n_strx */
	int	sy_used;		/* symbols used in this seg */
	struct	nlist **sy_hfirst;	/* base of hash table, this seg */
	struct	nlist **sy_hlast;	/* end of hash table, this seg */
} symseg[NSEG], *csymseg;

/*
 * The lookup routine uses quadratic rehash.  Since a quadratic rehash
 * only probes 1/2 of the buckets in the table, and since the hash
 * table is segmented the same way the symbol table is, we make the
 * hash table have twice as many buckets as there are symbol table slots
 * in the segment.  This guarantees that the quadratic rehash will never
 * fail to find an empty bucket if the segment is not full and the
 * symbol is not there.
 */
#define	HSIZE	(NSYM*2)

/*
 * Xsym converts symbol table indices (ala x) into symbol table pointers.
 * Symx (harder, but never used in loops) inverts pointers into the symbol
 * table into indices using the symseg[] structure.
 */
#define	xsym(x)	(symseg[(x)/NSYM].sy_first+((x)%NSYM))
/* symx() is a function, defined below */

struct	nlist cursym;		/* current symbol */
struct	nlist *lastsym;		/* last symbol entered */
struct	nlist *nextsym;		/* next available symbol table entry */
struct	nlist *addsym;		/* first sym defined during incr load */
int	nsym;			/* pass2: number of local symbols in a.out */
/* nsym + symx(nextsym) is the symbol table size during pass2 */

struct	nlist **lookup(), **slookup();
struct	nlist *p_etext, *p_edata, *p_end, *entrypt;

/*
 * Definitions of segmentation for library member table.
 * For each library we encounter on pass 1 we record pointers to all
 * members which we will load on pass 2.  These are recorded as offsets
 * into the archive in the library member table.  Libraries are
 * separated in the table by the special offset value -1.
 */
off_t	li_init[NROUT];
struct	libseg {
	off_t	*li_first;
	int	li_used;
	int	li_used2;
} libseg[NSEG] = {
	li_init, 0, 0,
}, *clibseg = libseg;

/*
 * In processing each module on pass 2 we must relocate references
 * relative to external symbols.  These references are recorded
 * in the relocation information as relative to local symbol numbers
 * assigned to the external symbols when the module was created.
 * Thus before relocating the module in pass 2 we create a table
 * which maps these internal numbers to symbol table entries.
 * A hash table is constructed, based on the local symbol table indices,
 * for quick lookup of these symbols.
 */
#define	LHSIZ	31
struct	local {
	int	l_index;		/* index to symbol in file */
	struct	nlist *l_symbol;	/* ptr to symbol table */
	struct	local *l_link;		/* hash link */
} *lochash[LHSIZ], lhinit[NSYMPR];
struct	locseg {
	struct	local *lo_first;
	int	lo_used;
} locseg[NSEG] = {
	lhinit, 0
}, *clocseg;

/*
 * Libraries are typically built with a table of contents,
 * which is the first member of a library with special file
 * name __.SYMDEF and contains a list of symbol names
 * and with each symbol the offset of the library member which defines
 * it.  The loader uses this table to quickly tell which library members
 * are (potentially) useful.  The alternative, examining the symbol
 * table of each library member, is painfully slow for large archives.
 *
 * See <ranlib.h> for the definition of the ranlib structure and an
 * explanation of the __.SYMDEF file format.
 */
int	tnum;		/* number of symbols in table of contents */
int	ssiz;		/* size of string table for table of contents */
struct	ranlib *tab;	/* the table of contents (dynamically allocated) */
char	*tabstr;	/* string table for table of contents */

/*
 * We open each input file or library only once, but in pass2 we
 * (historically) read from such a file at 2 different places at the
 * same time.  These structures are remnants from those days,
 * and now serve only to catch ``Premature EOF''.
 */
typedef struct {
	short	*fakeptr;
	int	bno;
	int	nibuf;
	int	nuser;
	char	buff[DEV_BSIZE];
} PAGE;

PAGE	page[2];

struct {
	short	*fakeptr;
	int	bno;
	int	nibuf;
	int	nuser;
} fpage;

typedef struct {
	char	*ptr;
	int	bno;
	int	nibuf;
	long	size;
	long	pos;
	PAGE	*pno;
} STREAM;

STREAM	text;
STREAM	reloc;

/*
 * Header from the a.out and the archive it is from (if any).
 */
struct	exec filhdr;
struct	ar_hdr archdr;
#define	OARMAG 0177545

/*
 * Options.
 */
int	trace;
int	xflag;		/* discard local symbols */
int	Xflag;		/* discard locals starting with 'L' */
int	Sflag;		/* discard all except locals and globals*/
int	rflag;		/* preserve relocation bits, don't define common */
int	arflag;		/* original copy of rflag */
int	sflag;		/* discard all symbols */
int	Mflag;		/* print rudimentary load map */
int	nflag;		/* pure procedure */
int	dflag;		/* define common even with rflag */
int	zflag;		/* demand paged  */
long	hsize;		/* size of hole at beginning of data to be squashed */
int	Aflag;		/* doing incremental load */
int	Nflag;		/* want impure a.out */
int	funding;	/* reading fundamental file for incremental load */
int	yflag;		/* number of symbols to be traced */
char	**ytab;		/* the symbols */

/*
 * These are the cumulative sizes, set in pass 1, which
 * appear in the a.out header when the loader is finished.
 */
off_t	tsize, dsize, bsize, trsize, drsize, ssize;

/*
 * Symbol relocation: c?rel is a scale factor which is
 * added to an old relocation to convert it to new units;
 * i.e. it is the difference between segment origins.
 * (Thus if we are loading from a data segment which began at location
 * 4 in a .o file into an a.out where it will be loaded starting at
 * 1024, cdrel will be 1020.)
 */
long	ctrel, cdrel, cbrel;

/*
 * Textbase is the start address of all text, 0 unless given by -T.
 * Database is the base of all data, computed before and used during pass2.
 */
long	textbase, database;

/*
 * The base addresses for the loaded text, data and bss from the
 * current module during pass2 are given by torigin, dorigin and borigin.
 */
long	torigin, dorigin, borigin;

/*
 * Errlev is nonzero when errors have occured.
 * Delarg is an implicit argument to the routine delexit
 * which is called on error.  We do ``delarg = errlev'' before normal
 * exits, and only if delarg is 0 (i.e. errlev was 0) do we make the
 * result file executable.
 */
int	errlev;
int	delarg	= 4;

/*
 * The biobuf structure and associated routines are used to write
 * into one file at several places concurrently.  Calling bopen
 * with a biobuf structure sets it up to write ``biofd'' starting
 * at the specified offset.  You can then use ``bwrite'' and/or ``bputc''
 * to stuff characters in the stream, much like ``fwrite'' and ``fputc''.
 * Calling bflush drains all the buffers and MUST be done before exit.
 */
struct	biobuf {
	short	b_nleft;		/* Number free spaces left in b_buf */
/* Initialize to be less than BUFSIZ initially, to boundary align in file */
	char	*b_ptr;			/* Next place to stuff characters */
	char	b_buf[BUFSIZ];		/* The buffer itself */
	off_t	b_off;			/* Current file offset */
	struct	biobuf *b_link;		/* Link in chain for bflush() */
} *biobufs;
#define	bputc(c,b) ((b)->b_nleft ? (--(b)->b_nleft, *(b)->b_ptr++ = (c)) \
		       : bflushc(b, c))
int	biofd;
off_t	boffset;
struct	biobuf *tout, *dout, *trout, *drout, *sout, *strout;

/*
 * Offset is the current offset in the string file.
 * Its initial value reflects the fact that we will
 * eventually stuff the size of the string table at the
 * beginning of the string table (i.e. offset itself!).
 */
off_t	offset = sizeof (off_t);

int	ofilfnd;		/* -o given; otherwise move l.out to a.out */
char	*ofilename = "l.out";
int	ofilemode;		/* respect umask even for unsucessful ld's */
int	infil;			/* current input file descriptor */
char	*filname;		/* and its name */

/*
 * Base of the string table of the current module (pass1 and pass2).
 */
char	*curstr;

char 	get();
int	delexit();
char	*savestr();

main(argc, argv)
char **argv;
{
	register int c, i; 
	int num;
	register char *ap, **p;
	char save;

	if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
		signal(SIGINT, delexit);
		signal(SIGTERM, delexit);
	}
	if (argc == 1)
		exit(4);
	p = argv+1;

	/*
	 * Scan files once to find where symbols are defined.
	 */
	for (c=1; c<argc; c++) {
		if (trace)
			printf("%s:\n", *p);
		filname = 0;
		ap = *p++;
		if (*ap != '-') {
			load1arg(ap);
			continue;
		}
		for (i=1; ap[i]; i++) switch (ap[i]) {

		case 'o':
			if (++c >= argc)
				error(1, "-o where?");
			ofilename = *p++;
			ofilfnd++;
			continue;
		case 'u':
		case 'e':
			if (++c >= argc)
				error(1, "-u or -c: arg missing");
			enter(slookup(*p++));
			if (ap[i]=='e')
				entrypt = lastsym;
			continue;
		case 'H':
			if (++c >= argc)
				error(1, "-H: arg missing");
			if (tsize!=0)
				error(1, "-H: too late, some text already loaded");
			hsize = atoi(*p++);
			continue;
		case 'A':
			if (++c >= argc)
				error(1, "-A: arg missing");
			if (Aflag) 
				error(1, "-A: only one base file allowed");
			Aflag = 1;
			nflag = 0;
			funding = 1;
			load1arg(*p++);
			trsize = drsize = tsize = dsize = bsize = 0;
			ctrel = cdrel = cbrel = 0;
			funding = 0;
			addsym = nextsym;
			continue;
		case 'D':
			if (++c >= argc)
				error(1, "-D: arg missing");
			num = htoi(*p++);
			if (dsize > num)
				error(1, "-D: too small");
			dsize = num;
			continue;
		case 'T':
			if (++c >= argc)
				error(1, "-T: arg missing");
			if (tsize!=0)
				error(1, "-T: too late, some text already loaded");
			textbase = htoi(*p++);
			continue;
		case 'l':
			save = ap[--i]; 
			ap[i]='-';
			load1arg(&ap[i]); 
			ap[i]=save;
			goto next;
		case 'M':
			Mflag++;
			continue;
		case 'x':
			xflag++;
			continue;
		case 'X':
			Xflag++;
			continue;
		case 'S':
			Sflag++; 
			continue;
		case 'r':
			rflag++;
			arflag++;
			continue;
		case 's':
			sflag++;
			xflag++;
			continue;
		case 'n':
			nflag++;
			Nflag = zflag = 0;
			continue;
		case 'N':
			Nflag++;
			nflag = zflag = 0;
			continue;
		case 'd':
			dflag++;
			continue;
		case 'i':
			printf("ld86: -i ignored\n");
			continue;
		case 't':
			trace++;
			continue;
		case 'y':
			if (ap[i+1] == 0)
				error(1, "-y: symbol name missing");
			if (yflag == 0) {
				ytab = (char **)calloc(argc, sizeof (char **));
				if (ytab == 0)
					error(1, "ran out of memory (-y)");
			}
			ytab[yflag++] = &ap[i+1];
			goto next;
		case 'z':
			zflag++;
			Nflag = nflag = 0;
			continue;
		default:
			filname = savestr("-x");	/* kludge */
			filname[1] = ap[i];		/* kludge */
			archdr.ar_name[0] = 0;		/* kludge */
			error(1, "bad flag");
		}
next:
		;
	}
	if (rflag == 0 && Nflag == 0 && nflag == 0)
		zflag++;
	endload(argc, argv);
	exit(0);
}

/*
 * Convert a ascii string which is a hex number.
 * Used by -T and -D options.
 */
htoi(p)
	register char *p;
{
	register int c, n;

	n = 0;
	while (c = *p++) {
		n <<= 4;
		if (isdigit(c))
			n += c - '0';
		else if (c >= 'a' && c <= 'f')
			n += 10 + (c - 'a');
		else if (c >= 'A' && c <= 'F')
			n += 10 + (c - 'A');
		else
			error(1, "badly formed hex number");
	}
	return (n);
}

delexit()
{

	bflush();
	unlink("l.out");
	if (delarg==0 && Aflag==0)
		chmod(ofilename, ofilemode);
	exit (delarg);
}

endload(argc, argv)
	int argc; 
	char **argv;
{
	register int c, i; 
	long dnum;
	register char *ap, **p;

	clibseg = libseg;
	filname = 0;
	middle();
	setupout();
	p = argv+1;
	for (c=1; c<argc; c++) {
		ap = *p++;
		if (trace)
			printf("%s:\n", ap);
		if (*ap != '-') {
			load2arg(ap);
			continue;
		}
		for (i=1; ap[i]; i++) switch (ap[i]) {

		case 'D':
			dnum = htoi(*p);
			if (dorigin < dnum)
				while (dorigin < dnum)
					bputc(0, dout), dorigin++;
			/* fall into ... */
		case 'T':
		case 'u':
		case 'e':
		case 'o':
		case 'H':
			++c; 
			++p;
			/* fall into ... */
		default:
			continue;
		case 'A':
			funding = 1;
			load2arg(*p++);
			funding = 0;
			c++;
			continue;
		case 'y':
			goto next;
		case 'l':
			ap[--i]='-'; 
			load2arg(&ap[i]);
			goto next;
		}
next:
		;
	}
	finishout();
}

/*
 * Scan file to find defined symbols.
 */
load1arg(cp)
	register char *cp;
{
	register struct ranlib *tp;
	off_t nloc;
	int kind;

	kind = getfile(cp);
	if (Mflag)
		printf("%s\n", filname);
	switch (kind) {

	/*
	 * Plain file.
	 */
	case 0:
		load1(0, 0L);
		break;

	/*
	 * Archive without table of contents.
	 * (Slowly) process each member.
	 */
	case 1:
		error(-1,
"warning: archive has no table of contents; add one using ranlib(1)");
		nloc = SARMAG;
		while (step(nloc))
			nloc += sizeof(archdr) +
			    round(atol(archdr.ar_size), sizeof (short));
		break;

	/*
	 * Archive with table of contents.
	 * Read the table of contents and its associated string table.
	 * Pass through the library resolving symbols until nothing changes
	 * for an entire pass (i.e. you can get away with backward references
	 * when there is a table of contents!)
	 */
	case 2:
		nloc = SARMAG + sizeof (archdr);
		dseek(&text, nloc, sizeof (tnum));
		mget((char *)&tnum, sizeof (tnum), &text);
		nloc += sizeof (tnum);
		tab = (struct ranlib *)malloc(tnum);
		if (tab == 0)
			error(1, "ran out of memory (toc)");
		dseek(&text, nloc, tnum);
		mget((char *)tab, tnum, &text);
		nloc += tnum;
		tnum /= sizeof (struct ranlib);
		dseek(&text, nloc, sizeof (ssiz));
		mget((char *)&ssiz, sizeof (ssiz), &text);
		nloc += sizeof (ssiz);
		tabstr = (char *)malloc(ssiz);
		if (tabstr == 0)
			error(1, "ran out of memory (tocstr)");
		dseek(&text, nloc, ssiz);
		mget((char *)tabstr, ssiz, &text);
		for (tp = &tab[tnum]; --tp >= tab;) {
			if (tp->ran_un.ran_strx < 0 ||
			    tp->ran_un.ran_strx >= ssiz)
				error(1, "mangled archive table of contents");
			tp->ran_un.ran_name = tabstr + tp->ran_un.ran_strx;
		}
		while (ldrand())
			continue;
		cfree((char *)tab);
		cfree(tabstr);
		nextlibp(-1);
		break;

	/*
	 * Table of contents is out of date, so search
	 * as a normal library (but skip the __.SYMDEF file).
	 */
	case 3:
		error(-1,
"warning: table of contents for archive is out of date; rerun ranlib(1)");
		nloc = SARMAG;
		do
			nloc += sizeof(archdr) +
			    round(atol(archdr.ar_size), sizeof(short));
		while (step(nloc));
		break;
	}
	close(infil);
}

/*
 * Advance to the next archive member, which
 * is at offset nloc in the archive.  If the member
 * is useful, record its location in the liblist structure
 * for use in pass2.  Mark the end of the archive in libilst with a -1.
 */
step(nloc)
	off_t nloc;
{

	dseek(&text, nloc, (long) sizeof archdr);
	if (text.size <= 0) {
		nextlibp(-1);
		return (0);
	}
	getarhdr();
	if (load1(1, nloc + (sizeof archdr)))
		nextlibp(nloc);
	return (1);
}

/*
 * Record the location of a useful archive member.
 * Recording -1 marks the end of files from an archive.
 * The liblist data structure is dynamically extended here.
 */
nextlibp(val)
	off_t val;
{

	if (clibseg->li_used == NROUT) {
		if (++clibseg == &libseg[NSEG])
			error(1, "too many files loaded from libraries");
		clibseg->li_first = (off_t *)malloc(NROUT * sizeof (off_t));
		if (clibseg->li_first == 0)
			error(1, "ran out of memory (nextlibp)");
	}
	clibseg->li_first[clibseg->li_used++] = val;
	if (val != -1 && Mflag)
		printf("\t%s\n", archdr.ar_name);
}

/*
 * One pass over an archive with a table of contents.
 * Remember the number of symbols currently defined,
 * then call step on members which look promising (i.e.
 * that define a symbol which is currently externally undefined).
 * Indicate to our caller whether this process netted any more symbols.
 */
ldrand()
{
	register struct nlist *sp, **hp;
	register struct ranlib *tp, *tplast;
	off_t loc;
	int nsymt = symx(nextsym);

	tplast = &tab[tnum-1];
	for (tp = tab; tp <= tplast; tp++) {
		if ((hp = slookup(tp->ran_un.ran_name)) == 0)
			continue;
		sp = *hp;
		if (sp->n_type != N_EXT+N_UNDF)
			continue;
		step(tp->ran_off);
		loc = tp->ran_off;
		while (tp < tplast && (tp+1)->ran_off == loc)
			tp++;
	}
	return (symx(nextsym) != nsymt);
}

/*
 * Examine a single file or archive member on pass 1.
 */
load1(libflg, loc)
	off_t loc;
{
	register struct nlist *sp;
	struct nlist *savnext;
	int ndef, nlocal, type, size, nsymt;
	register int i;
	off_t maxoff;
	struct stat stb;

	readhdr(loc);
	if (filhdr.a_syms == 0) {
		if (filhdr.a_text+filhdr.a_data == 0)
			return (0);
		error(1, "no namelist");
	}
	if (libflg)
		maxoff = atol(archdr.ar_size);
	else {
		fstat(infil, &stb);
		maxoff = stb.st_size;
	}
	if (N_STROFF(filhdr) + sizeof (off_t) >= maxoff)
		error(1, "too small (old format .o?)");
	ctrel = tsize; cdrel += dsize; cbrel += bsize;
	ndef = 0;
	nlocal = sizeof(cursym);
	savnext = nextsym;
	loc += N_SYMOFF(filhdr);
	dseek(&text, loc, filhdr.a_syms);
	dseek(&reloc, loc + filhdr.a_syms, sizeof(off_t));
	mget(&size, sizeof (size), &reloc);
	dseek(&reloc, loc + filhdr.a_syms+sizeof (off_t), size-sizeof (off_t));
	curstr = (char *)malloc(size);
	if (curstr == NULL)
		error(1, "no space for string table");
	mget(curstr+sizeof(off_t), size-sizeof(off_t), &reloc);
	while (text.size > 0) {
		mget((char *)&cursym, sizeof(struct nlist), &text);
		if (cursym.n_un.n_strx) {
			if (cursym.n_un.n_strx<sizeof(size) ||
			    cursym.n_un.n_strx>=size)
				error(1, "bad string table index (pass 1)");
			cursym.n_un.n_name = curstr + cursym.n_un.n_strx;
		}
		type = cursym.n_type;
		if ((type&N_EXT)==0) {
			if (Xflag==0 || cursym.n_un.n_name[0]!='L' ||
			    type & N_STAB)
				nlocal += sizeof cursym;
			continue;
		}
		symreloc();
		if (enter(lookup()))
			continue;
		if ((sp = lastsym)->n_type != N_EXT+N_UNDF)
			continue;
		if (cursym.n_type == N_EXT+N_UNDF) {
			if (cursym.n_value > sp->n_value)
				sp->n_value = cursym.n_value;
			continue;
		}
		if (sp->n_value != 0 && cursym.n_type == N_EXT+N_TEXT)
			continue;
		ndef++;
		sp->n_type = cursym.n_type;
		sp->n_value = cursym.n_value;
	}
	if (libflg==0 || ndef) {
		tsize += filhdr.a_text;
		dsize += round(filhdr.a_data, sizeof (long));
		bsize += round(filhdr.a_bss, sizeof (long));
		ssize += nlocal;
		trsize += filhdr.a_trsize;
		drsize += filhdr.a_drsize;
		if (funding)
			textbase = (*slookup("_end"))->n_value;
		nsymt = symx(nextsym);
		for (i = symx(savnext); i < nsymt; i++) {
			sp = xsym(i);
			sp->n_un.n_name = savestr(sp->n_un.n_name);
		}
		free(curstr);
		return (1);
	}
	/*
	 * No symbols defined by this library member.
	 * Rip out the hash table entries and reset the symbol table.
	 */
	symfree(savnext);
	free(curstr);
	return(0);
}

middle()
{
	register struct nlist *sp;
	long csize, t, corigin, ocsize;
	int nund, rnd;
	char s;
	register int i;
	int nsymt;

	torigin = 0; 
	dorigin = 0; 
	borigin = 0;

	p_etext = *slookup("_etext");
	p_edata = *slookup("_edata");
	p_end = *slookup("_end");
	/*
	 * If there are any undefined symbols, save the relocation bits.
	 */
	nsymt = symx(nextsym);
	if (rflag==0) {
		for (i = 0; i < nsymt; i++) {
			sp = xsym(i);
			if (sp->n_type==N_EXT+N_UNDF && sp->n_value==0 &&
			    sp!=p_end && sp!=p_edata && sp!=p_etext) {
				rflag++;
				dflag = 0;
				break;
			}
		}
	}
	if (rflag) 
		sflag = zflag = 0;
	/*
	 * Assign common locations.
	 */
	csize = 0;
	if (!Aflag)
		addsym = symseg[0].sy_first;
	database = round(tsize+textbase,
	    (nflag||zflag? PAGSIZ : sizeof (long)));
	database += hsize;
	if (dflag || rflag==0) {
		ldrsym(p_etext, tsize, N_EXT+N_TEXT);
		ldrsym(p_edata, dsize, N_EXT+N_DATA);
		ldrsym(p_end, bsize, N_EXT+N_BSS);
		for (i = symx(addsym); i < nsymt; i++) {
			sp = xsym(i);
			if ((s=sp->n_type)==N_EXT+N_UNDF &&
			    (t = sp->n_value)!=0) {
				if (t >= sizeof (double))
					rnd = sizeof (double);
				else if (t >= sizeof (long))
					rnd = sizeof (long);
				else
					rnd = sizeof (short);
				csize = round(csize, rnd);
				sp->n_value = csize;
				sp->n_type = N_EXT+N_COMM;
				ocsize = csize;	
				csize += t;
			}
			if (s&N_EXT && (s&N_TYPE)==N_UNDF && s&N_STAB) {
				sp->n_value = ocsize;
				sp->n_type = (s&N_STAB) | (N_EXT+N_COMM);
			}
		}
	}
	/*
	 * Now set symbols to their final value
	 */
	csize = round(csize, sizeof (long));
	torigin = textbase;
	dorigin = database;
	corigin = dorigin + dsize;
	borigin = corigin + csize;
	nund = 0;
	nsymt = symx(nextsym);
	for (i = symx(addsym); i<nsymt; i++) {
		sp = xsym(i);
		switch (sp->n_type & (N_TYPE+N_EXT)) {

		case N_EXT+N_UNDF:
			if (arflag == 0)
				errlev |= 01;
			if ((arflag==0 || dflag) && sp->n_value==0) {
				if (sp==p_end || sp==p_etext || sp==p_edata)
					continue;
				if (nund==0)
					printf("Undefined:\n");
				nund++;
				printf("%s\n", sp->n_un.n_name);
			}
			continue;
		case N_EXT+N_ABS:
		default:
			continue;
		case N_EXT+N_TEXT:
			sp->n_value += torigin;
			continue;
		case N_EXT+N_DATA:
			sp->n_value += dorigin;
			continue;
		case N_EXT+N_BSS:
			sp->n_value += borigin;
			continue;
		case N_EXT+N_COMM:
			sp->n_type = (sp->n_type & N_STAB) | (N_EXT+N_BSS);
			sp->n_value += corigin;
			continue;
		}
	}
	if (sflag || xflag)
		ssize = 0;
	bsize += csize;
	nsym = ssize / (sizeof cursym);
	if (Aflag) {
		fixspec(p_etext,torigin);
		fixspec(p_edata,dorigin);
		fixspec(p_end,borigin);
	}
}

fixspec(sym,offset)
	struct nlist *sym;
	long offset;
{

	if(symx(sym) < symx(addsym) && sym!=0)
		sym->n_value += offset;
}

ldrsym(sp, val, type)
	register struct nlist *sp;
	long val;
{

	if (sp == 0)
		return;
	if ((sp->n_type != N_EXT+N_UNDF || sp->n_value) && !Aflag) {
		printf("%s: ", sp->n_un.n_name);
		error(0, "user attempt to redfine loader-defined symbol");
		return;
	}
	sp->n_type = type;
	sp->n_value = val;
}

off_t	wroff;
struct	biobuf toutb;

setupout()
{
	int bss;
	extern char *sys_errlist[];
	extern int errno;

	ofilemode = 0777 & ~umask(0);
	biofd = creat(ofilename, 0666 & ofilemode);
	if (biofd < 0) {
		filname = ofilename;		/* kludge */
		archdr.ar_name[0] = 0;		/* kludge */
		error(1, sys_errlist[errno]);	/* kludge */
	} else {
		struct stat mybuf;		/* kls kludge */
		fstat(biofd, &mybuf);		/* suppose file exists, wrong*/
		if(mybuf.st_mode & 0111) {	/* mode, ld fails? */
			chmod(ofilename, mybuf.st_mode & 0666);
			ofilemode = mybuf.st_mode;
		}
	}
	tout = &toutb;
	bopen(tout, 0);
	filhdr.a_magic = nflag ? NMAGIC : (zflag ? ZMAGIC : OMAGIC);
	filhdr.a_text = nflag ? tsize :
	    round(tsize, zflag ? PAGSIZ : sizeof (long));
	filhdr.a_data = zflag ? round(dsize, PAGSIZ) : dsize;
	bss = bsize - (filhdr.a_data - dsize);
	if (bss < 0)
		bss = 0;
	filhdr.a_bss = bss;
	filhdr.a_trsize = trsize;
	filhdr.a_drsize = drsize;
	filhdr.a_syms = sflag? 0: (ssize + (sizeof cursym)*symx(nextsym));
	if (entrypt) {
		if (entrypt->n_type!=N_EXT+N_TEXT)
			error(0, "entry point not in text");
		else
			filhdr.a_entry = entrypt->n_value;
	} else
		filhdr.a_entry = 0;
	filhdr.a_trsize = (rflag ? trsize:0);
	filhdr.a_drsize = (rflag ? drsize:0);
	bwrite((char *)&filhdr, sizeof (filhdr), tout);
	if (zflag) {
		bflush1(tout);
		biobufs = 0;
		bopen(tout, PAGSIZ);
	}
	wroff = N_TXTOFF(filhdr) + filhdr.a_text;
	outb(&dout, filhdr.a_data);
	if (rflag) {
		outb(&trout, filhdr.a_trsize);
		outb(&drout, filhdr.a_drsize);
	}
	if (sflag==0 || xflag==0) {
		outb(&sout, filhdr.a_syms);
		wroff += sizeof (offset);
		outb(&strout, 0);
	}
}

outb(bp, inc)
	register struct biobuf **bp;
{

	*bp = (struct biobuf *)malloc(sizeof (struct biobuf));
	if (*bp == 0)
		error(1, "ran out of memory (outb)");
	bopen(*bp, wroff);
	wroff += inc;
}

load2arg(acp)
char *acp;
{
	register char *cp;
	off_t loc;

	cp = acp;
	if (getfile(cp) == 0) {
		while (*cp)
			cp++;
		while (cp >= acp && *--cp != '/');
		mkfsym(++cp);
		load2(0L);
	} else {	/* scan archive members referenced */
		for (;;) {
			if (clibseg->li_used2 == clibseg->li_used) {
				if (clibseg->li_used < NROUT)
					error(1, "libseg botch");
				clibseg++;
			}
			loc = clibseg->li_first[clibseg->li_used2++];
			if (loc == -1)
				break;
			dseek(&text, loc, (long)sizeof(archdr));
			getarhdr();
			mkfsym(archdr.ar_name);
			load2(loc + (long)sizeof(archdr));
		}
	}
	close(infil);
}

load2(loc)
long loc;
{
	int size;
	register struct nlist *sp;
	register struct local *lp;
	register int symno, i;
	int type;

	readhdr(loc);
	if (!funding) {
		ctrel = torigin;
		cdrel += dorigin;
		cbrel += borigin;
	}
	/*
	 * Reread the symbol table, recording the numbering
	 * of symbols for fixing external references.
	 */
	for (i = 0; i < LHSIZ; i++)
		lochash[i] = 0;
	clocseg = locseg;
	clocseg->lo_used = 0;
	symno = -1;
	loc += N_TXTOFF(filhdr);
	dseek(&text, loc+filhdr.a_text+filhdr.a_data+
		filhdr.a_trsize+filhdr.a_drsize+filhdr.a_syms, sizeof(off_t));
	mget(&size, sizeof(size), &text);
	dseek(&text, loc+filhdr.a_text+filhdr.a_data+
		filhdr.a_trsize+filhdr.a_drsize+filhdr.a_syms+sizeof(off_t),
		size - sizeof(off_t));
	curstr = (char *)malloc(size);
	if (curstr == NULL)
		error(1, "out of space reading string table (pass 2)");
	mget(curstr+sizeof(off_t), size-sizeof(off_t), &text);
	dseek(&text, loc+filhdr.a_text+filhdr.a_data+
		filhdr.a_trsize+filhdr.a_drsize, filhdr.a_syms);
	while (text.size > 0) {
		symno++;
		mget((char *)&cursym, sizeof(struct nlist), &text);
		if (cursym.n_un.n_strx) {
			if (cursym.n_un.n_strx<sizeof(size) ||
			    cursym.n_un.n_strx>=size)
				error(1, "bad string table index (pass 2)");
			cursym.n_un.n_name = curstr + cursym.n_un.n_strx;
		}
/* inline expansion of symreloc() */
		switch (cursym.n_type & 017) {

		case N_TEXT:
		case N_EXT+N_TEXT:
			cursym.n_value += ctrel;
			break;
		case N_DATA:
		case N_EXT+N_DATA:
			cursym.n_value += cdrel;
			break;
		case N_BSS:
		case N_EXT+N_BSS:
			cursym.n_value += cbrel;
			break;
		case N_EXT+N_UNDF:
			break;
		default:
			if (cursym.n_type&N_EXT)
				cursym.n_type = N_EXT+N_ABS;
		}
/* end inline expansion of symreloc() */
		type = cursym.n_type;
		if (yflag && cursym.n_un.n_name)
			for (i = 0; i < yflag; i++)
				/* fast check for 2d character! */
				if (ytab[i][1] == cursym.n_un.n_name[1] &&
				    !strcmp(ytab[i], cursym.n_un.n_name)) {
					tracesym();
					break;
				}
		if ((type&N_EXT) == 0) {
			if (!sflag&&!xflag&&
			    (!Xflag||cursym.n_un.n_name[0]!='L'||type&N_STAB))
				symwrite(&cursym, sout);
			continue;
		}
		if (funding)
			continue;
		if ((sp = *lookup()) == 0)
			error(1, "internal error: symbol not found");
		if (cursym.n_type == N_EXT+N_UNDF) {
			if (clocseg->lo_used == NSYMPR) {
				if (++clocseg == &locseg[NSEG])
					error(1, "local symbol overflow");
				clocseg->lo_used = 0;
			}
			if (clocseg->lo_first == 0) {
				clocseg->lo_first = (struct local *)
				    malloc(NSYMPR * sizeof (struct local));
				if (clocseg->lo_first == 0)
					error(1, "out of memory (clocseg)");
			}
			lp = &clocseg->lo_first[clocseg->lo_used++];
			lp->l_index = symno;
			lp->l_symbol = sp;
			lp->l_link = lochash[symno % LHSIZ];
			lochash[symno % LHSIZ] = lp;
			continue;
		}
		if (cursym.n_type & N_STAB)
			continue;
		if (cursym.n_type!=sp->n_type || cursym.n_value!=sp->n_value) {
			printf("%s: ", cursym.n_un.n_name);
			error(0, "multiply defined");
		}
	}
	if (funding)
		return;
	dseek(&text, loc, filhdr.a_text);
	dseek(&reloc, loc+filhdr.a_text+filhdr.a_data, filhdr.a_trsize);
	load2td(ctrel, torigin - textbase, tout, trout);
	dseek(&text, loc+filhdr.a_text, filhdr.a_data);
	dseek(&reloc, loc+filhdr.a_text+filhdr.a_data+filhdr.a_trsize,
	    filhdr.a_drsize);
	load2td(cdrel, dorigin - database, dout, drout);
	while (filhdr.a_data & (sizeof(long)-1)) {
		bputc(0, dout);
		filhdr.a_data++;
	}
	torigin += filhdr.a_text;
	dorigin += round(filhdr.a_data, sizeof (long));
	borigin += round(filhdr.a_bss, sizeof (long));
	free(curstr);
}

struct tynames {
	int	ty_value;
	char	*ty_name;
} tynames[] = {
	N_UNDF,	"undefined",
	N_ABS,	"absolute",
	N_TEXT,	"text",
	N_DATA,	"data",
	N_BSS,	"bss",
	N_COMM,	"common",
	0,	0,
};

tracesym()
{
	register struct tynames *tp;

	if (cursym.n_type & N_STAB)
		return;
	printf("%s", filname);
	if (archdr.ar_name[0])
		printf("(%s)", archdr.ar_name);
	printf(": ");
	if ((cursym.n_type&N_TYPE) == N_UNDF && cursym.n_value) {
		printf("definition of common %s size %d\n",
		    cursym.n_un.n_name, cursym.n_value);
		return;
	}
	for (tp = tynames; tp->ty_name; tp++)
		if (tp->ty_value == (cursym.n_type&N_TYPE))
			break;
	printf((cursym.n_type&N_TYPE) ? "definition of" : "reference to");
	if (cursym.n_type&N_EXT)
		printf(" external");
	if (tp->ty_name)
		printf(" %s", tp->ty_name);
	printf(" %s\n", cursym.n_un.n_name);
}

/*
 * This routine relocates the single text or data segment argument.
 * Offsets from external symbols are resolved by adding the value
 * of the external symbols.  Non-external reference are updated to account
 * for the relative motion of the segments (ctrel, cdrel, ...).  If
 * a relocation was pc-relative, then we update it to reflect the
 * change in the positioning of the segments by adding the displacement
 * of the referenced segment and subtracting the displacement of the
 * current segment (creloc).
 *
 * If we are saving the relocation information, then we increase
 * each relocation datum address by our base position in the new segment.
 */
load2td(creloc, position, b1, b2)
	long creloc, offset;
	struct biobuf *b1, *b2;
{
	register struct nlist *sp;
	register struct local *lp;
	long tw;
	register struct relocation_info *rp, *rpend;
	struct relocation_info *relp;
	char *codep;
	register char *cp;
	int relsz, codesz;

	relsz = reloc.size;
	relp = (struct relocation_info *)malloc(relsz);
	codesz = text.size;
	codep = (char *)malloc(codesz);
	if (relp == 0 || codep == 0)
		error(1, "out of memory (load2td)");
	mget((char *)relp, relsz, &reloc);
	rpend = &relp[relsz / sizeof (struct relocation_info)];
	mget(codep, codesz, &text);
	for (rp = relp; rp < rpend; rp++) {
		cp = codep + rp->r_address;
		/*
		 * Pick up previous value at location to be relocated.
		 */
		switch (rp->r_length) {

		case 0:		/* byte */
			tw = *cp;
			break;

		case 1:		/* word */
			tw = *(short *)cp;
			break;

		case 2:		/* long */
			tw = *(long *)cp;
			break;

		default:
			error(1, "load2td botch: bad length");
		}
		/*
		 * If relative to an external which is defined,
		 * resolve to a simpler kind of reference in the
		 * result file.  If the external is undefined, just
		 * convert the symbol number to the number of the
		 * symbol in the result file and leave it undefined.
		 */
		if (rp->r_extern) {
			/*
			 * Search the hash table which maps local
			 * symbol numbers to symbol tables entries
			 * in the new a.out file.
			 */
			lp = lochash[rp->r_symbolnum % LHSIZ];
			while (lp->l_index != rp->r_symbolnum) {
				lp = lp->l_link;
				if (lp == 0)
					error(1, "local symbol botch");
			}
			sp = lp->l_symbol;
			if (sp->n_type == N_EXT+N_UNDF)
				rp->r_symbolnum = nsym+symx(sp);
			else {
				rp->r_symbolnum = sp->n_type & N_TYPE;
				tw += sp->n_value;
				rp->r_extern = 0;
			}
		} else switch (rp->r_symbolnum & N_TYPE) {
		/*
		 * Relocation is relative to the loaded position
		 * of another segment.  Update by the change in position
		 * of that segment.
		 */
		case N_TEXT:
			tw += ctrel;
			break;
		case N_DATA:
			tw += cdrel;
			break;
		case N_BSS:
			tw += cbrel;
			break;
		case N_ABS:
			break;
		default:
			error(1, "relocation format botch (symbol type))");
		}
		/*
		 * Relocation is pc relative, so decrease the relocation
		 * by the amount the current segment is displaced.
		 * (E.g if we are a relative reference to a text location
		 * from data space, we added the increase in the text address
		 * above, and subtract the increase in our (data) address
		 * here, leaving the net change the relative change in the
		 * positioning of our text and data segments.)
		 */
		if (rp->r_pcrel)
			tw -= creloc;
		/*
		 * Put the value back in the segment,
		 * while checking for overflow.
		 */
		switch (rp->r_length) {

		case 0:		/* byte */
			if (tw < -128 || tw > 127)
				error(0, "byte displacement overflow");
			*cp = tw;
			break;
		case 1:		/* word */
			/* if (tw < -32768 || tw > 32767)
				error(0, "word displacement overflow");
			 *** 8086 ***/
			*(short *)cp = tw;
			break;
		case 2:		/* long */
			*(long *)cp = tw;
			break;
		}
		/*
		 * If we are saving relocation information,
		 * we must convert the address in the segment from
		 * the old .o file into an address in the segment in
		 * the new a.out, by adding the position of our
		 * segment in the new larger segment.
		 */
		if (rflag)
			rp->r_address += position;
	}
	bwrite(codep, codesz, b1);
	if (rflag)
		bwrite(relp, relsz, b2);
	cfree((char *)relp);
	cfree(codep);
}

finishout()
{
	register int i;
	int nsymt;

	if (sflag==0) {
		nsymt = symx(nextsym);
		for (i = 0; i < nsymt; i++)
			symwrite(xsym(i), sout);
		bwrite(&offset, sizeof offset, sout);
	}
	if (!ofilfnd) {
		unlink("a.out");
		if (link("l.out", "a.out") < 0)
			error(1, "cannot move l.out to a.out");
		ofilename = "a.out";
	}
	delarg = errlev;
	delexit();
}

mkfsym(s)
char *s;
{

	if (sflag || xflag)
		return;
	cursym.n_un.n_name = s;
	cursym.n_type = N_TEXT;
	cursym.n_value = torigin;
	symwrite(&cursym, sout);
}

getarhdr()
{
	register char *cp;

	mget((char *)&archdr, sizeof archdr, &text);
	for (cp=archdr.ar_name; cp<&archdr.ar_name[sizeof(archdr.ar_name)];)
		if (*cp++ == ' ') {
			cp[-1] = 0;
			return;
		}
}

mget(loc, n, sp)
register STREAM *sp;
register char *loc;
{
	register char *p;
	register int take;

top:
	if (n == 0)
		return;
	if (sp->size && sp->nibuf) {
		p = sp->ptr;
		take = sp->size;
		if (take > sp->nibuf)
			take = sp->nibuf;
		if (take > n)
			take = n;
		n -= take;
		sp->size -= take;
		sp->nibuf -= take;
		sp->pos += take;
		do
			*loc++ = *p++;
		while (--take > 0);
		sp->ptr = p;
		goto top;
	}
	if (n > BUFSIZ) {
		take = n - n % DEV_BSIZE;
		lseek(infil, (sp->bno+1)*DEV_BSIZE, 0);
		if (take > sp->size || read(infil, loc, take) != take)
			error(1, "premature EOF");
		loc += take;
		n -= take;
		sp->size -= take;
		sp->pos += take;
		dseek(sp, (sp->bno+1+take/DEV_BSIZE)*DEV_BSIZE, -1);
		goto top;
	}
	*loc++ = get(sp);
	--n;
	goto top;
}

symwrite(sp, bp)
	struct nlist *sp;
	struct biobuf *bp;
{
	register int len;
	register char *str;

	str = sp->n_un.n_name;
	if (str) {
		sp->n_un.n_strx = offset;
		len = strlen(str) + 1;
		bwrite(str, len, strout);
		offset += len;
	}
	bwrite(sp, sizeof (*sp), bp);
	sp->n_un.n_name = str;
}

dseek(sp, loc, s)
register STREAM *sp;
long loc, s;
{
	register PAGE *p;
	register b, o;
	int n;

	b = loc>>DEV_BSHIFT;
	o = loc&DEV_BMASK;
	if (o&01)
		error(1, "loader error; odd offset");
	--sp->pno->nuser;
	if ((p = &page[0])->bno!=b && (p = &page[1])->bno!=b)
		if (p->nuser==0 || (p = &page[0])->nuser==0) {
			if (page[0].nuser==0 && page[1].nuser==0)
				if (page[0].bno < page[1].bno)
					p = &page[0];
			p->bno = b;
			lseek(infil, loc & ~(long)DEV_BMASK, 0);
			if ((n = read(infil, p->buff, sizeof(p->buff))) < 0)
				n = 0;
			p->nibuf = n;
	} else
		error(1, "botch: no pages");
	++p->nuser;
	sp->bno = b;
	sp->pno = p;
	if (s != -1) {sp->size = s; sp->pos = 0;}
	sp->ptr = (char *)(p->buff + o);
	if ((sp->nibuf = p->nibuf-o) <= 0)
		sp->size = 0;
}

char
get(asp)
STREAM *asp;
{
	register STREAM *sp;

	sp = asp;
	if ((sp->nibuf -= sizeof(char)) < 0) {
		dseek(sp, ((long)(sp->bno+1)<<DEV_BSHIFT), (long)-1);
		sp->nibuf -= sizeof(char);
	}
	if ((sp->size -= sizeof(char)) <= 0) {
		if (sp->size < 0)
			error(1, "premature EOF");
		++fpage.nuser;
		--sp->pno->nuser;
		sp->pno = (PAGE *) &fpage;
	}
	sp->pos += sizeof(char);
	return(*sp->ptr++);
}

getfile(acp)
char *acp;
{
	register char *cp;
	register int c;
	char arcmag[SARMAG+1];
	struct stat stb;

	cp = acp; 
	infil = -1;
	archdr.ar_name[0] = '\0';
	filname = cp;
	if (cp[0]=='-' && cp[1]=='l') {
		char *locfilname = "/usr/local/lib/libxxxxxxxxxxxxxxx";
		if(cp[2] == '\0')
			cp = "-la";
		filname = "/usr/lib/libxxxxxxxxxxxxxxx";
		for(c=0; cp[c+2]; c++) {
			filname[c+12] = cp[c+2];
			locfilname[c+18] = cp[c+2];
		}
		filname[c+12] = locfilname[c+18] = '.';
		filname[c+13] = locfilname[c+19] = 'a';
		filname[c+14] = locfilname[c+20] = '\0';
		if ((infil = open(filname+4, 0)) >= 0) {
			filname += 4;
		} else if ((infil = open(filname, 0)) < 0) {
			filname = locfilname;
		}
	}
	if (infil == -1 && (infil = open(filname, 0)) < 0)
		error(1, "cannot open");
	page[0].bno = page[1].bno = -1;
	page[0].nuser = page[1].nuser = 0;
	text.pno = reloc.pno = (PAGE *) &fpage;
	fpage.nuser = 2;
	dseek(&text, 0L, SARMAG);
	if (text.size <= 0)
		error(1, "premature EOF");
	mget((char *)arcmag, SARMAG, &text);
	arcmag[SARMAG] = 0;
	if (strcmp(arcmag, ARMAG))
		return (0);
	dseek(&text, SARMAG, sizeof archdr);
	if(text.size <= 0)
		return (1);
	getarhdr();
	if (strncmp(archdr.ar_name, "__.SYMDEF", sizeof(archdr.ar_name)) != 0)
		return (1);
	fstat(infil, &stb);
	return (stb.st_mtime > atol(archdr.ar_date) ? 3 : 2);
}

struct nlist **
lookup()
{
	register int sh; 
	register struct nlist **hp;
	register char *cp, *cp1;
	register struct symseg *gp;
	register int i;

	sh = 0;
	for (cp = cursym.n_un.n_name; *cp;)
		sh = (sh<<1) + *cp++;
	sh = (sh & 0x7fffffff) % HSIZE;
	for (gp = symseg; gp < &symseg[NSEG]; gp++) {
		if (gp->sy_first == 0) {
			gp->sy_first = (struct nlist *)
			    calloc(NSYM, sizeof (struct nlist));
			gp->sy_hfirst = (struct nlist **)
			    calloc(HSIZE, sizeof (struct nlist *));
			if (gp->sy_first == 0 || gp->sy_hfirst == 0)
				error(1, "ran out of space for symbol table");
			gp->sy_last = gp->sy_first + NSYM;
			gp->sy_hlast = gp->sy_hfirst + HSIZE;
		}
		if (gp > csymseg)
			csymseg = gp;
		hp = gp->sy_hfirst + sh;
		i = 1;
		do {
			if (*hp == 0) {
				if (gp->sy_used == NSYM)
					break;
				return (hp);
			}
			cp1 = (*hp)->n_un.n_name; 
			for (cp = cursym.n_un.n_name; *cp == *cp1++;)
				if (*cp++ == 0)
					return (hp);
			hp += i;
			i += 2;
			if (hp >= gp->sy_hlast)
				hp -= HSIZE;
		} while (i < HSIZE);
		if (i > HSIZE)
			error(1, "hash table botch");
	}
	error(1, "symbol table overflow");
	/*NOTREACHED*/
}

symfree(saved)
	struct nlist *saved;
{
	register struct symseg *gp;
	register struct nlist *sp;

	for (gp = csymseg; gp >= symseg; gp--, csymseg--) {
		sp = gp->sy_first + gp->sy_used;
		if (sp == saved) {
			nextsym = sp;
			return;
		}
		for (sp--; sp >= gp->sy_first; sp--) {
			gp->sy_hfirst[sp->n_hash] = 0;
			gp->sy_used--;
			if (sp == saved) {
				nextsym = sp;
				return;
			}
		}
	}
	if (saved == 0)
		return;
	error(1, "symfree botch");
}

struct nlist **
slookup(s)
	char *s;
{

	cursym.n_un.n_name = s;
	cursym.n_type = N_EXT+N_UNDF;
	cursym.n_value = 0;
	return (lookup());
}

enter(hp)
register struct nlist **hp;
{
	register struct nlist *sp;

	if (*hp==0) {
		if (hp < csymseg->sy_hfirst || hp >= csymseg->sy_hlast)
			error(1, "enter botch");
		*hp = lastsym = sp = csymseg->sy_first + csymseg->sy_used;
		csymseg->sy_used++;
		sp->n_un.n_name = cursym.n_un.n_name;
		sp->n_type = cursym.n_type;
		sp->n_hash = hp - csymseg->sy_hfirst;
		sp->n_value = cursym.n_value;
		nextsym = lastsym + 1;
		return(1);
	} else {
		lastsym = *hp;
		return(0);
	}
}

symx(sp)
	struct nlist *sp;
{
	register struct symseg *gp;

	if (sp == 0)
		return (0);
	for (gp = csymseg; gp >= symseg; gp--)
		/* <= is sloppy so nextsym will always work */
		if (sp >= gp->sy_first && sp <= gp->sy_last)
			return ((gp - symseg) * NSYM + sp - gp->sy_first);
	error(1, "symx botch");
	/*NOTREACHED*/
}

symreloc()
{
	if(funding) return;
	switch (cursym.n_type & 017) {

	case N_TEXT:
	case N_EXT+N_TEXT:
		cursym.n_value += ctrel;
		return;

	case N_DATA:
	case N_EXT+N_DATA:
		cursym.n_value += cdrel;
		return;

	case N_BSS:
	case N_EXT+N_BSS:
		cursym.n_value += cbrel;
		return;

	case N_EXT+N_UNDF:
		return;

	default:
		if (cursym.n_type&N_EXT)
			cursym.n_type = N_EXT+N_ABS;
		return;
	}
}

error(n, s)
char *s;
{

	if (errlev==0)
		printf("ld86:");
	if (filname) {
		printf("%s", filname);
		if (n != -1 && archdr.ar_name[0])
			printf("(%s)", archdr.ar_name);
		printf(": ");
	}
	printf("%s\n", s);
	if (n == -1)
		return;
	if (n)
		delexit();
	errlev = 2;
}

readhdr(loc)
off_t loc;
{

	dseek(&text, loc, (long)sizeof(filhdr));
	mget((short *)&filhdr, sizeof(filhdr), &text);
	if (N_BADMAG(filhdr)) {
		if (filhdr.a_magic == OARMAG)
			error(1, "old archive");
		error(1, "bad magic number");
	}
	if (filhdr.a_text&01 || filhdr.a_data&01)
		error(1, "text/data size odd");
	if (filhdr.a_magic == NMAGIC || filhdr.a_magic == ZMAGIC) {
		cdrel = -round(filhdr.a_text, PAGSIZ);
		cbrel = cdrel - filhdr.a_data;
	} else if (filhdr.a_magic == OMAGIC) {
		cdrel = -filhdr.a_text;
		cbrel = cdrel - filhdr.a_data;
	} else
		error(1, "bad format");
}

round(v, r)
	int v;
	u_long r;
{

	r--;
	v += r;
	v &= ~(long)r;
	return(v);
}

#define	NSAVETAB	8192
char	*savetab;
int	saveleft;

char *
savestr(cp)
	register char *cp;
{
	register int len;

	len = strlen(cp) + 1;
	if (len > saveleft) {
		saveleft = NSAVETAB;
		if (len > saveleft)
			saveleft = len;
		savetab = (char *)malloc(saveleft);
		if (savetab == 0)
			error(1, "ran out of memory (savestr)");
	}
	strncpy(savetab, cp, len);
	cp = savetab;
	savetab += len;
	saveleft -= len;
	return (cp);
}

bopen(bp, off)
	struct biobuf *bp;
{

	bp->b_ptr = bp->b_buf;
	bp->b_nleft = BUFSIZ - off % BUFSIZ;
	bp->b_off = off;
	bp->b_link = biobufs;
	biobufs = bp;
}

int	bwrerror;

bwrite(p, cnt, bp)
	register char *p;
	register int cnt;
	register struct biobuf *bp;
{
	register int put;
	register char *to;

top:
	if (cnt == 0)
		return;
	if (bp->b_nleft) {
		put = bp->b_nleft;
		if (put > cnt)
			put = cnt;
		bp->b_nleft -= put;
		to = bp->b_ptr;
		asm("movc3 r8,(r11),(r7)");
		bp->b_ptr += put;
		p += put;
		cnt -= put;
		goto top;
	}
	if (cnt >= BUFSIZ) {
		if (bp->b_ptr != bp->b_buf)
			bflush1(bp);
		put = cnt - cnt % BUFSIZ;
		if (boffset != bp->b_off)
			lseek(biofd, bp->b_off, 0);
		if (write(biofd, p, put) != put) {
			bwrerror = 1;
			error(1, "output write error");
		}
		bp->b_off += put;
		boffset = bp->b_off;
		p += put;
		cnt -= put;
		goto top;
	}
	bflush1(bp);
	goto top;
}

bflush()
{
	register struct biobuf *bp;

	if (bwrerror)
		return;
	for (bp = biobufs; bp; bp = bp->b_link)
		bflush1(bp);
}

bflush1(bp)
	register struct biobuf *bp;
{
	register int cnt = bp->b_ptr - bp->b_buf;

	if (cnt == 0)
		return;
	if (boffset != bp->b_off)
		lseek(biofd, bp->b_off, 0);
	if (write(biofd, bp->b_buf, cnt) != cnt) {
		bwrerror = 1;
		error(1, "output write error");
	}
	bp->b_off += cnt;
	boffset = bp->b_off;
	bp->b_ptr = bp->b_buf;
	bp->b_nleft = BUFSIZ;
}

bflushc(bp, c)
	register struct biobuf *bp;
{

	bflush1(bp);
	bputc(c, bp);
}
rerror)
		return;
	for (bp = biobufs; bp; bp = bp->b_link)
		bflush1(bp);
}

bflush1(bp)
	register struct biobuf *bp;
{
	register int cnt = bp->b_ptr - bp->b_buf;

	if (cnt == 0)
		return;
	if (boffset != bp->b_off)
		lseek(biofd, bp->b_off, 0);
	if (write(biofd, bp->b_buf, cnt) != cnt) a86/ps.c                                                                                               444      26      12         7756  2733665330   5270                                                                                                                                                                                                                                                                                                                                                                      #include "mical.h"

End()
  {	register int i;
	register struct csect *p;

/* Pass 2 */
	if (Pass > 1) {				/* On the second pass, */
		Fix_Rel();			/* patch up object file */
		return; }

/* Pass 1 */
	fseek(stdin,0L,0);

	sdi_resolve();	/* resolve span dependent instructions */

	for (p = &Csects[0], i=0; i < Csect_load; i++, p++)
		p->len_cs += sdi_inc(p, p->len_cs);

	tsize = (Text_csect->len_cs + 1) & ~1;
	dsize = (Data_csect->len_cs + 1) & ~1;	/* make word aligned */
	bsize = (Bss_csect->len_cs + 1) & ~1;

	Sym_Fix();	/* relocate and globalize */
	sdi_free();	/* release sdi blocks */
	Rel_Header();	/* Initialize output stuff */
	Start_Pass();	/* Init per-pass variables */
	return;
}

/* Initialize per-pass variables */

Start_Pass()
 {	register int i;

	Last_symbol = Dot_bkt;	/* last defined symbol at start of pass */
	Line_no = 0;
	Errors = 0;
	Pass++;
	if (Pass != 2) for (i=0; i<Csect_load; i++) Csects[i].dot_cs = 0;
	else {
	  Text_csect->dot_cs = 0;
	  Data_csect->dot_cs = tsize;
	  Bss_csect->dot_cs = tsize + dsize;
	}
	New_Csect(&Csects[0]);	/* start in text segment */
}

/*
 * .even handler
 */
Even()
{
	if (Dot&1) {
		Dot++;
		Code[0] = 0;
		Put_Text(Code,1);
	}
}

ByteWord(Which)
  register int Which;
  {	register int i;
	register struct oper *p;
	char temp;

	for (i=0, p=operands; i < numops; i++, p++) {
	  if (!(p->type_o==t_norm || p->type_o==t_sxt)) {
	    p->sym_o = 0;
	    p->type_o = t_norm;
	    p->value_o = 0;
	    Prog_Error(E_OPERAND);
	  } else if (p->sym_o) Put_Rel(p,Which,Dot+BC,0);

	  switch (Which) {
	    case L:	WCode[1] = p->value_o >> 16;
			WCode[0] = p->value_o;
			Put_Text(WCode,4);
			BC += 4;
			break;

	    case W:	WCode[0] = p->value_o;
	  		Put_Text(WCode,2);
			BC += 2;
			break;

	    case B:	temp = p->value_o;
			Put_Text(&temp,1);
			BC++;
			break;
	  }
	}
}

/* handle .ascii and .asciz pseudo ops -- zero<>0 indicates that
 * user wants zero byte at end of string.
 */
Ascii(zero)
  {	register char *p;

	if (numops!=1 || operands[0].type_o!=t_string)
	  { Prog_Error(E_OPERAND); return; }
	p = (char *)operands[0].value_o;
	while (*p) { Put_Text(p++,1); BC++; }
	if (zero) { Put_Text(p,1); BC++; }
}	

/* .zerow -- initialize specified number of words to 0 */
Zerow()
  {	register int i;
	short zero = 0;

	if (numops!=1 || operands[0].type_o!=t_norm || operands[0].sym_o!=NULL)
	  { Prog_Error(E_OPERAND); return; }
	for (i = operands[0].value_o; i > 0; i--) {
	  Put_Text(&zero,2);
	  BC += 2;
	}
}	

struct csect Csects[CSECT_MAX] = {
  ".text",0,0,0,R_ISPC|R_PURE,	/* text csect */
  ".data",0,0,0,0,		/* data csect */
  ".bss",0,0,0,0		/* uninitialized csect */
} ;

int Csect_load = 4;			/* Next available csect in Csects[] */
struct csect *Cur_csect = &(Csects[0]);	/* ptr to current csect */
struct csect *Text_csect = &(Csects[0]);
struct csect *Data_csect = &(Csects[1]);
struct csect *Bss_csect = &(Csects[2]);

New_Csect(csp)
  register struct csect *csp;
  {	register struct sym_bkt *sbp;	/* for defining new symbol */
	extern struct csect *Cur_csect;	/* ptr to current csect */
	extern struct sym_bkt	*Last_symbol;	/* used for local symbols */
	extern struct sym_bkt	*Dot_bkt;	/* sym_bkt for location counter */
	
	Cur_csect = csp;
	Dot = csp->dot_cs;
	Dot_bkt->csect_s = Cur_csect;	/* update dot's csect. Dot_bkt->value_s will be updated in the main loop */

	sbp = Lookup(csp->name_cs);
	sbp->attr_s |= S_DEC | S_DEF | S_LOCAL;
	sbp->csect_s = Cur_csect;
	sbp->value_s = 0;
}

Globl()
  {	register int i;
	register struct sym_bkt *sbp;

	if (Pass == 1) for (i=0; i<numops; i++) {
	  sbp = operands[i].sym_o;
	  if (sbp == NULL) Prog_Error(E_SYMBOL);
	  else {
	    sbp->csect_s = 0;		/* don't know which */
	    sbp->attr_s |= S_DEC | S_EXT;	/* declared and external */
	  }
	}
	return;
}

Comm()
  {	register struct sym_bkt *sbp;

	if (Pass == 1) {
	  sbp = operands[0].sym_o;
	  if (sbp == NULL) Prog_Error(E_OPERAND);
	  else {
	    sbp->csect_s = 0;	/* make it undefined */
	    sbp->attr_s |= S_DEC | S_EXT | S_COMM;
	    sbp->value_s = operands[1].value_o;
	  }
	}
	return;
}
s; i++) {
	  sbp =a86/rel.c                                                                                              444      26      12        10062  2703135070   5416                                                                                                                                                                                                                                                                                                                                                                      #include "mical.h"
#include <a.out.h>

/*  Handle output file processing for a.out files */

FILE *tout;		/* text portion of output file */
FILE *dout;		/* data portion of output file */
FILE *rtout;		/* text relocation commands */
FILE *rdout;		/* data relocation commands */

long rtsize;		/* size of text relocation area */
long rdsize;		/* size of data relocation area */
long Sym_Write();

struct exec filhdr;	/* header for a.out files, contains sizes */

/* Initialize files for output and write out the header */

Rel_Header()
  {	char rname[STR_MAX];	/* name of file for relocation commands */

	if ((tout = fopen(Rel_name, "w")) == NULL ||
		(dout = fopen(Rel_name, "a")) == NULL)
		Sys_Error("open on output file %s failed", Rel_name);

	Concat(rname, Source_name, ".textr");
	rtout = fopen(rname, "w");
	Concat(rname, Source_name, ".datar");
	rdout = fopen(rname, "w");
	if (rtout == NULL || rdout == NULL)
	  Sys_Error("open on output file %s failed", rname);

	fseek(tout, (long)N_TXTOFF(filhdr), 0);	/* seek to start of text */
	fseek(dout, (long)N_TXTOFF(filhdr)+tsize, 0);	
	rtsize = 0;
	rdsize = 0;
}

/* Fix_Rel -	Fix up the object file */
Fix_Rel()
  {	register FILE *fin, *fout;
	register int i;
	char rname[STR_MAX];	/* name of file for relocation commands */

	fclose(rtout);
	fclose(rdout);
	fclose(tout);

	filhdr.a_magic = OMAGIC;
	filhdr.a_text = tsize;
	filhdr.a_data = dsize;
	filhdr.a_bss = bsize;
	filhdr.a_trsize = rtsize;
	filhdr.a_drsize = rdsize;
	filhdr.a_entry = 0;

	fseek(dout, (long)(N_TXTOFF(filhdr)+tsize+dsize), 0);

	Concat(rname, Source_name, ".textr");
	if ((fin = fopen(rname, "r")) == NULL)
		Sys_Error("cannot reopen relocation file %s", rname);
	while ((i = getc(fin)) != EOF) putc(i,dout);
	fclose(fin);
	unlink(rname);

	Concat(rname, Source_name, ".datar");
	if ((fin = fopen(rname, "r")) == NULL)
		Sys_Error("cannot reopen relocation file %s", rname);
	while ((i = getc(fin)) != EOF) putc(i,dout);
	fclose(fin);
	unlink(rname);

	filhdr.a_syms = Sym_Write(dout);

	fseek(dout, 0L, 0);
	fwrite(&filhdr, sizeof(filhdr), 1, dout);
}

/* Put_Text -	Write out text to proper portion of file */
Put_Text(code,length)
 register char *code;
 {	if (Pass != 2) return;
	if (Cur_csect == Text_csect) fwrite(code, length, 1, tout);
	else if (Cur_csect == Data_csect) fwrite(code, length, 1, dout);
	else return;	/* ignore if bss segment */
 }

/* Pad_Text -	Write zero bytes to pad out proper portion of file */

Pad_Text(length)
 register length;
 {	register FILE *f;

	if (Pass != 2) return;
	if (Cur_csect == Text_csect) f = tout;
	else if (Cur_csect == Data_csect) f = dout;
	else return;	/* ignore if bss segment */
	while (length-- > 0)
		putc(0, f);
 }

/* set up relocation word for operand:
 *  opnd	pointer to operand structure
 *  size	0 = byte, 1 = word, 2 = long/address
 *  offset	offset into current segment
 */
Put_Rel(opnd,size,offset,pcrel)
struct oper *opnd;
int size;
long offset;
{	struct relocation_info r;

	if (opnd->sym_o == 0) return;	/* no relocation */
	if (Cur_csect == Text_csect)
		rtsize += rel_cmd(&r, opnd, size, offset, pcrel, rtout);
	else if (Cur_csect == Data_csect)
		rdsize += rel_cmd(&r, opnd, size, offset - tsize, pcrel, rdout);
	else return;	/* just ignore if bss segment */
}


/* rel_cmd -	Generate a relocation command and output */

rel_cmd(rp, opnd, size, offset, pcrel, file)
  register struct relocation_info *rp;
  struct oper *opnd;
  int size;
  long offset;
  FILE *file;
  {	int csid;			/* reloc csect identifier */
	register struct csect *csp;	/* pointer to csect of sym */
	register struct sym_bkt *sp;	/* pointer to symbol */

	sp = opnd->sym_o;
	csp = sp->csect_s;
	if (Pass == 2) {
		rp->r_address = offset;
		rp->r_pcrel = pcrel;
		rp->r_length = size;
		rp->r_extern = 0;
		if (!(sp->attr_s & S_DEF) && (sp->attr_s & S_EXT)) {
		  rp->r_extern = 1;
		  rp->r_symbolnum = sp->id_s;
		} else if (csp == Text_csect) rp->r_symbolnum = N_TEXT;
		else if (csp == Data_csect) rp->r_symbolnum = N_DATA;
		else if (csp == Bss_csect) rp->r_symbolnum = N_BSS;
		else Prog_Error(E_RELOCATE);
		fwrite(rp, sizeof *rp, 1, file);
	}
	return(sizeof *rp);
}
opnd->sym_o;
	csp = sp->csect_s;
	if (Pass == 2) {
		rp->r_address = offset;
		rp->r_pcrel = pcrel;
		rp->r_length = size;
		rp->r_extern = 0;
		if (!(sp->attr_s & S_DEF) && (sp->attr_s & S_EXT)) {
		  rp->r_extern = 1;
		  rp->r_symbolnum = sp->id_s;
		} else if (csp == Text_csect) rp->r_symbolnum = N_TEXT;
		else if (csp == Data_csect) rp->r_symbolnum = N_DATA;
		else if (csp == Bss_csect) rp->r_symbolnum = N_BSS;
		else Prog_Error(E_RELOCATE);
		fwrite(rpa86/rom86.c                                                                                            666      26      12        16437  3240351653   5635                                                                                                                                                                                                                                                                                                                                                                      #include <stdio.h>
#include <a.out.h>

/* convert a.out files into .com files for IBM Dos system */

/* Modified by LDS to provide -D option to specify relocation of data segment.
   The -O option specifies relocation of text segment (both use decimal).
   Default for text segment offset is 0x100; default for data segment is 0.
   These are the correct values for relocating an MSDOS .com file, assuming
   that the data segment register is set to the end of the code segment.
   If a negative value is specified for the data relocation, then relocation
   is done assuming that the data segment register will be equal to the
   code segment register, ie, the data will be relocated by the length
   of the code plus the relocation for the code.
*/

struct exec hdr;	/* header info from a.out file */

struct nlist *symtab;	/* pointer to symbol table */
FILE *infile;

long	Offset =     0x100;	/* base of text segment */
long	DataOffset = 0x000;	/* base of data segment */
long atol();

main(argc,argv)
  char **argv;
  {	register int i;
	register char *text,*strings;
	register struct nlist *s;
	int size;
	long string_size;
	char temp[100];

	while (*(text = argv[1]) == '-')
	 {
	   argv++; argc--; switch(*++text)
		{
		  case 'O':	Offset = atol(++text); continue;
		  case 'D':	DataOffset = atol(++text); continue;
		  default: fprintf(stderr, "Bad option %s\r\n", argv[0]);
			   exit(-1);
		}
	 }

	if (argc != 3) {
	  fprintf(stderr,"usage: rom86 <a.out file name> <.com file name>\n");
	  exit(1);
	}

	if ((infile = fopen(argv[1],"r")) == NULL) {
	  fprintf(stderr,"rom86: cannot open %s for input\n",argv[1]);
	  exit(1);
	}

	if (fread(&hdr,sizeof(hdr),1,infile) != 1) {
	  fprintf(stderr,"rom86: read of a.out header failed\n");
	  exit(1);
	}

	if (hdr.a_magic != OMAGIC) {
	  fprintf(stderr,"rom86: a.out file not in 0407 format\n");
	  exit(1);
	}

	if ((text = (char *)malloc(hdr.a_text + hdr.a_data)) == NULL ||
	    fread(text,1,hdr.a_text+hdr.a_data,infile) != hdr.a_text + hdr.a_data) {
	  fprintf(stderr,"rom86: setup failed for text and data\n");
	  exit(1);
	}

	if (DataOffset < 0)	/* Implies data segment equals code segment */
	    DataOffset = (hdr.a_text + 15 + Offset) & ~15;

	fseek(infile,N_SYMOFF(hdr),0);
	if ((symtab = (struct nlist *)malloc(hdr.a_syms)) == NULL ||
	    fread(symtab,1,hdr.a_syms,infile) != hdr.a_syms) {
	  fprintf(stderr,"rom86: setup failed for symbols\n");
	  exit(1);
	}

	fread(&string_size,sizeof(string_size),1,infile);
	if ((strings = (char *)malloc(string_size-4)) == NULL ||
	    fread(strings,1,string_size-4,infile) != string_size-4) {
	  fprintf(stderr,"rom86: setup failed for string data\n");
	  exit(1);
	}

	/* set up symbol string pointers, and define .comm symbols */
	for (i = hdr.a_syms/sizeof(struct nlist), s = symtab; i--; s++) {
	  if (s->n_un.n_strx != 0) s->n_un.n_name = &strings[s->n_un.n_strx-4];
	  if (s->n_type==(N_UNDF|N_EXT) && (size = s->n_value)!=0) {
	    s->n_value = hdr.a_data + hdr.a_bss;
	    s->n_type = N_BSS;
	    hdr.a_bss += size;
	  }
	}

	/* define _etext, _edata, and _end if user uses them */
	for (i = hdr.a_syms/sizeof(struct nlist), s = symtab; i--; s++)
	  if (s->n_type == (N_UNDF|N_EXT)) {
	    if (strcmp(s->n_un.n_name,"_etext") == 0) {
	      s->n_value = (hdr.a_text + 15 + Offset) & ~15;
	      s->n_type = N_TEXT;
	    } else if (strcmp(s->n_un.n_name,"_edata") == 0) {
	      s->n_value = hdr.a_data + DataOffset;
	      s->n_type = N_DATA;
	    } else if (strcmp(s->n_un.n_name,"_end") == 0) {
	      s->n_value = hdr.a_data + hdr.a_bss + DataOffset;
	      s->n_type = N_BSS;
	    }
	  }

	fseek(infile,N_TXTOFF(hdr)+hdr.a_text+hdr.a_data,0);

	/* do text relocation */
	relocate(hdr.a_trsize/sizeof(struct relocation_info), text);

	/* do data relocation */
	relocate(hdr.a_drsize/sizeof(struct relocation_info), &text[hdr.a_text]);

	size = hdr.a_text + hdr.a_data;
	strcpy(temp,argv[2]);
	strcat(temp,".low");
	romout(temp,text,size);

	strcpy(temp,argv[2]);
	strcat(temp,".high");
	romout(temp,&text[1],size);
}

#define outbyte(c,s,f)	s += ((c) & 0xFF);\
			putc(hex[((c)>>4)&0xF], f);\
			putc(hex[(c)&0xF], f)

#define outword(w,s,f)	outbyte((w)>>8, s, f);\
			outbyte((w), s, f)

char hex[] = "0123456789ABCDEF";	/* hex character set		*/

/* Output routines for writing standard records.
 * Format is
 *	;BBAAAAHHHHHHHH .... HHHHCCCC
 * where
 *	B :	length of record
 *	A :	address of memory
 *	H :	data bytes
 *	C :	checksum (includes the whole record)
 *
 * the last record is as follows
 *	;00RRRRCCCC
 * the byte count is zero. The address field contains
 * the number of records transferred.
 */
romout(fname,data,size)
  register char *fname,*data;
  register int size;
  {	register int i, j, k;
	int adr, xadr;
	int csum,rnum = 0;
	char buf[256];
	FILE *outp;

	if ((outp = fopen(fname,"w")) == NULL) {
	  fprintf(stderr,"rom86: cannot open %s for output\n",fname);
	  exit(1);
	}

	i = 0;
	adr = 0;
	while (i < size) {
	  xadr = adr;			
	  for (j=0; (i < size) && (j < 250); i += 2, adr++) buf[j++] = data[i];
	  csum = 0; putc(';', outp);	/* download command char */
	  outbyte(j, csum, outp);	/* record length	 */
	  outword(xadr, csum, outp);	/* start address	 */
	  for (k=0; k<j; k++) { outbyte(buf[k], csum, outp); }
	  outword(csum, k, outp);	/* checksum		 */
	  rnum++;
	}
	j = 0; putc(';', outp);			/* eof record		 */
	outbyte(0, j, outp);			/* zero bytes		 */
	outword(rnum, j, outp);			/* number of records	 */
	outword(j, k, outp);			/* checksum		 */
	fclose(outp);
}

/* process relocation commands */
relocate(ncmds,base)
  register int ncmds;
  register char *base;
  {	register struct nlist *s;
	struct relocation_info r;

	while (ncmds--) {
	  fread(&r,sizeof(r),1,infile);

/*	  fprintf(stderr,"addr = 0x%x, sym = %s (0x%x), pcrel = %d, length = %d, extern = %d\n",
		  r.r_address,symtab[r.r_symbolnum].n_un.n_name,r.r_symbolnum,
		  r.r_pcrel,r.r_length,r.r_extern);
*/
	  if (r.r_extern == 0) {
	    if (r.r_pcrel != 1) switch (r.r_symbolnum) {
	      case N_TEXT: put_word(&base[r.r_address],r.r_length,
			     get_word(&base[r.r_address],r.r_length) + Offset);
			   break;

	      case N_BSS:
	      case N_DATA: put_word(&base[r.r_address],r.r_length,
			     get_word(&base[r.r_address],r.r_length) 
					- hdr.a_text + DataOffset);
			   break;

	      default:	   fprintf(stderr,"rom86: strange csect %d\n",r.r_symbolnum);
			   break;
	    }
	  } else {
	    s = &symtab[r.r_symbolnum];

/*	    fprintf(stderr,"  relocation by symbol, value = 0x%0x\n",s->n_value);
*/
	    switch (s->n_type & N_TYPE) {
	      default:	fprintf(stderr,"rom86: relocation by undefined symbol %s ignored\n",
				s->n_un.n_name);
			break;

	      case N_ABS:
	      case N_TEXT:
	      case N_DATA:
	      case N_BSS:
			put_word(&base[r.r_address],r.r_length,
		   	  get_word(&base[r.r_address],r.r_length) + s->n_value);
			break;
	    }
	  }
	}
}

/* not portable! requires byte addressing to work for all sizes of operands */
int get_word(addr,size) 
  register char *addr;
  int size;
  {	switch (size) {
	  case 0:	return (*addr);

	  case 1:	return (*(short *)addr);

	  case 2:	return (*(long *)addr);
	}
}

/* not portable! requires byte addressing to work for all sizes of operands */
put_word(addr,size,value)
  register char *addr;
  int size, value;
  {	switch (size) {
	  case 0:	*addr = value; break;

	  case 1:	*(short *)addr = value; break;

	  case 2:	*(long *)addr = value; break;
	}
}
o work for all sizes of operands */
int get_word(addr,size) 
  register char *addr;
  int size;
  {	switch (size) {
	  case 0:	return (*addr);

	  case 1:	return (*(short *)addr);

	  case 2:	return (*(long *)addr);
	}
}

/* a86/scan.c                                                                                             444      26      12        30564  3115703341   5571                                                                                                                                                                                                                                                                                                                                                                      #include "mical.h"

/* process lines from source file, returns when EOF detected */

#define LSIZE	200	/* max size of input line */

/* small info table for each input character */
short cinfo[128] = {
	ERR,	ERR,	ERR,	ERR,	ERR,	ERR,	ERR,	ERR,
	ERR,	SPC,	EOL,	SPC,	SPC,	SPC,	ERR,	ERR,
	ERR,	ERR,	ERR,	ERR,	ERR,	ERR,	ERR,	ERR,
	ERR,	ERR,	ERR,	ERR,	ERR,	ERR,	ERR,	ERR,
	SPC,	ERR,	QUO,	IMM,	SOP,	ERR,	ERR,	CHR,
	LP,	RP,	MUL,	ADD,	COM,	SUB,	S+T,	DIV,
	D+T,	D+T,	D+T,	D+T,	D+T,	D+T,	D+T,	D+T,
	D+T,	D+T,	COL,	EOS,	ERR,	EQL,	ERR,	ERR,
	IND,	S+T,	S+T,	S+T,	S+T,	S+T,	S+T,	S+T,
	S+T,	S+T,	S+T,	S+T,	S+T,	S+T,	S+T,	S+T,
	S+T,	S+T,	S+T,	S+T,	S+T,	S+T,	S+T,	S+T,
	S+T,	S+T,	S+T,	ERR,	ERR,	ERR,	ERR,	S+T,
	ERR,	S+T,	S+T,	S+T,	S+T,	S+T,	S+T,	S+T,
	S+T,	S+T,	S+T,	S+T,	S+T,	S+T,	S+T,	S+T,
	S+T,	S+T,	S+T,	S+T,	S+T,	S+T,	S+T,	S+T,
	S+T,	S+T,	S+T,	ERR,	EOL,	ERR,	NOT,	S+T
};

char *sassign(),*sdefer(),*exp(),*term();
int slabel();

char iline[LSIZE];	/* current input line resides */
int Line_no;		/* current input line number */
char Code[CODE_MAX];	/* where generated code is stored */
long Dot;		/* offset in current csect */
int BC;			/* size of code for current line */
char segflag;		/* <>0 if segment prefix seen on current line */

main(argc,argv)
  char *argv[];
  {	Init(argc,argv);
	scan();
	End();
	scan();
	End();
	exit(Errors? -1: 0);
}

scan()
  {	register int i;
	register char *p;	/* pointer into input line */
	char *token;		/* pointer to beginning of last token */
	int opindex;		/* index of opcode on current line */
	extern char File_name[];

	while (fgets(iline,LSIZE,stdin) == iline) {

	/* handle info passed on by cpp */
	  if (iline[0] == '#') {
	    sscanf(iline,"# %d \"%[^\"]",&Line_no,File_name);
	    Line_no--;
	    continue;
	  }

	  Line_no++;
	  p = iline;
	  BC = 0;
	  Code_length = 0;

	  /* see what's the first thing on the line. if newline or comment
	   * char just ignore line all together.  if start of symbol see
	   * what follows.  otherwise error.
	   */
 restart: skipb(p);
	  i = cinfo[*p];	/* see what we know about next char */
	  if (i == EOS) { p++; goto restart; }
	  else if (i == EOL) continue;
	  else if (!(i & (S|D))) { Prog_Error(E_BADCHAR); continue; }

	  /* what follows is either label or opcode, gobble it up */
	  token = p;
	  skips(p);
	  skipb(p);
	  i = cinfo[*p];

	  /* if next char is ":", this is label definition */
	  if (i == COL) { p++; slabel(token); goto restart; }

	  /* if next char is "=", this is label assignment */
	  if (i == EQL) {
	    p = sassign(++p,token);
	    if ((i = cinfo[*p])!=EOL && i!=EOS) Prog_Error(E_BADCHAR);
	    goto restart;
	  }

	  /* otherwise this must be opcode, find its index */
	  if ((opindex = sopcode(token)) == 0) {
	    Prog_Error(E_OPCODE);
	    continue;
	  }

	  if (i==EOL || i==EOS) { numops = 0; goto doins; }

	  /* keep reading operands until we run out of room or hit EOL */
	  segflag = 0;
	  for (numops = 1; numops <= OPERANDS_MAX; numops++) {
	    p = soperand(p,&operands[numops-1]);
	    /* printop(&operands[numops-1]); */
	    skipb(p);
	    i = cinfo[*p];
	    if (i == COM) { p++; continue; }
	    if (i==EOL || i==EOS) goto doins;
	    Prog_Error(E_OPERAND);
	    goto next;
	  }
	  Prog_Error(E_NUMOPS);
  next:	  continue;

  doins:  BC = 0;
	  Instruction(opindex);
	  Dot += BC;
	  Cur_csect->dot_cs = Dot_bkt->value_s = Dot;
	  if (Dot > Cur_csect->len_cs) Cur_csect->len_cs = Dot;
	  goto restart;
	}
}

/* lookup token in opcode hash table, return 0 if not found */
int sopcode(token)
  register char *token;
  {	register char *p;
	register struct ins_bkt *ibp;
	char mnem[50];

	/* make asciz version of mnemonic */
	p = mnem;
	while (cinfo[*token] & T) *p++ = *token++;
	*p = 0;

	/* look through appropriate hash bucket */
	ibp = ins_hash_tab[Hash(mnem)];
	while (ibp) {
	  if (strcmp(ibp->text_i,mnem) == 0) return(ibp->code_i);
	  ibp = ibp->next_i;
	}

	return(0);
}

/* handle definition of label */
slabel(token)
  register char *token;
  {	register char *p;
	register struct sym_bkt *sbp;
	char lab[50];

	/* make asciz version of label */
	p = lab;
	while (cinfo[*token]&T || *token=='$') *p++ = *token++;
	*p = 0;

	/* find/enter symbol in the symbol table */
	sbp = Lookup(lab);

	/* on pass 1 look for multiply defined symbols.  if ok, label
	 * value is dot in current csect
	 */
	if (Pass==1) {
	  if (sbp->attr_s & (S_LABEL|S_REG)) Prog_Error(E_MULTSYM);
	  sbp->attr_s |= S_LABEL | S_DEC | S_DEF;
	  sbp->csect_s = Cur_csect;
	  sbp->value_s = Dot;
	} else if (sbp->csect_s!=Cur_csect || sbp->value_s!=Dot)
	  Prog_Error(E_MULTSYM);

	if (!(cinfo[lab[0]] & D)) Last_symbol = sbp;

/* fprintf(stderr,"slabel(%s) = %ld\n",lab,Dot); */
}

/* handle assignment to a label, return updated line pointer */
char *sassign(lptr,token)
  register char *token;
  register char *lptr;
  {	register char *p;
	register struct sym_bkt *sbp;
	struct oper value;
	char lab[50];

	/* make asciz version of label */
	p = lab;
	while (cinfo[*token] & T) *p++ = *token++;
	*p = 0;

	/* find/enter symbol in the symbol table, and get its new value */
	sbp = Lookup(lab);
	lptr = exp(lptr,&value);

	/* if assignment is to dot, we'll treat it specially */
	if (sbp == Dot_bkt) {
	  if (value.sym_o && value.sym_o->csect_s!=Cur_csect)
	    Prog_Error(E_OPERAND);
	  if ( Dot > value.value_o ) Prog_Error(E_OPERAND);
	  else Pad_Text(value.value_o - Dot);
	  Dot = value.value_o;
	  Cur_csect->dot_cs = Dot_bkt->value_s = Dot;
	  if (Dot > Cur_csect->len_cs) Cur_csect->len_cs = Dot;
	} else {
	  sbp->value_s = value.value_o;
	  sbp->csect_s = (value.sym_o!=NULL) ? value.sym_o->csect_s : NULL;
	  if (sbp->attr_s & S_LABEL) Prog_Error(E_EQUALS);
	  else sbp->attr_s |= (value.sym_o!=NULL) ?
	    (value.sym_o->attr_s & ~(S_LABEL|S_PERM)): (S_DEC | S_DEF);
	}

/* fprintf(stderr,"sassign(%s) = %ld\n",lab,value.value_o); */

	/* return update line pointer */
	skipb(lptr);
	return(lptr);
}

/* Hashing routine for Symbol and Instruction hash tables */
Hash(s)
  register char *s;
  {	register int i = 0;

	while (*s) i = i*10 + *s++ - ' ';
	i = i % HASH_MAX;
	return(i<0 ? i+HASH_MAX : i);
}

/* Fetches operand value and register subfields and loads them into
 * the operand structure. This routine will fetch only one set of value
 * and register subfields. It will move line pointer to first untouched char.
 */
char *soperand(lptr,opnd)
  register char *lptr;
  struct oper *opnd;
  {	char c;
	struct oper topnd;

	opnd->type_o = opnd->flags_o = opnd->reg_o = 0;
	opnd->value_o = 0;
	opnd->sym_o = NULL;

 again:	while (1) {
	  skipb(lptr);
	  if (cinfo[*lptr] == SOP) { opnd->type_o |= t_short; lptr++; continue; }
	  if (cinfo[*lptr] == IND) { opnd->type_o |= t_ind; lptr++; continue; }
	  break;
	}

	if (cinfo[*lptr] == IMM) {
	  lptr = exp(lptr+1,opnd);
	  if ((opnd->type_o & t_type) != t_norm) Prog_Error(E_OPERAND);
	  opnd->type_o += t_imm - t_norm;
	} else if (cinfo[*lptr] == MUL) {
	  lptr = exp(lptr+1,opnd);
	  if ((opnd->type_o & t_type) != t_norm) Prog_Error(E_OPERAND);
	  opnd->type_o += t_sxt - t_norm;
	} else if (*(lptr+1)=='s' && *(lptr+2)==':') {
	  if (*lptr == 'e') Code[0] = 0x26;
	  else if (*lptr == 'c') Code[0] = 0x2E;
	  else if (*lptr == 's') Code[0] = 0x36;
	  else if (*lptr == 'd') Code[0] = 0x3E;
	  else { Prog_Error(E_OPERAND); Code[0] = 0x90; }
	  if (segflag) Prog_Error(E_OPERAND);
	  else {
	    segflag = 1;
	    Put_Text(Code,1);
	    Dot += 1;
	  }
	  lptr += 3;
	  goto again;
	} else if (cinfo[*lptr] != LP) {
	  lptr = exp(lptr,opnd);
	  skipb(lptr);
	}

	if (cinfo[*lptr] == LP) {
	  topnd.type_o = topnd.flags_o = topnd.reg_o = 0;
	  topnd.value_o = 0;
	  topnd.sym_o = NULL;
	  lptr = exp(lptr+1,&topnd);
	  if (cinfo[*lptr] != RP) Prog_Error(E_OPERAND);
	  else lptr++;
	  if (topnd.type_o != t_reg) Prog_Error(E_OPERAND);
	  opnd->reg_o = topnd.value_o;
	  if ((opnd->type_o&t_type) == t_sxt) opnd->type_o += t_six - t_sxt;
	  else if ((opnd->type_o&t_type) == 0) opnd->type_o = t_indr;
	  else opnd->type_o = (opnd->type_o & ~t_type) | t_ix;
	}
	return(lptr);
}

/* read expression */
char *exp(lptr,Arg1)
  register char *lptr;
  register struct oper *Arg1;
  {	struct oper Arg2;	/* holds value of right hand term */
	register int i;
	register char Op;	/* operator character */

	skipb(lptr);				/* Find the operator */
	i = cinfo[*lptr];
	if (i==EOL || i==COM) {		/* nil operand is zero */
	  Arg1->sym_o = NULL;
	  Arg1->value_o = 0;
	  return(lptr);
	 }
	lptr = term(lptr,Arg1);

	while (1) {
	  skipb(lptr);
	  switch (cinfo[*lptr]) {
	    case ADD:	lptr = term(++lptr,&Arg2);
			if (Arg1->type_o==t_reg || Arg2.type_o==t_reg) break;
			if (Arg1->sym_o && Arg2.sym_o) break;
			if (Arg2.sym_o) Arg1->sym_o = Arg2.sym_o;
			Arg1->value_o += Arg2.value_o;
			Arg1->flags_o |= Arg2.flags_o&O_COMPLEX;
			continue;

	    case MUL:	lptr = term(++lptr,&Arg2);
			if (Arg1->type_o==t_reg || Arg2.type_o==t_reg) break;
			if (Arg1->sym_o || Arg2.sym_o) break;
			Arg1->value_o *= Arg2.value_o;
			Arg1->flags_o |= Arg2.flags_o&O_COMPLEX;
			continue;

	    case DIV:	lptr = term(++lptr,&Arg2);
			if (Arg1->type_o==t_reg || Arg2.type_o==t_reg) break;
			if (Arg1->sym_o || Arg2.sym_o) break;
			Arg1->value_o /= Arg2.value_o;
			Arg1->flags_o |= Arg2.flags_o&O_COMPLEX;
			continue;

	    case SUB:	lptr = term(++lptr,&Arg2);
			if (Arg1->type_o==t_reg || Arg2.type_o==t_reg) break;
			if (Arg2.sym_o)		/* if B is relocatable, */
			  if (Arg1->sym_o) {	/* and A is relocatable, */
			    if (Arg2.sym_o->csect_s != Arg1->sym_o->csect_s) break; /* break into error */
			    else {
			      Arg1->sym_o = NULL;	/* result is absolute (no offset) */
			      Arg1->flags_o |= O_COMPLEX;	/* but not a simple address for sdi's */
			    }
			  } else break;		/* if B rel., and A is not, then break into relocation error */
			Arg1->value_o -= Arg2.value_o;
			continue;

	    default:	return(lptr);
	  }
	Prog_Error(E_RELOCATE);
	return(lptr);
	}
}

/* read term: either symbol, constant, or unary minus */
char *term(lptr,Vp)
  register char *lptr;
  register struct oper *Vp;
  {	register int i;
	register struct sym_bkt *sbp;
	register char *p;
	register int base = 10;
	register long val;
	char token[50];

	skipb(lptr);
	i = cinfo[*lptr];

	/* here for number */
	if (i & D) {
	  p = lptr;
	  if (*lptr == '0') {
	    lptr++;
	    if (*lptr=='x' || *lptr=='X') { lptr++; base = 16; }
	    else base = 8;
	  }
	  val = 0;
	  if (base == 16) while (1) {
	    if (cinfo[*lptr] & D) val = val*16 + *lptr++ - '0';
	    else if (*lptr>='A' && *lptr<='F')
	      val = val*16 + *lptr++ - 'A' + 10;
	    else if (*lptr>='a' && *lptr<='f')
	      val = val*16 + *lptr++ - 'a' + 10;
	    else break;
	  } else while (cinfo[*lptr] & D) val = val*base + *lptr++ - '0';

	  if (*lptr == '$') { lptr = p; goto sym; }

	  Vp->value_o = val;
	  Vp->sym_o = NULL;
	  Vp->type_o |= t_norm;
	  return(lptr);
	}

	/* here for symbol name */
	if (i & S) {
    sym:  p = token;
	  while (cinfo[*lptr]&T || *lptr=='$') *p++ = *lptr++;
	  *p = 0;	  
	  sbp = Lookup(token);		/* find its symbol bucket */

	  if (sbp->attr_s & S_DEF)	/* if it's defined, use its value */
	    Vp->value_o = sbp->value_s;
	  else Vp->value_o = 0;

	  if (sbp->attr_s & S_REG) Vp->type_o |= t_reg;
	  else {
	    Vp->sym_o = (sbp->attr_s & S_DEF) &&
			 (sbp->csect_s == 0 || (sbp->csect_s->attr_cs & R_ABS))
				    ? 0 : sbp;
	    Vp->type_o |= t_norm;
	  }
	  return(lptr);
	}

	/* check for unary minus */
	if (i == SUB) {
	  lptr = term(++lptr,Vp);
	  if (Vp->sym_o) Prog_Error(E_RELOCATE);
	  Vp->value_o = -(Vp->value_o);	/* and finally do it */
	  return(lptr);
	}

	/* check for complement */
	if (i == NOT) {
	  lptr = term(++lptr,Vp);
	  if (Vp->sym_o) Prog_Error(E_RELOCATE);
	  Vp->value_o = ~(Vp->value_o);	/* and finally do it */
	  return(lptr);
	}

	/* check for character constant */
	if (i == CHR) {
	  Vp->value_o = *(lptr+1);
	  Vp->sym_o = NULL;
	  Vp->type_o = t_norm;
	  return(lptr+2);
	}

	/* here for string */
	if (i == QUO) {
	  Vp->value_o = (long)(lptr+1);
	  do i = cinfo[*++lptr]; while (i!=EOL && i!=QUO);
	  *lptr++ = 0;
	  Vp->sym_o = NULL;
	  Vp->type_o |= t_string;
	  return(lptr);
	}

	Prog_Error(E_TERM);
	return(lptr);
}

char *tnames[] = {
  "?", "norm", "reg", "imm", "sxt", "indr", "ix", "six", "string"
};

printop(o)
  register struct oper *o;
  {	fprintf(stderr,"operand %d: type=%s",numops,tnames[o->type_o & t_type]);
	if (o->type_o & t_ind) putc('@',stderr);
	if (o->type_o & t_short) putc('$',stderr);
	if (o->sym_o)
	  fprintf(stderr," csect=%s sym=%s",
		  o->sym_o->csect_s->name_cs,o->sym_o->name_s);
	fprintf(stderr," value=%ld reg=%d\n",
		o->value_o,o->reg_o);
}
urn(lptr);
	}

	Prog_Error(E_TERM);
	return(lptr);
}

char *tnames[] = {
  "?", "norm", "reg", "imm", "sxt", "indr", "ix", "six", "string"
}a86/sdi.c                                                                                              444      26      12        13241  2657354353   5434                                                                                                                                                                                                                                                                                                                                                                      #include "mical.h"

static char *sdi = "~|^`s.sdi.c R1.7 on 6/27/80";

/*
 * module to handle span-dependent instructions, e.g. jbr
 * see CACM Vol 21 No 4 April 1978 for a description of the
 * algorithm for resolving sdi's between the 1st and 2nd pass
 */


struct sdi {	/* information for span dependent instructions (sdi's) */
	struct sdi *sdi_next;           /* next sdi in list */
	struct csect *sdi_csect;	/* csect of the sdi */
	long int sdi_loc;		/* location of the sdi */
	struct sym_bkt *sdi_sym;	/* symbol part of the sdi address */
	long int sdi_off;		/* offset part of the sdi address */
	int sdi_gleng;			/* length of the most general form */
	int sdi_leng;			/* actual length of the sdi */
	long int sdi_span;		/* span of  the sdi */
	long int sdi_base;		/* origin of the span of the sdi */
	struct blist *sdi_bounds;	/* length & bounds info for forms of sdi */
} *sdi_list = 0;	/* linked list of sdi's descriptors */

struct blist {	/* length and bounds information for various forms of sdi's */
	struct blist *b_next;	/* next element in list */
	int b_length;		/* length of this form of the sdi */
	long int b_lbound;	/* lower and upper bound on the span */
	long int b_ubound;	/* for this form of the sdi */
} shortblist = {
  NULL, 2, -128L, 127		/* canonical bounds list for byte offset */
};

/*
 * routine to create a sdi descriptor and insert it into the list
 */
makesdi(op, gleng, base, bounds)
struct oper *op;	/* the operand of the sdi */
int gleng;		/* the length of the most general form of the sdi */
long int base;		/* origin of the the initial span of the sdi, to be */
			/* corrected between pass1 and pass2 by subtracting */
			/* from the value of the symbol of the operand */
			/* i.e. 0 for resolving short absolute address modes */
			/* Dot[+increment] for PC relative addresses */
struct blist *bounds;	/* list of lengths & bounds for the sdi */
{
	register struct sdi *s, **p;
	extern struct csect *Cur_csect;

	if (op->flags_o&O_COMPLEX)	/* not a simple address */
		return;
	if ((s = (struct sdi *)calloc(1,sizeof *s)) == NULL)
		Sys_Error("sdi storage exceeded\n");
	s->sdi_loc = Dot;
	s->sdi_csect = Cur_csect;
	s->sdi_sym = op->sym_o;
	s->sdi_off = op->value_o;
	s->sdi_gleng = gleng;
	s->sdi_base = base;
	s->sdi_span = - base;
	s->sdi_bounds = bounds;
	s->sdi_leng = bounds->b_length;	/* shortest length */
	for (p = &sdi_list; *p; p = &(*p)->sdi_next)
		if (s->sdi_loc < (*p)->sdi_loc)
			break;
	s->sdi_next = *p;
	*p = s;
	return(s->sdi_leng);	/* return the current length */
}

/*
 * insert a new blist element into a blist
 * The blist is sorted by increasing b_length
 */
struct blist *sdi_bound(leng, lbound, ubound, next)
int leng;		/* length of this form of the sdi */
long int lbound;	/* lower bound of span */
long int ubound;	/* upper bound */
struct blist *next;	/* target blist */
{
	register struct blist *b, **p;

	if ((b = (struct blist *)calloc(1,sizeof *b)) == NULL)
		Sys_Error("sdi bound list storage exceeded\n");
	b->b_length = leng;
	b->b_lbound = lbound;
	b->b_ubound = ubound;
	for (p = &next; *p; p = &(*p)->b_next)
		if (leng <= (*p)->b_length)
			break;
	b->b_next = *p;
	*p = b;
	return(*p);
}

/*
 * resolve sdi's between pass1 and pass2
 * basic algorithm is to repeatedly look for sdi that must use the
 * long form, and update the span of other sdi's.
 * When this terminates, all remaining sdi's can use the short form
 */
sdi_resolve()
{
	register struct sdi *s;
	register struct sym_bkt *p;
	register int t;
	int changed;

	for (s = sdi_list; s; s = s->sdi_next) {
		p = s->sdi_sym;
		if (s->sdi_csect == p->csect_s && (p->attr_s & S_DEF))
			s->sdi_span += s->sdi_sym->value_s;
	}

	do {
		changed = 0;
		for (s = sdi_list; s; s = s->sdi_next) {
			if ((t = sdi_len(s) - s->sdi_leng) > 0) {
				longsdi(s, t);
				changed = 1;
			} else if (t < 0)
				Sys_Error("Pathological sdi\n");
		}
	} while (changed);
}

/*
 * update sdi list assuming the specified sdi must be long
 */
longsdi(s, delta)
struct sdi *s;
register int delta;
{
	register struct sdi *t;
	long loc;

	s->sdi_leng += delta;	/* update the length of this sdi */
	/* get the real location of the sdi */
	loc = s->sdi_loc + sdi_inc(s->sdi_csect, s->sdi_loc);
	for (t = sdi_list; t; t = t->sdi_next)
		if (t != s && s->sdi_csect == t->sdi_sym->csect_s) {
			if (t->sdi_span < 0
			 && t->sdi_span+t->sdi_base <= loc
			 && loc < t->sdi_base)
				t->sdi_span -= delta;
			else if (t->sdi_span >= 0
			 && t->sdi_base <= loc
			 && loc < t->sdi_span+t->sdi_base)
				t->sdi_span += delta;
			if (t->sdi_base > loc)
				t->sdi_base += delta;
		}
}

/*
 * compute the length of the specified sdi by searching the bounds list
 */
sdi_len(s)
register struct sdi *s;
{
	register struct blist *b;
	if (!(s->sdi_sym->attr_s & S_DEF) || s->sdi_csect != s->sdi_sym->csect_s)
		return(s->sdi_gleng);
	for (b = s->sdi_bounds; b; b = b->b_next)
		if (b->b_lbound <= s->sdi_span && s->sdi_span <= b->b_ubound)
			return(b->b_length);
	return(s->sdi_gleng);
}

/*
 * return the total number of extra bytes due to long sdi's before
 * the specified offset in the specified csect
 */
sdi_inc(csect, offset)
register struct csect *csect;
long int offset;
{
	register struct sdi *s;
	register int total;

	for (s = sdi_list, total = 0; s; s = s->sdi_next) {
		if (csect == s->sdi_csect) {
			if (offset <= s->sdi_loc)
				break;
			total += s->sdi_leng - s->sdi_bounds->b_length;
		}
	}
	return(total);
}

/*
 * release all sdi descriptors
 */
sdi_free()
{
	register struct sdi *s, *t;
	for (s = sdi_list; s; s = t) {
		t = s->sdi_next;
		b_free(s->sdi_bounds);
		free(s);
	}
	sdi_list = (struct sdi *)0;
}

/*
 * release a bounds list
 */
b_free(p)
register struct blist *p;
{
	register struct blist *q;
	while(p) {
		q = p->b_next;
		free(p);
		p = q;
	}
}

i_next) {
		if (csect == s->sdi_csect) {
			if (offset <= s->sdi_loc)
				break;
			total += s->sdi_leng - s->sdi_bounds->b_length;
		}
	}
	return(total);
}

/*
 * release all sdi descriptors
 */
sdi_free()
{
	register struct sdi *s, *t;
	for (s = sdi_list; s; s = t) {
		t = s->sdi_next;
		b_free(s->sdi_bounds);
		free(s);
	}
	sdi_list = (struct sdia86/sym.c                                                                                              444      26      12        12023  2657354354   5463                                                                                                                                                                                                                                                                                                                                                                      #include "mical.h"
#include <a.out.h>

/* Allocation increments for symbol buckets and character blocks */
#define	SYM_INCR	50
#define CBLOCK_INCR	512

struct sym_bkt *Last_symbol;			/* last symbol defined */
struct sym_bkt *sym_hash_tab[HASH_MAX];		/* Symbol hash table */
struct sym_bkt *sym_free = NULL;		/* head of free list */
char *cblock = NULL;				/* storage for symbol names */
int ccnt = 0;					/* number of chars left in c block */

/* grab a new symbol bucket off of the free list; allocate space
 * for a new free list if necessary
 */
struct sym_bkt *gsbkt()
  {	register struct sym_bkt	*sbp;
	register int i;

	if ((sbp = sym_free) != NULL) sym_free = sbp->next_s;
	else {
	  sbp = (struct sym_bkt *)calloc(SYM_INCR,sizeof(struct sym_bkt));
	  if (sbp == NULL) Sys_Error("Symbol storage exceeded\n",0);
	  for (i = SYM_INCR-1; i--;) {
	    sbp->next_s = sym_free;
	    sym_free = sbp++;
	  }
	}

	return(sbp);
}

/* initialize hash table */
Sym_Init()
  {	register int i;

	for (i=0; i<HASH_MAX; i++) sym_hash_tab[i] = NULL;
}

char *sstring(string)
  register char *string;
  {	register char *p,*q;	/* working char string */
	register int i;

	i = strlen(string);	/* get length of string */

	if (++i > ccnt) {	/* if not enough room get more */
	  if ((cblock = (char *)calloc(CBLOCK_INCR,1)) == NULL)
	    Sys_Error("Symbol storage exceeded\n",0);
	  ccnt = CBLOCK_INCR;
	}

	p = q = cblock;		/* copy string into permanent storage */
	while (*p++ = *string++);
	cblock = p;
	ccnt -= i;
	return(q);
}

/* lookup symbol in symbol table */
struct sym_bkt *Lookup(s)
  register char *s;
  {	register struct sym_bkt	*sbp;	/* general purpose ptr */
	register int Save;		/* save subscript in sym_hash_tab */
	register char *p;
	char local[50];			/* used for constructing local sym */

	if (*s>='0' && *s<='9') {	/* local symbol hackery */
	  p = local;
	  while (*p++ = *s++);		/* copy local symbol */
	  p--;
	  s = Last_symbol->name_s;	/* add last symbol defined as suffix */
	  while (*p++ = *s++);
	  s = local;			/* this becomes name to deal with */
	}

	/* if the symbol is already in here, return a ptr to it */
	for (sbp = sym_hash_tab[Save=Hash(s)]; sbp != NULL ; sbp = sbp->next_s)
	  if (strcmp(sbp->name_s,s) == 0) return(sbp);

	/* Since it's not, make a bucket for it, and put the bucket in the symbol table */
	sbp = gsbkt();				/* get the bucket */
	sbp->name_s = sstring(s);		/* Store it's name */
	sbp->value_s = sbp->id_s = sbp->attr_s = 0;
	sbp->csect_s = NULL;
	sbp->next_s = sym_hash_tab[Save];	/* and insert on top of list */
	if (s == local) sbp->attr_s |= S_LOCAL;
	return(sym_hash_tab[Save] = sbp);
}

/* Sym_Fix -	Assigns index numbers
		to the symbols.  Also performs relocation of
		the symbols assuming data segment follows text
		and bss follows the data.  If global flag,
		make all undefined symbols defined to be externals.
*/
Sym_Fix()
{
	register struct sym_bkt **sbp1, *sbp2;
	int i = 0;

	for (sbp1 = sym_hash_tab; sbp1 < &sym_hash_tab[HASH_MAX]; sbp1++)
	  for (sbp2 = *sbp1; sbp2; sbp2 = sbp2->next_s) {
	    if ((sbp2->attr_s & (S_DEC|S_DEF)) == 0) {
	      sbp2->attr_s |= S_EXT | S_DEC;
	      sbp2->csect_s = NULL;
	    }
	    sbp2->value_s += sdi_inc(sbp2->csect_s, sbp2->value_s);
	    if (sbp2->csect_s == Data_csect) sbp2->value_s += tsize;
	    else if (sbp2->csect_s == Bss_csect) sbp2->value_s += tsize + dsize;
	    if (sbp2 == Dot_bkt || sbp2->attr_s & (S_REG|S_MACRO|S_LOCAL|S_PERM))
	      sbp2->id_s = -1;
	    else sbp2->id_s = i++;
	  }
}


/* Sym_Write -	Write out the symbols to the specified
		file in a.out format, while computing size
		of the symbol segment in output file.
 */
long Sym_Write(file)
  FILE *file;
  {	register struct sym_bkt  **sbp1, *sbp2;
	register char *sp;
	long size = 0;
	long slength = 4;
	struct nlist s;

	s.n_other = 0;
	s.n_desc = 0;
	for (sbp1 = sym_hash_tab; sbp1 < &sym_hash_tab[HASH_MAX]; sbp1++)
	  for (sbp2 = *sbp1; sbp2; sbp2 = sbp2->next_s)
	    if (sbp2->id_s != -1) {
	      if (!(sbp2->attr_s&S_DEF)) s.n_type = N_UNDF;
	      else if (sbp2->csect_s == Text_csect) s.n_type = N_TEXT;
	      else if (sbp2->csect_s == Data_csect) s.n_type = N_DATA;
	      else if (sbp2->csect_s == Bss_csect) s.n_type = N_BSS;
	      else s.n_type = N_ABS;
	      if (sbp2->attr_s & S_EXT) s.n_type |= N_EXT;
	      s.n_value = sbp2->value_s;
	      s.n_un.n_strx = slength;
	      fwrite(&s, sizeof s, 1, file);
	      size += sizeof(s);
	      slength += strlen(sbp2->name_s) + 1;
	    }

	fwrite(&slength, sizeof(slength), 1, file);

	for (sbp1 = sym_hash_tab; sbp1 < &sym_hash_tab[HASH_MAX]; sbp1++)
	  for (sbp2 = *sbp1; sbp2; sbp2 = sbp2->next_s)
	    if (sbp2->id_s != -1) {
	      sp = sbp2->name_s;
	      do putc(*sp,file); while (*sp++);
	    }

	return(size);
}

/*
 * Perm	Flags all currently defined symbols as permanent (and therefore
 *	ineligible for redefinition.  Also prevents them from being output
 *	in the object file).
 */
Perm()
  {	register struct sym_bkt **sbp1, *sbp2;

	for (sbp1 = sym_hash_tab; sbp1 < &sym_hash_tab[HASH_MAX]; sbp1++)
		for (sbp2 = *sbp1; sbp2; sbp2 = sbp2->next_s)
			sbp2->attr_s |= S_PERM;
}
 sbp2 = sbp2->next_s)
	    if (sbp2->id_s != -1) {
	      sp = sbp2->name_s;
	      do putc(*sp,file); while (*sp++);
	    }

	return(size);
}

/*
 * Perm	Flags all currently defined symbols as permanent (and therefore
 *	ineligible for redefinition.  Also prevents them from being output
 *	in the object file).
 */
Perm()
  {	register struct sym_bkt **sbp1, *sbp2;

	for (sbp1 = sym_hash_tab; sbp1 < &sym_hash_tab[HASH_MAX]; sbp1++)
		for (sbp2 = *sbp1; sbp2; sbp2 = sbp2->next_s)
			sbp2->aa86/inst.h                                                                                             644      26      12        11565  2744362614   5644                                                                                                                                                                                                                                                                                                                                                                      /* dispatch numbers for 8086 instructions.  These numbers are placed in
 * the code_i component of each instruction bucket by init.c and are used
 * by ins.c for dispatching.
 */

#define i_aaa	1
#define i_aad	2
#define i_aam	3
#define i_aas	4
#define i_adc	5
#define i_add	6
#define i_and	7
#define i_call	8
#define i_calli	9
#define i_cbw	10
#define i_clc	11
#define i_cld	12
#define i_cli	13
#define i_cmc	14
#define i_cmp	15
#define i_cmpb	16
#define i_cmpw	17
#define i_cwd	18
#define i_daa	19
#define i_das	20
#define i_dec	21
#define i_div	22
#define i_esc	23
#define i_idiv	24
#define i_imul	25
#define i_in	26
#define i_inc	27
#define i_int	28
#define i_into	29
#define i_inw	30
#define i_iret	31
#define i_hlt	32
#define i_j	33
#define i_je	34
#define i_jl	35
#define i_jle	36
#define i_jb	37
#define i_jbe	38
#define i_jp	39
#define i_jo	40
#define i_js	41
#define i_jne	42
#define i_jnl	43
#define i_jnle	44
#define i_jnb	45
#define i_jnbe	46
#define i_jnp	47
#define i_jno	48
#define i_jns	49
#define i_jcxz	50
#define i_jmp	51
#define i_jmpi	52
#define i_lahf	53
#define i_lds	54
#define i_lea	55
#define i_les	56
#define i_lock	57
#define i_lodb	58
#define i_lodw	59
#define i_loop	60
#define i_loope	61
#define i_loopne	62
#define i_mov	63
#define i_movb	64
#define i_movw	65
#define i_mul	66
#define i_neg	67
#define i_not	68
#define i_or	69
#define i_out	70
#define i_outw	71
#define i_pop	72
#define i_popf	73
#define i_push	74
#define i_pushf	75
#define i_rcl	76
#define i_rcr	77
#define i_repnz	78
#define i_repz	79
#define i_ret	80
#define i_reti	81
#define i_rol	82
#define i_ror	83
#define i_sahf	84
#define i_sal	85
#define i_sar	86
#define i_sbb	87
#define i_scab	88
#define i_scaw	89
#define i_seg	90
#define i_shr	91
#define i_stc	92
#define i_std	93
#define i_sti	94
#define i_stob	95
#define i_stow	96
#define i_sub	97
#define i_test	98
#define i_wait	99
#define i_xchg	100
#define i_xlat	101
#define i_xor	102

#define i_beq	103
#define i_bne	104
#define i_ble	105
#define i_bgt	106
#define i_blt	107
#define i_bge	108
#define i_blos	109
#define i_bhi	110
#define i_blo	111
#define i_bhis	112
#define	i_br	113

#define i_addb	114
#define i_adcb	115
#define i_incb	116
#define i_subb	117
#define i_sbbb	118
#define i_decb	119
#define i_negb	120
#define i_mulb	121
#define i_imulb	122
#define i_divb	123
#define i_idivb	124
#define i_notb	125
#define i_salb	126
#define i_shrb	127
#define i_sarb	128
#define i_rolb	129
#define i_rorb	130
#define i_rclb	131
#define i_rcrb	132
#define i_andb	133
#define i_testb	134
#define i_orb	135
#define i_xorb	136

#define i_fabs		137
#define i_faddf		138
#define i_faddl		139
#define i_faddd		140
#define i_faddi		141
#define i_fadd		142
#define i_faddp		143
#define i_fchs		146
#define i_fclex		147
#define i_fcomf		148
#define i_fcoml		149
#define i_fcomd		150
#define i_fcomi		151
#define i_fcom		152
#define i_fcompf	153
#define i_fcompl	154
#define i_fcompd	155
#define i_fcompi	156
#define i_fcomp		157
#define i_fcompp	158
#define i_fdecstp	159
#define i_fdisi		160
#define i_fdivf		161
#define i_fdivl		162
#define i_fdivd		163
#define i_fdivi		164
#define i_fdiv		165
#define i_fdivp		166
#define i_fdivr		167
#define i_fdivrp	168
#define i_feni		169
#define i_ffree		170
#define i_fincstp	171
#define i_finit		172
#define i_fldcw		173
#define i_fldenv	174
#define i_fldf		175
#define i_fldl		176
#define i_fldd		177
#define i_fldi		178
#define i_fld		179
#define i_fldlg2	180
#define i_fldln2	181
#define i_fldl2e	182
#define i_fldl2t	183
#define i_fldpi		184
#define i_fldz		185
#define i_fld1		186
#define i_fnop		187
#define i_fmulf		188
#define i_fmull		189
#define i_fmuld		190
#define i_fmuli		191
#define i_fmul		192
#define i_fmulp		193
#define i_fpatan	196
#define i_fprem		197
#define i_fptan		198
#define i_frstor	199
#define i_frndint	200
#define i_fsave		201
#define i_fscale	202
#define i_fsqrt		203
#define i_fstf		204
#define i_fstl		205
#define i_fstd		206
#define i_fsti		207
#define i_fst		208
#define i_fstpf		209
#define i_fstpl		210
#define i_fstpd		211
#define i_fstpi		212
#define i_fstp		213
#define i_fstcw		214
#define i_fstenv	215
#define i_fstsw		216
#define i_fsubf		217
#define i_fsubl		218
#define i_fsubd		219
#define i_fsubi		220
#define i_fsub		221
#define i_fsubp		222
#define i_fsubr		223
#define i_fsubrp	224
#define i_ftst		225
#define i_fwait		226
#define i_fxam		227
#define i_fxch		228
#define i_fxtract	229
#define i_fyl2x		230
#define i_fyl2xp1	231
#define i_f2xm1		232
#define i_fdivrf	233
#define i_fdivrl	234
#define i_fdivrd	235
#define i_fdivri	236
#define i_fsubrf	237
#define i_fsubrl	238
#define i_fsubrd	239
#define i_fsubri	240

#define i_long	241
#define i_word	242
#define i_byte	243
#define i_text	244
#define i_data	245
#define i_bss	246
#define i_globl 247
#define i_comm	248
#define i_even	249
#define i_ascii 250
#define i_asciz 251
#define i_zerow 252
/* the following definition added by Bill O'Farrell June 28, 1982 */
#define i_para  253
1
#define i_f2xm1		232
#define i_fdivrf	233
#define i_fdivrl	234
#define i_fdivrd	235
#define i_fdivri	236
#define i_fsubrf	237
#define i_fa86/mical.h                                                                                            444      26      12        12172  2747346765   5761                                                                                                                                                                                                                                                                                                                                                                      #include <stdio.h>

/* Assembler parameters */
#define	STR_MAX		32	/* number of chars in any single token */
#define OPERANDS_MAX	16	/* number of operands allowed per instruction */
#define	HASH_MAX	256	/* size of symbol, command, and macro hash tables */
#define CODE_MAX	12	/* number of bytes generated for 1 machine instruction */
#define ERR_MAX		50	/* Max number of different error codes */
#define CSECT_MAX	200	/* number of control sections */

/* Error Codes */
#define E_END		1
#define E_BADCHAR	2
#define E_MULTSYM	3
#define	E_NOSPACE	4
#define	E_OFFSET	5
#define	E_SYMLEN	6
#define	E_SYMDEF	7
#define	E_CONSTANT	8
#define	E_TERM		9
#define	E_OPERATOR	10
#define	E_RELOCATE	11
#define	E_TYPE		12
#define	E_OPERAND	13
#define	E_SYMBOL	14
#define	E_EQUALS	15
#define	E_NLABELS	16
#define	E_OPCODE	17
#define	E_ENTRY		18
#define	E_STRING	19
#define	E_INSRT		20
#define	E_ATTRIBUTE	21
#define	E_.ERROR	22
#define	E_LEVELS	23
#define	E_CONDITION	24
#define	E_NUMOPS	25
#define	E_LINELONG	26
#define E_REG		27
#define	E_IADDR		28
#define E_UNIMPL	29
#define E_FILE		30
#define E_MLENGTH	32
#define E_MACARG	33
#define	E_MACFORMAL	34
#define E_ENDC		35
#define E_RELADDR	36
#define E_ARGUMENT	37
#define E_VECINDEX	38
#define E_VECMNEM	39
#define E_MACRO		40
#define E_TMACRO	41
#define E_CSECT		42
#define E_ODDADDR	43

/* Size Codes - These should agree with Rel size codes in b.h */
#define B 0	/* byte */
#define W 1	/* word */
#define L 2	/* long */

/* operand flags */
#define O_WINDEX 1
#define O_LINDEX 2
#define O_COMPLEX 4

/* Symbol attributes */
#define	S_DEC	01
#define S_DEF	02
#define S_EXT	04
#define S_LABEL	010
#define S_MACRO	020
#define S_REG	040
#define S_LOCAL 0100
#define S_COMM	0200
#define S_PERM	0400

/* Rel file and Csect attributes */
#define R_EXT	01
#define R_ISPC	02
#define R_PURE	04
#define R_ABS	010
#define R_DEC	020

/* operand types */
#define t_norm	1	/* ordinary operand */
#define t_reg	2	/* register */
#define t_imm	3	/* immediate operand */
#define t_sxt	4	/* sign extendable immediate operand */
#define t_indr	5	/* indirect through register */
#define t_ix	6	/* indexed with word offset */
#define t_six	7	/* indexed with sign extendable offset */
#define t_string 8	/* arguments to .ascii, .asciz pseudo ops */
#define t_short	020	/* set if byte operand */
#define t_ind	040	/* indirect through memory */
#define t_type	017	/* used to mask type bits */

/* Instruction Hash Table */
struct ins_bkt {
  struct ins_bkt *next_i;	/* ptr to next bkt on the list */
  char *text_i;			/* ptr to asciz instruction mnemonic */
  short code_i;			/* opcode index for dispatching */
};

/* Csect descriptor */
struct csect {
  char *name_cs;	/* name */
  long len_cs;		/* Length in machine addresses, i.e., highest address referenced */
  long dot_cs;		/* current dot in this cs, in machine addresses */
  short id_cs;		/* ID # for output file */
  short attr_cs;	/* attributes */
};

/* Symbol bucket definition */
struct sym_bkt {
  char *name_s;			/* symbol identifier */
  struct sym_bkt *next_s;	/* next bkt on linked list */
  struct csect *csect_s;	/* ptr to it's csect */
  long value_s;			/* it's value */
  short id_s;			/* id number for .b file */
  short attr_s;			/* attributes */
};

/* operand structure */
struct oper {
  char type_o;			/* operand type info */
  char flags_o;			/* operand flags */
  char reg_o;			/* Register subfield value */
  struct sym_bkt *sym_o;	/* symbol used for relocation */
  long value_o;			/* Value subfield */
};

extern char *soperand(),*exp();
extern char iline[],Code[];
extern short cinfo[];
extern int numops,Errors,Line_no,Pass,BC;
extern struct oper operands[];
extern struct ins_bkt *ins_hash_tab[];
extern struct sym_bkt *Lookup();
extern struct sym_bkt *Dot_bkt;
extern struct sym_bkt *Last_symbol;
extern long Dot,tsize,dsize,bsize;
extern struct csect *Cur_csect,*Text_csect,*Data_csect,*Bss_csect;
extern struct csect Csects[];
extern int Csect_load;
extern char Rel_name[],*Source_name;
extern short *WCode;		/* buffer for code in ins.c */
extern char Code_length;	/* number of bytes in WCode */

/* skip to next non-spacing character */
#define skipb(p) while (cinfo[*p] == SPC) p++

/* skip to end of symbol */
#define skips(p) while (cinfo[*p]&T || *p=='$') p++

/* bits found in character info array cinfo[] */
#define D 0x0100	/* digit */
#define S 0x0200	/* can start symbol */
#define T 0x0400	/* can be part of symbol */

#define COL 0x00	/* label definition */
#define EQL 0x01	/* label assignment */
#define EOL 0x02	/* end of line -- newline or comment char */
#define ADD 0x03	/* addition operator */
#define SUB 0x04	/* subtraction operator */
#define SPC 0x05	/* spacing character */
#define ERR 0x06	/* illegal character */
#define IMM 0x07	/* immediate operand indicator */
#define LP  0x08	/* left paren */
#define RP  0x09	/* right paren */
#define COM 0x0A	/* operand separator */
#define IND 0x0B	/* indirection operator */
#define MUL 0x0C	/* multiplication operator */
#define NOT 0x0D	/* complement operator */
#define QUO 0x0E	/* beginning/end of string */
#define SOP 0x0F	/* sign-extendable operand */
#define EOS 0x10	/* end of statement */
#define CHR 0x11	/* character constant */
#define DIV 0x12	/* divide */
aracter */
#define IMM 0x07	/* immediate operand indicator */
#define LP  0x08	/* left paren */
#define RP  0x09	/* right paren */
#define COM 0x0A	/* operand separator */
#define IND 0x0B	/* indirection operator */
#define MUL 0x0C	/* multiplication operator */
#define NOT 0x0D	/* complement operator */
#define QUO 0x0E	/* beginning/end of string */
#define SOP 0x0F	/* sign-extendable olib86/Makefile                                                                                         444      30      12          751  3355665364   6437                                                                                                                                                                                                                                                                                                                                                                      remake:
	- rm libc.a nlibc.a
	make all

all: libc.a nlibc.a crt0.b

libc.a:
	cd crt; make
	cd sys; make
	cd gen; make
	cd stdio; make
	ls crt/*.b gen/*.b sys/*.b stdio/*.b | sort -t/ +1 > t1
	ar cr libc.a `lorder \`cat t1\` | tsort`;
	ranlib libc.a
	rm -f t1

nlibc.a:
	cd ncrt; make
	cd sys; make
	cd ngen; make
	cd nstdio; make
	ls ncrt/*.b ngen/*.b sys/*.b nstdio/*.b | sort -t/ +1 > t1
	ar cr nlibc.a `lorder \`cat t1\` | tsort`;
	ranlib nlibc.a
	rm -f t1

crt0.b:	crt0.a86
	a86 crt0

achines/8086/lib86     lib86/lorder                                                                                           755     140      12          620  3347424577   6233                                                                                                                                                                                                                                                                                                                                                                      trap "rm -f $$sym?ef; exit" 0 1 2 13 15
case $# in
0)	echo usage: lorder file ...
	exit ;;
1)	case $1 in
	*.b)	set $1 $1
	esac
esac
nm -g $* | sed '
	/^$/d
	/:$/{
		/\.b:/!d
		s/://
		h
		s/.*/& &/
		p
		d
	}
	/[TD] /{
		s/.* //
		G
		s/\n/ /
		w '$$symdef'
		d
	}
	s/.* //
	G
	s/\n/ /
	w '$$symref'
	d
'
sort $$symdef -o $$symdef
sort $$symref -o $$symref
join $$symref $$symdef | sed 's/[^ ]* *//'
bc.a `lorder \`cat t1\` | tsort`;
	ranlib nlibc.a
	rm -f t1

crt0.b:	crt0/usr/src/local/Machines/8086/lib86     lib86/include/                                                                                         777     140      12            0  3523723626   6373                                                                                                                                                                                                                                                                                                                                                                      lib86/include/Vft.h                                                                                    644     140      12         4267  3347424410   7366                                                                                                                                                                                                                                                                                                                                                                      
struct VFontHdr
{
	unsigned short FontRes;	/* font raster resolution or scale	*/
	short	room[19];	/* room for additional font data	*/
};

struct VCharDef
{
	unsigned short HSize;	/* horizontal size			*/
	unsigned short VSize;	/* vertical size			*/
	short HAdj;		/* horizontal position adjustment	*/
	short VAdj;		/* vertical position adjustment		*/
	unsigned short HIncr;	/* horizontal position increment	*/
	unsigned short VIncr;	/* vertical position increment		*/
	long Raster;		/* relative pointer to mini-raster	*/
};

/* Given a pointer (p) to a VCharDef, if ((p)->Raster <= 0) then no mini-
 * raster data is present for that character, otherwise:
 *	
 *	(long *)	VCharRaster(p)	gives a pointer to the character's
 *					mini-raster;
 *	(long)		VRasterSize(p)	gives the size of the character's
 *					mini-raster, in bytes (calculated
 *					from VSize, HSize as shown below.
 */

#define	VCharRaster(p)	(((char *)&((p)->Raster))+((p)->Raster))
#define	VRasterSize(p)	((((p)->VSize)*((((p)->HSize)+15)>>4))<<1)
#define	FONTSIZE	128		/* Number of characters in a font   */

#define	FONTSCALE(X)	((short) (((X)*FontRes))/2400))

/* Size of Raster is Ch.VSIZE*((Ch.HSize+15) >> 4), in 16-bit words.
 * N.B: Raster is dealt with as 16-bit words; hence it must be
 *	word-aligned, and consists of HSize raster lines each of which
 *	contains an integral number of 16-bit data words.
 * Actual position of upper-left corner of miniraster is
 *	(CurX+Ch.HAdj, CurY+Ch.VAdj)
 * Each word of raster information is stored HIGH byte first, ala 68000.
 * Low order bit of first word is left-most raster point.  Bit 0 of first
 *   word thus corresponds to upper-left corner of character.
 *
 * HIncr and VIncr of space character (octal 040) correspond to default
 *   character and line spacing, respectively; these are used by some
 *   programs eg for tab and newline expansion.
 *
 * Format of .Vft files: each begins with a VFontHdr structure, followed
 *   an array of FONTSIZE (128) VCharDefs, followed by aggregated
 *   mini-raster data.  Thus a program may read the initial portion
 *   of the file to get per-character summary data, or may read the entire
 *   file in a single operation in order to load a complete font.
 */
cter (octal 040) correspond to default
 *   character and line spacing, respectively; these are used by some
 *   programs eg for tab and newline expansion.
 *
 * Format of .Vft files: each begins with a VFontHdr structure, followed
 *   an array of FONTSIZE (128) VCharDefs, followed by aggregated
 *   mini-raster data.  Thus alib86/include/a.out.h                                                                                  644     140      12         5103  3347424410   7643                                                                                                                                                                                                                                                                                                                                                                      /*
 * Header prepended to each a.out file.
 */
struct exec {
	long	a_magic;	/* magic number */
unsigned long	a_text;		/* size of text segment */
unsigned long	a_data;		/* size of initialized data */
unsigned long	a_bss;		/* size of uninitialized data */
unsigned long	a_syms;		/* size of symbol table */
unsigned long	a_entry;	/* entry point */
unsigned long	a_trsize;	/* size of text relocation */
unsigned long	a_drsize;	/* size of data relocation */
};

#define	OMAGIC	0407		/* old impure format */
#define	NMAGIC	0410		/* read-only text */
#define	ZMAGIC	0413		/* demand load format */

/*
 * Macros which take exec structures as arguments and tell whether
 * the file has a reasonable magic number or offsets to text|symbols|strings.
 */
#define	N_BADMAG(x) \
    (((x).a_magic)!=OMAGIC && ((x).a_magic)!=NMAGIC && ((x).a_magic)!=ZMAGIC)

#define	N_TXTOFF(x) \
	((x).a_magic==ZMAGIC ? 1024 : sizeof (struct exec))
#define N_SYMOFF(x) \
	(N_TXTOFF(x) + (x).a_text+(x).a_data + (x).a_trsize+(x).a_drsize)
#define	N_STROFF(x) \
	(N_SYMOFF(x) + (x).a_syms)

/*
 * Format of a relocation datum.
 */
struct relocation_info {
	long	r_address;	/* address which is relocated */
unsigned int	r_symbolnum:16,	/* local symbol ordinal */
		r_crap:8,	/* high symbolnum, set to zero (SAW)	*/
		r_pcrel:1, 	/* was relocated pc relative already */
		r_length:2,	/* 0=byte, 1=word, 2=long */
		r_extern:1,	/* does not include value of sym referenced */
		:4;		/* nothing, yet */
};

/*
 * Format of a symbol table entry; this file is included by <a.out.h>
 * and should be used if you aren't interested the a.out header
 * or relocation information.
 */
struct	nlist {
	union {
		char	*n_name;	/* for use when in-core */
		long	n_strx;		/* index into file string table */
	} n_un;
unsigned char	n_type;		/* type flag, i.e. N_TEXT etc; see below */
	char	n_other;	/* unused */
	short	n_desc;		/* see <stab.h> */
unsigned long	n_value;	/* value of this symbol (or sdb offset) */
};
#define	n_hash	n_desc		/* used internally by ld */

/*
 * Simple values for n_type.
 */
#define	N_UNDF	0x0		/* undefined */
#define	N_ABS	0x2		/* absolute */
#define	N_TEXT	0x4		/* text */
#define	N_DATA	0x6		/* data */
#define	N_BSS	0x8		/* bss */
#define	N_COMM	0x12		/* common (internal to ld) */
#define	N_FN	0x1f		/* file name symbol */

#define	N_EXT	01		/* external bit, or'ed in */
#define	N_TYPE	0x1e		/* mask for all the type bits */

/*
 * Sdb entries have some of the N_STAB bits set.
 * These are given in <stab.h>
 */
#define	N_STAB	0xe0		/* if any of these bits set, a SDB entry */

/*
 * Format for namelist values.
 */
#define	N_FORMAT	"%08x"
solute */
#define	N_TEXT	0x4		/* text */
#define	N_DATA	0x6		/* data */
#define	N_BSS	0x8		/* bss */
#define	N_COMM	0x12		/* common (internal to ld) */
#define	N_FN	0x1f		/* file name symbol */

#define	N_EXT	01		/* external bit, or'ed in */
#define	N_TYPE	0x1e		/* mask for all the type bits */

/*
 * Sdb entries have some of the N_STAB bits set.
 * These are given in <stab.h>
 */
#define	N_STAB	0xe0		/* if any of these bits set, a SDB entrylib86/include/ar.h                                                                                     644     140      12          324  3347424410   7177                                                                                                                                                                                                                                                                                                                                                                      #define	ARMAG	"!<arch>\n"
#define	SARMAG	8

#define	ARFMAG	"`\n"

struct ar_hdr {
	char	ar_name[16];
	char	ar_date[12];
	char	ar_uid[6];
	char	ar_gid[6];
	char	ar_mode[8];
	char	ar_size[10];
	char	ar_fmag[2];
};
ld) */
#define	N_FN	0x1f		/* file name symbol */

#define	N_EXT	01		/* external bit, or'ed in */
#define	N_TYPE	0x1e		/* mask for all the type bits */

/*
 * Sdb entries have some of the N_STAB bits set.
 * These are given in <s        ØÕÿ¼Õÿ«H        ä            ,ÖÿðÕÿû/         ,ÖÿôÕÿlib86/include/assert.h                                                                                 644     140      12          471  3347424411  10102                                                                                                                                                                                                                                                                                                                                                                      # ifndef NDEBUG
# define _assert(ex) {if (!(ex)){fprintf(stderr,"Assertion failed: file %s, line %d\n", __FILE__, __LINE__);exit(1);}}
# define assert(ex) {if (!(ex)){fprintf(stderr,"Assertion failed: file %s, line %d\n", __FILE__, __LINE__);exit(1);}}
# else
# define _assert(ex) ;
# define assert(ex) ;
# endif
ine	N_TYPE	0x1e		/* mask for all the type bits */

/*
 * Sdb entries have some of the N_STAB bits set.
 * These are given in <s        ØÕÿ¼Õÿ«H        ä            ,ÖÿðÕÿû/         ,ÖÿôÕÿlib86/include/core.h                                                                                   644     140      12          213  3347424411   7523                                                                                                                                                                                                                                                                                                                                                                      /* machine dependent stuff for core files */
#define TXTRNDSIZ 8192L
#define stacktop(siz) (0x10000L)
#define stackbas(siz) (0x10000L-siz)
fine assert(ex) {if (!(ex)){fprintf(stderr,"Assertion failed: file %s, line %d\n", __FILE__, __LINE__);exit(1);}}
# else
# define _assert(ex) ;
# define assert(ex) ;
# endif
ine	N_TYPE	0x1e		/* mask for all the type bits */

/*
 * Sdb entries have some of the N_STAB bits set.
 * These are given in <s        ØÕÿ¼Õÿ«H        ä            ,ÖÿðÕÿû/         ,ÖÿôÕÿlib86/include/ctype.h                                                                                  644     140      12         1160  3347424411   7741                                                                                                                                                                                                                                                                                                                                                                      #define	_U	01
#define	_L	02
#define	_N	04
#define	_S	010
#define _P	020
#define _C	040

extern	char	_ctype_[];

#define	isalpha(c)	((_ctype_+1)[c]&(_U|_L))
#define	isupper(c)	((_ctype_+1)[c]&_U)
#define	islower(c)	((_ctype_+1)[c]&_L)
#define	isdigit(c)	((_ctype_+1)[c]&_N)
#define	isspace(c)	((_ctype_+1)[c]&_S)
#define ispunct(c)	((_ctype_+1)[c]&_P)
#define isalnum(c)	((_ctype_+1)[c]&(_U|_L|_N))
#define isprint(c)	((_ctype_+1)[c]&(_P|_U|_L|_N))
#define iscntrl(c)	((_ctype_+1)[c]&_C)
#define isascii(c)	((unsigned)(c)<=0177)
#define toupper(c)	((c)-'a'+'A')
#define tolower(c)	((c)-'A'+'a')
#define toascii(c)	((c)&0177)
#define	isalpha(c)	((_ctype_+1)[c]&(_U|_L))
#define	isupper(c)	((_ctype_+1)[c]&_U)
#define	islower(c)	((_ctype_+1)[c]&_L)
#define	isdigit(c)	((_ctype_+1)[c]&_N)
#define	isspace(c)	((_ctype_+1)[c]&_S)
#define ispunct(c)	((_ctype_+1)[c]&_P)
#define isalnum(c)	((_ctype_+1)[c]&(_U|_L|_N))
#define isprint(c)	((_ctype_+1)[c]&(_P|_U|_L|_N))
#define iscntrl(c)	((_ctype_+1)[c]&_C)
#define isascii(c)	((unsilib86/include/dk.h                                                                                     644     140      12          370  3347424411   7175                                                                                                                                                                                                                                                                                                                                                                      /*
 * switch commands
 */
#define	RAM_ON	0226
#define	ROM_ON	0322
#define	R_CNTL	0264
#define	W_CNTL	0170

/*
 * dk command channel mode
 */
#define	DKCMD	04000

/*
 * library routine declarations
 */
extern long cmread();
extern long ocmread();


t(c)	((_ctype_+1)[c]&_N)
#define	isspace(c)	((_ctype_+1)[c]&_S)
#define ispunct(c)	((_ctype_+1)[c]&_P)
#define isalnum(c)	((_ctype_+1)[c]&(_U|_L|_N))
#define isprint(c)	((_ctype_+1)[c]&(_P|_U|        ØÕÿ¼Õÿ«H        ä            ,ÖÿðÕÿû/         ,ÖÿôÕÿlib86/include/dumprestor.h                                                                             644     140      12         1004  3347424411  11016                                                                                                                                                                                                                                                                                                                                                                      #define NTREC   	20
#define MLEN    	16
#define MSIZ    	4096

#define TS_TAPE 	1
#define TS_INODE	2
#define TS_BITS 	3
#define TS_ADDR 	4
#define TS_END  	5
#define TS_CLRI 	6
#define MAGIC   	(int)60011
#define CHECKSUM	(int)84446
struct	spcl
{
	int	c_type;
	time_t	c_date;
	time_t	c_ddate;
	int	c_volume;
	daddr_t	c_tapea;
	ino_t	c_inumber;
	int	c_magic;
	int	c_checksum;
	struct	dinode	c_dinode;
	int	c_count;
	char	c_addr[BSIZE];
} spcl;

struct	idates
{
	char	id_name[16];
	char	id_incno;
	time_t	id_ddate;
};
ine NTREC   	20
#define MLEN    	16
#define MSIZ    	4096

#define TS_TAPE 	1
#define TS_INODE	2
#define TS_BITS 	3
#define TS_ADDR 	4
#define TS_END  	5
#define TS_CLRI 	6
#define MAGIC   	(int)60011
#define CHECKSUM	(int)84446
struct	spcl
{
	int	c_type;
	time_t	c_date;
	time_t	c_ddate;
	int	c_volume;
	daddr_t	c_tapea;
	ino_t	c_inumber;
	int	c_magic;
	int	c_checksum;
	struct	dinode	c_dinode;
	int	c_count;
	char	c_addr[BSIZE];
} spcl;

struct	idates
{
	char	id_name[16];
	char	id_incno;
	time_t	id_ddate;lib86/include/errno.h                                                                                  644     140      12         1173  3347424411   7746                                                                                                                                                                                                                                                                                                                                                                      /*
 * Error codes
 */

#define	EPERM	1
#define	ENOENT	2
#define	ESRCH	3
#define	EINTR	4
#define	EIO	5
#define	ENXIO	6
#define	E2BIG	7
#define	ENOEXEC	8
#define	EBADF	9
#define	ECHILD	10
#define	EAGAIN	11
#define	ENOMEM	12
#define	EACCES	13
#define	EFAULT	14
#define	ENOTBLK	15
#define	EBUSY	16
#define	EEXIST	17
#define	EXDEV	18
#define	ENODEV	19
#define	ENOTDIR	20
#define	EISDIR	21
#define	EINVAL	22
#define	ENFILE	23
#define	EMFILE	24
#define	ENOTTY	25
#define	ETXTBSY	26
#define	EFBIG	27
#define	ENOSPC	28
#define	ESPIPE	29
#define	EROFS	30
#define	EMLINK	31
#define	EPIPE	32

/* math software */
#define	EDOM	33
#define	ERANGE	34
ne	E2BIG	7
#define	ENOEXEC	8
#define	EBADF	9
#define	ECHILD	10
#define	EAGAIN	11
#define	ENOMEM	12
#define	EACCES	13
#define	EFAULT	14
#define	ENOTBLK	15
#define	EBUSY	16
#define	EEXIST	17
#define	EXDEV	18
#define	ENODEV	19
#define	ENOTDIR	20
#define	EISDIR	21
#define	EINVAL	22
#define	ENFILE	23
#define	EMFILE	24
#define	ENOTTY	25
#define	ETXTBSY	26
#define	EFBIG	27
#define	ENOSPC	28
#dlib86/include/execargs.h                                                                               644     140      12           60  3347424411  10354                                                                                                                                                                                                                                                                                                                                                                      char **execargs = (char **)((USRTOP*400L) - 4);
31
#define	EPIPE	32

/* math software */
#define	EDOM	33
#define	ERANGE	34
ne	E2BIG	7
#define	ENOEXEC	8
#define	EBADF	9
#define	ECHILD	10
#define	EAGAIN	11
#define	ENOMEM	12
#define	EACCES	13
#define	EFAULT	14
#define	ENOTBLK	15
#define	EBUSY	16
#define	EEXIST	17
#define	EXDEV	18
#define	ENODEV	19
#define	ENOTDIR	20
#define	EISDIR	21
#define	EINVAL	22
#define	ENFILE	23
#define	EMFILE	24
#d        ØÕÿ¼Õÿ«H        ä            ,ÖÿðÕÿû/         ,ÖÿôÕÿlib86/include/ft.h                                                                                     644     140      12         4567  3347424411   7244                                                                                                                                                                                                                                                                                                                                                                      /* Definition of .ft format file:	10/80 Steve Ward
 * Updated 7/16/81 SAW
 */

struct CharDef
 { char HSize;		/* Horizontal size, in bits (unsigned)		*/
   char VSize;		/* Vertical size, in bits (unsigned)		*/
   char HAdj;		/* Horizontal position adjustment (signed)	*/
   char VAdj;		/* Vertical position adjustment (signed)	*/
   char HIncr;		/* Horizontal position increment (unsigned)	*/
   char VIncr;		/* Vertical position increment (unsigned)	*/
   unsigned short Raster;/* relative pointer to Mini-raster --		*/
 };

/* Given a pointer p to a CharDef,
 *	(short *)	CharRaster(p)	gives a pointer to the character's
 *					mini-raster;
 *	(short)		RasterSize(p)	gives the size of the character's
 *					mini-raster, in bytes (calculated
 *					from VSize, HSize as below).
 */

#define	CharRaster(p)	(((char *)&((p)->Raster))+((p)->Raster))
#define	RasterSize(p)	((((p)->VSize)*((((p)->HSize)+15)>>4))<<1)
#define	FONTSIZE	128		/* Number of characters in a font   */

/* Size of Raster is Ch.VSIZE*((Ch.HSize+15) >> 4), in 16-bit words.
 * N.B: Raster is dealt with as 16-bit words; hence it must be
 *	word-aligned, and consists of HSize raster lines each of which
 *	contains an integral number of 16-bit data words.
 * Actual position of upper-left corner of miniraster is
 *	(CurX+Ch.HAdj, CurY+Ch.VAdj)
 * Each word of raster information is stored HIGH byte first, ala 68000.
 * Low order bit of first word is left-most raster point.  Bit 0 of first
 *   word thus corresponds to upper-left corner of character.
 *
 * HIncr and VIncr of space character (octal 040) correspond to default
 *   character and line spacing, respectively; these are used by some
 *   programs eg for tab and newline expansion.
 *
 * Format of .ft files: each begins with an array of FONTSIZE (viz. 128)
 *   CharDefs, followed by aggregated mini-raster data.  Thus a program
 *   may read simply the initial portion of the file to get per-character
 *   summary data, or may read the entire file in a single operation in
 *   order to load a complete font.
 */

/*	Additional notes on .ft format		Bern Niamir (5/81)
 * The actual bit pattern of the character is flush left of the miniraster.
 * The bits to the right of the pattern (i.e. to the right of HSize)
 *   and before the short boundary must be 0 (in order that VidChr to work
 *   correctly.
 * Vadj is normally negative, implying that coordinate (0, 0) is upper left.
 */
e file to get per-character
 *   summary data, or may read the entire file in a single operation in
 *   order to load a complete font.
 lib86/include/graphl.h                                                                                 644     140      12         3514  3347424412  10100                                                                                                                                                                                                                                                                                                                                                                      /* Definitions for graphics library graphl.b:		Steve Ward 6/80
 *
 * Raster coordinates: (0, 0) is upper left-hand corner of screen.
 * 		       (800, 1023) is lower-right.
 */

extern short	VideoX,		/* Current X position			*/
		VideoY,		/* Current Y position			*/
		VideoM;		/* Current screen mode			*/

/* VideoM modes:							*/
#define	VID_SET	1		/* Set bits (OR onto screen)		*/
#define	VID_CLR 2		/* Clear bits				*/
#define	VID_XOR	3		/* Complement bits			*/

extern VidChr();

/* Put character Ch at current cursor location, using current screen mode.
 * VidChr(Ch); struct CharDef *Ch;
 */

/*extern struct CharDef
/* { char HSize;		/* Horizontal size, in bits (unsigned)		*/
/*   char VSize;		/* Vertical size, in bits (unsigned)		*/
/*   char HAdj;		/* Horizontal position adjustment (signed)	*/
/*   char VAdj;		/* Vertical position adjustment (signed)	*/
/*   char HIncr;		/* Horizontal position increment (unsigned)	*/
/*   char VIncr;		/* Vertical position increment (unsigned)	*/
/*   short Raster;	/* relative pointer to Mini-raster --		*/
/* } *VideoF;		/* Current font pointer [128]			*/

/* Size of Raster is Ch.VSIZE*((Ch.HSize+15) >> 4), in 16-bit words.
 * N.B: Raster is dealt with as 16-bit words; hence it must be
 *	word-aligned, and consists of HSize raster lines each of which
 *	contains an integral number of 16-bit data words.
 * Actual position of upper-left corner of miniraster is
 *	(VideoX+Ch.HAdj, VideoY+Ch.VAdj)
 * Updates VideoX, VideoY by CH.HIncr, Ch.VIncr.
 */

extern	VidMov();	/* VidMov(x, y) -- move to (x, y)	*/
extern	VidCnt();	/* VidCnt(dx, dy) -- draw a vector	*/

extern	VidPos();	/* VidPos(col, row) -- move to char posn*/
extern	VidFont();	/* VidFont(&Font) -- change fonts	*/
extern	VidPut();	/* VidPut(ch) -- output a character	*/
extern short VideoRow,	/* Number of rows, columns for cur. font*/
	     VideoCol;
.
 * Actual position of upper-left corner of miniraster is
 *	(VideoX+Ch.HAdj, VideoY+Ch.VAdj)
 * Updates VideoX, VideoY by CH.HIncr, Ch.VIncr.
 */

extern	VidMov();	/* VidMov(x, ylib86/include/grp.h                                                                                    644     140      12          147  3347424412   7372                                                                                                                                                                                                                                                                                                                                                                      struct	group { /* see getgrent(3) */
	char	*gr_name;
	char	*gr_passwd;
	int	gr_gid;
	char	**gr_mem;
};
os(col, row) -- move to char posn*/
extern	VidFont();	/* VidFont(&Font) -- change fonts	*/
extern	VidPut();	/* VidPut(ch) -- output a character	*/
extern short VideoRow,	/* Number of rows, columns for cur. font*/
	     VideoCol;
.
 * Actual position of upper-left corner of miniraster is
 *	(VideoX+Ch.HAdj, VideoY+Ch.VAdj)
 * Updates Vi        ØÕÿ¼Õÿ«H        ä            ,ÖÿðÕÿû/         ,ÖÿôÕÿlib86/include/ident.h                                                                                  644     140      12           42  3347424412   7657                                                                                                                                                                                                                                                                                                                                                                      char myname[] = "research 11/70";
*/
	char	*gr_name;
	char	*gr_passwd;
	int	gr_gid;
	char	**gr_mem;
};
os(col, row) -- move to char posn*/
extern	VidFont();	/* VidFont(&Font) -- change fonts	*/
extern	VidPut();	/* VidPut(ch) -- output a character	*/
extern short VideoRow,	/* Number of rows, columns for cur. font*/
	     VideoCol;
.
 * Actual position of upper-left corner of miniraster is
 *	(VideoX+Ch.HAdj, VideoY+Ch.VAdj)
 * Updates Vi        ØÕÿ¼Õÿ«H        ä            ,ÖÿðÕÿû/         ,ÖÿôÕÿlib86/include/int.h                                                                                    644     140      12          557  3347424412   7401                                                                                                                                                                                                                                                                                                                                                                      /* header for interrupt hackery -- see lib86/sys/handler.a86 for details */

struct Int {
  int intnumber;	/* which interrupt we're handling */
  int oldip,oldcs;	/* what used to be the vector */
  int ip;		/* points to user's interrupt routine */
  int arg;		/* argument to user's interrupt routine */
  int istack[100];	/* interrupt stack and handler routine */
};
corner of miniraster is
 *	(VideoX+Ch.HAdj, VideoY+Ch.VAdj)
 * Updates Vi        ØÕÿ¼Õÿ«H        ä            ,ÖÿðÕÿû/         ,ÖÿôÕÿlib86/include/ioctl.h                                                                                  644     140      12        12763  3347424412   7763                                                                                                                                                                                                                                                                                                                                                                      /*	ioctl.h	4.2	12/17/80	*/
/*
 * ioctl definitions, and special character and local tty definitions
 */
#ifndef	_IOCTL_
#define	_IOCTL_
struct tchars {
	char	t_intrc;	/* interrupt */
	char	t_quitc;	/* quit */
	char	t_startc;	/* start output */
	char	t_stopc;	/* stop output */
	char	t_eofc;		/* end-of-file */
	char	t_brkc;		/* input delimiter (like nl) */
};
struct ltchars {
	char	t_suspc;	/* stop process signal */
	char	t_dsuspc;	/* delayed stop process signal */
	char	t_rprntc;	/* reprint line */
	char	t_flushc;	/* flush output (toggles) */
	char	t_werasc;	/* word erase */
	char	t_lnextc;	/* literal next character */
	char	t_clearc;	/* clear screen char */
};

/*
 * local mode settings
 */
#define	LCRTBS	01		/* correct backspacing for crt */
#define	LPRTERA 02		/* printing terminal \ ... / erase */
#define	LCRTERA	04		/* do " \b " to wipe out character */
#define	LTILDE	010		/* IIASA - hazeltine tilde kludge */
#define	LMDMBUF	020		/* IIASA - start/stop output on carrier intr */
#define	LLITOUT	040		/* IIASA - suppress any output translations */
#define	LTOSTOP	0100		/* send stop for any background tty output */
#define	LFLUSHO	0200		/* flush output sent to terminal */
#define	LNOHANG 0400		/* IIASA - don't send hangup on carrier drop */
#define	LETXACK 01000		/* IIASA - diablo style buffer hacking */
#define	LCRTKIL	02000		/* erase whole line on kill with " \b " */
#define	LINTRUP 04000		/* interrupt on every input char - SIGTINT */
#define	LCTLECH	010000		/* echo control characters as ^X */
#define	LPENDIN	020000		/* tp->t_rawq is waiting to be reread */

/* local state */
#define	LSBKSL	01		/* state bit for lowercase backslash work */
#define	LSQUOT	02		/* last character input was \ */
#define	LSERASE	04		/* within a \.../ for LPRTRUB */
#define	LSLNCH	010		/* next character is literal */
#define	LSTYPEN	020		/* retyping suspended input (LPENDIN) */
#define	LSCNTTB	040		/* counting width of tab; leave LFLUSHO alone */

/*
 * tty ioctl commands
 */
#define	TIOCGETD	(('t'<<8)|0)	/* get line discipline */
#define	TIOCSETD	(('t'<<8)|1)	/* set line discipline */
#define	TIOCHPCL	(('t'<<8)|2)	/* set hangup line on close bit */
#define	TIOCMODG	(('t'<<8)|3)	/* modem bits get (???) */
#define	TIOCMODS	(('t'<<8)|4)	/* modem bits set (???) */
#define	TIOCGETP	(('t'<<8)|8)	/* get parameters - like old gtty */
#define	TIOCSETP	(('t'<<8)|9)	/* set parameters - like old stty */
#define	TIOCSETN	(('t'<<8)|10)	/* set params w/o flushing buffers */
#define	TIOCEXCL	(('t'<<8)|13)	/* set exclusive use of tty */
#define	TIOCNXCL	(('t'<<8)|14)	/* reset exclusive use of tty */
#define	TIOCFLUSH	(('t'<<8)|16)	/* flush buffers */
#define	TIOCSETC	(('t'<<8)|17)	/* set special characters */
#define	TIOCGETC	(('t'<<8)|18)	/* get special characters */
#define	TIOCIOANS	(('t'<<8)|20)
#define	TIOCSIGNAL	(('t'<<8)|21)
#define	TIOCUTTY	(('t'<<8)|22)
/* locals, from 127 down */
#define	TIOCLBIS	(('t'<<8)|127)	/* bis local mode bits */
#define	TIOCLBIC	(('t'<<8)|126)	/* bic local mode bits */
#define	TIOCLSET	(('t'<<8)|125)	/* set entire local mode word */
#define	TIOCLGET	(('t'<<8)|124)	/* get local modes */
#define	TIOCSBRK	(('t'<<8)|123)	/* set break bit */
#define	TIOCCBRK	(('t'<<8)|122)	/* clear break bit */
#define	TIOCSDTR	(('t'<<8)|121)	/* set data terminal ready */
#define	TIOCCDTR	(('t'<<8)|120)	/* clear data terminal ready */
#define	TIOCGPGRP	(('t'<<8)|119)	/* get pgrp of tty */
#define	TIOCSPGRP	(('t'<<8)|118)	/* set pgrp of tty */
#define	TIOCSLTC	(('t'<<8)|117)	/* set local special characters */
#define	TIOCGLTC	(('t'<<8)|116)	/* get local special characters */
#define	TIOCOUTQ	(('t'<<8)|115)	/* number of chars in output queue */
#define	TIOCSTI		(('t'<<8)|114)	/* simulate a terminal in character */

#define	OTTYDISC	0		/* old, v7 std tty driver */
/* #define	NETLDISC	1		/* line discip for berk net */
#define KEYDISC		1		/* AI keyboard, old tty discipline */
#define	NTTYDISC	2		/* new tty discipline */
#define NKEYDISC	3		/* AI keyboard, new tty discipline */
/* #define	PKDISC		3		/* packet driver */
/* #define	TRDISC		4		/* datakit trailer protocol */
/* #define	TDKDISC		5		/* datakit terminal protocol */

#define	DIOCLSTN	(('d'<<8)|1)
#define	DIOCMD		(('d'<<8)|2)
#define	DIOCMPX		(('d'<<8)|3)
#define	DIOCNMPX	(('d'<<8)|4)
#define	DIOCSCALL	(('d'<<8)|5)
#define	DIOCRCALL	(('d'<<8)|6)
#define	DIOCPGRP	(('d'<<8)|7)
#define	DIOCGETP	(('d'<<8)|8)
#define	DIOCSETP	(('d'<<8)|9)
#define	DIOCLOSE	(('d'<<8)|10)
#define	DIOCTIME	(('d'<<8)|11)
#define	DIOCRESET	(('d'<<8)|12)
#define	DIOCSMETA	(('d'<<8)|13)
#define	DIOCMERGE	(('d'<<8)|14)
#define	DIOCICHAN	(('d'<<8)|15)
#define	DIOCUMERGE	(('d'<<8)|16)
#define	DIOCRMETA	(('d'<<8)|17)
#define	DIOCXOUT	(('d'<<8)|18)
#define	DIOCBMETA	(('d'<<8)|19)
#define	DIOCAMETA	(('d'<<8)|20)
#define	DIOCSBMETA	(('d'<<8)|21)
#define	DIOCLOOP	(('d'<<8)|22)
#define	DIOCPROTOCOL	(('d'<<8)|23)
#define	DIOCTRL		(('d'<<8)|24)
#define	DIOCDMETA	(('d'<<8)|25)
#define	DIOCSWR		(('d'<<8)|26)

#define	FIOCLEX		(('f'<<8)|1)
#define	FIONCLEX	(('f'<<8)|2)
/* another local */
#define	FIONREAD	(('f'<<8)|127)	/* get # bytes to read */

/* mag tape io control commands */
#define MTIOCTOP	(('m'<<8)|1)	/* do a mag tape op (see <mtio.h>) */
#define MTIOCGET	(('m'<<8)|2)	/* get mag tape status (see <mtio.h>*/

/* mux io controls */
#define	MXLSTN		(('x'<<8)|1)
#define	MXNBLK		(('x'<<8)|2)

#ifdef notdef
/* varian ioctls, which are defined in sys/vcmd.h */
#define	VGETSTATE	(('v'<<8)|0)
#define	VSETSTATE	(('v'<<8)|1)
#endif

/* printer ioctls, see <lpio.h> */
#define	LGETSTATE	(('v'<<8)|2)
#define	LSETSTATE	(('v'<<8)|3)
#endif
ytes to read lib86/include/math.h                                                                                   644     140      12          544  3347424412   7534                                                                                                                                                                                                                                                                                                                                                                      extern double fabs(), floor(), ceil(), fmod(), ldexp();
extern double sqrt(), hypot(), atof();
extern double sin(), cos(), tan(), asin(), acos(), atan(), atan2();
extern double exp(), log(), log10(), pow();
extern double sinh(), cosh(), tanh();
extern double gamma();
extern double j0(), j1(), jn(), y0(), y1(), yn();

#define HUGE	1.701411733192644270e38
#define	VSETSTATE	(('v'<<8)|1)
#endif

/* printer ioctls, see <lpio.h> */
#define	LG        ØÕÿ¼Õÿ«H        ä            ,ÖÿðÕÿû/         ,ÖÿôÕÿlib86/include/olddump.h                                                                                644     140      12         2555  3347424412  10273                                                                                                                                                                                                                                                                                                                                                                      #define MAXSIZE	500		/* max size in blocks of dumped files */
#define NILIST	100		/* max files extracted at once */
#define BFACT	20		/* tape blocking factor */

int tden 1600;			/* tape density */
int tlen 2200;			/* tape length (feet) */

char *dump_cmd[] = {		/* default args for dump */
	"dump",
	"i",
	"/dev/rp0",
	0
};

char *rest_cmd[] = {		/* defaults for restor */
	"restor",
	"t",
	0
};

char	*tape	"/dev/rmt1";
char	dfile[]	"/dev/dtab";
char	tfile[]	"/tmp/dtmp";
char	name[100];

#define NDTAB	10
struct {
	char	dt_name[16];
	time_t	dt_date;
} dtab[NDTAB];

struct thdr {
	ino_t	isize;
	ino_t	maxi;
	daddr_t	fsize;
	time_t	cdate;
	time_t	ddate;
	long	tsize;
	int	nflg;
};

struct fhdr {
	short	xmagic;
	ino_t	xino;
	short	xmode;
	short	xnlink;
	short	xuid;
	short	xgid;
	daddr_t	xaddr;
	off_t	xsize;
	time_t	xatime;
	time_t	xmtime;
	time_t	xctime;
};
#define	FMAGIC	012345
#define	SMAGIC	031415

#define DAPTB	127	/* (BSIZE-2*sizeof(short))/sizeof(daddr_t)) */

FILE	*tmpf;

long
getsize()
{
	register c;
	long j;

	c = getc(tmpf);
	if(c == EOF)
		return((long)-1);
	if(c <= 253)
		return((long)c);
	if(c == 255)
		return((long)-1);
	j = 0;
	for(c=0;c<3;c++)
		j = (j<<8) + (getc(tmpf)&0377);
	return(j);
}

putsize(s)
long	s;
{
	if(s <= 253) {
		putc((char)s, tmpf);
		return;
	}
	putc(254, tmpf);
	putc((char)(s>>16), tmpf);
	putc((char)(s>>8), tmpf);
	putc((char)s, tmpf);
}
012345
#define	SMAGIC	031415

#define DAPTB	127	/* (BSIZE-2*sizeof(short))/sizeof(daddr_t)) */

FILE	*tmpf;

long
getsize()
{
	register c;
	long j;lib86/include/pack.h                                                                                   644     140      12         4233  3347424413   7541                                                                                                                                                                                                                                                                                                                                                                      struct header {
	char	sync;
	char	ksize;
	unsigned short	sum;
	char	cntl;
	char	ccntl;
};
#define	HDRSIZ	6

struct pack {
	short	p_state;	/* line state */
	short	p_bits;		/* mask for getepack */
	short	p_rsize;	/* input packet size */
	short	p_xsize;	/* output packet size */
	struct	header p_ihbuf;	/* input header */
	struct	header p_ohbuf; /* output header */
	char	*p_rptr;
	char	p_mode;
	char	**p_ipool;
	char	p_xcount;	/* # active output buffers */
	char	p_rcount;
	char	p_nout,p_tout;
	char	p_lpsize;	/* log(psize/32) */
	char	p_timer;
	char	p_obusy;
	char	p_srxmit;
	char	p_rwindow;	/* window size */
	char	p_swindow;
	char	p_msg;		/* control msg */
	char	p_rmsg;		/* repeated control msg */
	char	p_ps,p_pr;	/* last packet sent, recv'd */
	char	p_rpr;
	char	p_nxtps;	/* next output seq number */
	char	p_imap;		/* bit map of input buffers */
	char	p_pscopy;	/* newest output packet */
	char	*p_ob[8];	/* output buffers */
	char	*p_ib[8];	/* input buffers */
	char	p_os[8];	/* output buffer status */
	char	p_is[8];	/* input buffer status */
	short	p_osum[8];	/* output checksums */
	short	p_isum[8];	/* input checksums */
	DSYSTEM;
};
#define	CHECK	0125252
#define	SYN	020
#define	MOD8	7
#define	ISCNTL(a)	((a & 0300)==0)
#define	MIN(a,b)	((a<b)? a:b)

char	next[8];
char	mask[8];
int	npbits;
int	pkactive;

/*
 * driver state
 */
#define	DEAD	0
#define	INITa	1
#define	INITb	2
#define	INITab	3
#define	LIVE	010
#define	RXMIT	020
#define	RREJ	040
#define PDEBUG	0200
#define	DRAINO	0400
#define	WAITO	01000
#define	DOWN	02000
#define	RCLOSE	04000
#define	BADFRAME 020000

/*
 * io buffer states
 */
#define	B_NULL	0
#define	B_READY	1
#define	B_SENT	2
#define	B_RESID	010
#define	B_COPY	020
#define	B_MARK	040
#define	B_SHORT	0100

/*
 * control messages
 */
#define	CLOSE	1
#define	RJ	2
#define	SRJ	3
#define	RR	4
#define	INITC	5
#define	INITB	6
#define	INITA	7

#define	M_RJ	4
#define	M_SRJ	010
#define	M_RR	020
#define	M_INITC	040
#define	M_CLOSE	2
#define	M_INITA	0200
#define	M_INITB	0100



#define	PKOPRI	31
#define	PKIPRI	30

#define	NPLINES	8

/*
 * packet ioctl buf
 */
struct	piocb {
	unsigned t;
	short	psize;
	short	mode;
	short	state;
	char	window;
};

int pkdebug;
int pksizes[];
OPY	020
#define	B_MARK	040
#define	B_SHORT	0100

/*
 * control messages
 */
#define	CLOSE	1
#define	RJ	2
#define	SRJ	3
#define	RR	4
#define	INITC	5
#define	INITB	6
#define	INITA	7

#define	M_RJ	4
#define	M_SRJ	010
#define	M_RR	020
#define	M_INITC	040
#define	M_CLOSE	2
#define	M_INITA	0200
#define	M_INITB	0100



#define	PKOPRI	31
#define	PKIPRI	30

#definlib86/include/pagsiz.h                                                                                 644     140      12          274  3347424413  10101                                                                                                                                                                                                                                                                                                                                                                      #define	NBPG	512
#define	PGOFSET	511
#define	CLSIZE	2
#define	CLOFSET	1023
#define	BSIZE	1024
#define	BMASK	1023
#define	BSHIFT	10
#define	PAGSIZ	(NBPG*CLSIZE)
#define	PAGRND	((PAGSIZ)-1)
e	B_SHORT	0100

/*
 * control messages
 */
#define	CLOSE	1
#define	RJ	2
#define	SRJ	3
#define	RR	4
#define	INITC	5
#define	INITB	6
#define	INITA	7

#define	M_RJ	4
#define	M_SRJ	010
#define	M_RR	020
#define	M_INITC	040
#define	M_CLOSE	2
#define	M_INITA	        ØÕÿ¼Õÿ«H        ä            ,ÖÿðÕÿû/         ,ÖÿôÕÿlib86/include/pwd.h                                                                                    644     140      12          270  3347424413   7372                                                                                                                                                                                                                                                                                                                                                                      struct	passwd { /* see getpwent(3) */
	char	*pw_name;
	char	*pw_passwd;
	int	pw_uid;
	int	pw_gid;
	int	pw_quota;
	char	*pw_comment;
	char	*pw_gecos;
	char	*pw_dir;
	char	*pw_shell;
};
-1)
e	B_SHORT	0100

/*
 * control messages
 */
#define	CLOSE	1
#define	RJ	2
#define	SRJ	3
#define	RR	4
#define	INITC	5
#define	INITB	6
#define	INITA	7

#define	M_RJ	4
#define	M_SRJ	010
#define	M_RR	020
#define	M_INITC	040
#define	M_CLOSE	2
#define	M_INITA	        ØÕÿ¼Õÿ«H        ä            ,ÖÿðÕÿû/         ,ÖÿôÕÿlib86/include/ranlib.h                                                                                 644     140      12         1104  3347424413  10064                                                                                                                                                                                                                                                                                                                                                                      
/*
 * Structure of the __.SYMDEF table of contents for an archive.
 * __.SYMDEF begins with a word giving the number of ranlib structures
 * which immediately follow, and then continues with a string
 * table consisting of a word giving the number of bytes of strings
 * which follow and then the strings themselves.
 * The ran_strx fields index the string table whose first byte is numbered 0.
 */
struct	ranlib {
	union {
		off_t	ran_strx;	/* string table index of */
		char	*ran_name;	/* symbol defined by */
	} ran_un;
	off_t	ran_off;		/* library member at this offset */
};
 * __.SYMDEF begins with a word giving the number of ranlib structures
 * which immediately follow, and then continues with a string
 * table consisting of a word giving the number of bytes of strings
 * which follow and then the strings themselves.
 * The ran_strx fields index the string table whose first byte is numbered 0.
 */
struct	ranlib {
	union {
		off_t	ran_strx;	/* string table index of */
		char	*ran_name;	/* symbol defined by */lib86/include/saio.h                                                                                   644     140      12         1537  3347424413   7562                                                                                                                                                                                                                                                                                                                                                                      /*
 * header file for standalone package
 */

/*
 * io block: includes an
 * inode, cells for the use of seek, etc,
 * and a buffer.
 */
struct	iob {
	char	i_flgs;
	struct inode i_ino;
	int i_unit;
	daddr_t	i_boff;
	daddr_t	i_cyloff;
	off_t	i_offset;
	daddr_t	i_bn;
	char	*i_ma;
	int	i_cc;
	char	i_buf[512];
};

#define F_READ	01
#define F_WRITE	02
#define F_ALLOC	04
#define F_FILE	010




/*
 * dev switch
 */
struct devsw {
	char	*dv_name;
	int	(*dv_strategy)();
	int	(*dv_open)();
	int	(*dv_close)();
};

struct devsw devsw[];

/*
 * request codes. Must be the same a F_XXX above
 */
#define	READ	1
#define	WRITE	2


#define	NBUFS	4


char	b[NBUFS][512];
daddr_t	blknos[NBUFS];



#define NFILES	4
struct	iob iob[NFILES];

/*
 * Set to which 32Kw segment the code is physically running in.
 * Must be set by the users main (or there abouts).
 */
int	segflag;
efine F_ALLOC	04
#define F_FILE	010




/*
 * dev switch
 */
struct devsw {
	char	*dv_name;
	int	(*dv_strategy)();
	int	(*dv_open)();
	int	(*dv_close)();
};

strlib86/include/setjmp.h                                                                                 644     140      12           31  3347424413  10055                                                                                                                                                                                                                                                                                                                                                                      typedef int jmp_buf[13];
 request codes. Must be the same a F_XXX above
 */
#define	READ	1
#define	WRITE	2


#define	NBUFS	4


char	b[NBUFS][512];
daddr_t	blknos[NBUFS];



#define NFILES	4
struct	iob iob[NFILES];

/*
 * Set to which 32Kw segment the code is physically running in.
 * Must be set by the users main (or there abouts).
 */
int	segflag;
efine F_ALLOC	04
#define F_FILE	010




/*
 * dev switch
 */
struct devsw {
	char	*dv_nam        ØÕÿ¼Õÿ«H        ä            ,ÖÿðÕÿû/         ,ÖÿôÕÿlib86/include/sgtty.h                                                                                  644     140      12         2221  3347424413   7770                                                                                                                                                                                                                                                                                                                                                                      /*
 * Structure for stty and gtty system calls.
 */

struct sgttyb {
	char	sg_ispeed;		/* input speed */
	char	sg_ospeed;		/* output speed */
	char	sg_erase;		/* erase character */
	char	sg_kill;		/* kill character */
	int	sg_flags;		/* mode flags */
};

/*
 * Modes
 */
#define	TANDEM	01
#define	CBREAK	02
#define	LCASE	04
#define	ECHO	010
#define	CRMOD	020
#define	RAW	040
#define	ODDP	0100
#define	EVENP	0200
#define ANYP	0300
#define	NLDELAY	001400
#define	TBDELAY	006000
#define	XTABS	06000
#define	CRDELAY	030000
#define	VTDELAY	040000
#define BSDELAY 0100000
#define ALLDELAY 0177400

/*
 * Delay algorithms
 */
#define	CR0	0
#define	CR1	010000
#define	CR2	020000
#define	CR3	030000
#define	NL0	0
#define	NL1	000400
#define	NL2	001000
#define	NL3	001400
#define	TAB0	0
#define	TAB1	002000
#define	TAB2	004000
#define	FF0	0
#define	FF1	040000
#define	BS0	0
#define	BS1	0100000

/*
 * Speeds
 */
#define B0	0
#define B50	1
#define B75	2
#define B110	3
#define B134	4
#define B150	5
#define B200	6
#define B300	7
#define B600	8
#define B1200	9
#define	B1800	10
#define B2400	11
#define B4800	12
#define B9600	13
#define EXTA	14
#define EXTB	15

#include <ioctl.h>

ne	CR2	020000
#define	CR3	030000
#define	NL0	0
#define	NL1	000400
#define	NL2	001000
#define	NL3	001400
#define	TAB0	0
#define	TAB1	002000
#define	TAB2	004000
#define	FF0	0
#define	FF1	040000
#define	BS0	0
#define	BS1	0100000

/*
 * Speeds
 */
#define B0	0
#define B50	1
#define B75	2
#define B110	3
#define B134	4
#define B150	5
#define B200	6
#define B300	7
#definelib86/include/signal.h                                                                                 644     140      12         5237  3347424414  10106                                                                                                                                                                                                                                                                                                                                                                      #ifndef	NSIG
#define NSIG	32

#define	SIGHUP	1	/* hangup */
#define	SIGINT	2	/* interrupt */
#define	SIGQUIT	3	/* quit */
#define	SIGILL	4	/* illegal instruction (not reset when caught) */

#define	SIGTRAP	5	/* trace trap (not reset when caught) */
#define	SIGIOT	6	/* IOT instruction */
#define	SIGEMT	7	/* EMT instruction */
#define	SIGFPE	8	/* floating point exception */
#define		K_INT_OVF_T 0x1		/* integer overflow */
#define		K_INT_DIV_T 0x2		/* integer divide by zero */
#define		K_FLT_OVF_T 0x3		/* floating overflow */
#define		K_FLT_DIV_T 0x4		/* floating/decimal divide by zero */
#define		K_FLT_UND_T 0x5		/* floating underflow */
#define		K_DEC_OVF_T 0x6		/* decimal overflow */
#define		K_SUB_RNG_T 0x7		/* subscript out of range */
#define		K_FLT_OVF_F 0x8		/* floating overflow fault */
#define		K_FLT_DIV_F 0x9		/* divide by zero floating fault */
#define		K_FLT_UND_F 0xa		/* floating underflow fault */
#define	SIGKILL	9	/* kill (cannot be caught or ignored) */
#define	SIGBUS	10	/* bus error */
#define	SIGSEGV	11	/* segmentation violation */
#define	SIGSYS	12	/* bad argument to system call */
#define	SIGPIPE	13	/* write on a pipe with no one to read it */
#define	SIGALRM	14	/* alarm clock */
#define	SIGTERM	15	/* software termination signal from kill */

/* these signals are not yet supported on nunix */
/*#define	SIGSTOP	17	/* sendable stop signal not from tty */
/*#define	SIGTSTP	18	/* stop signal from tty */
/*#define	SIGCONT	19	/* continue a stopped process */
/*#define	SIGCHLD	20	/* to parent on child stop or exit */
/*#define	SIGTTIN	21	/* to readers pgrp upon background tty read */
/*#define	SIGTTOU	22	/* like TTIN for output if (tp->t_local&LTOSTOP) */
/*#define	SIGTINT	23	/* to pgrp on every input character if LINTRUP */
/*#define	SIGXCPU	24	/* exceeded CPU time limit */
/*#define	SIGXFSZ	25	/* exceeded file size limit */

#define SIGSTAT 26	/* status update requested */
#define SIGMOUS 27	/* mouse interrupt */

#ifndef KERNEL
int	(*signal())();
#endif

#define	BADSIG		(int (*)())-1
#define	SIG_DFL		(int (*)())0
#define	SIG_IGN		(int (*)())1
#ifdef KERNEL
#define	SIG_CATCH	(int (*)())2
#endif
#define	SIG_HOLD	(int (*)())3

#define	SIGISDEFER(x)	(((int)(x) & 1) != 0)
#define	SIGUNDEFER(x)	(int (*)())((int)(x) &~ 1)
#define	DEFERSIG(x)	(int (*)())((int)(x) | 1)

#define	SIGNUMMASK	0377		/* to extract pure signal number */
#define	SIGDOPAUSE	0400		/* do pause after setting action */
#define	SIGDORTI	01000		/* do ret+rti after setting action */
#endif

/* old fashioned unix stuff */
#ifdef KERNEL
#define SIGINS	SIGILL
#define SIGTRC	SIGTRAP
#define SIGFPT	SIGFPE
#define SIGKIL	SIGKILL
#define SIGSEG	SIGSEGV
#define SIGCLK	SIGALRM
#define SIGTRM	SIGTERM
#endif
) & 1) != 0)
#define	SIGUNDEFER(x)	(int (*)())((int)(x) &~ 1)
#define	DEFERSIG(x)	(int (*)())((int)(x) | 1)

#define	SIGNUMMASK	0377		/* to extract pure signal number */
#define	SIGDOPAUSE	0400		/* do pause after setting action */
#define	SIGDORTI	01000		/* do ret+rti after setting action */
#endif

/* old fashioned unix stuff */
#ifdef KERNEL
#definelib86/include/stat.h                                                                                   644      30      12         1663  3355662237   7567                                                                                                                                                                                                                                                                                                                                                                      typedef unsigned dev_t;
typedef long off_t;
typedef long time_t;

struct	stat
{
	dev_t	st_dev;
	unsigned short   	st_mode;
	short  	st_nlink;
	short  	st_uid;
	short  	st_gid;
	dev_t	st_rdev;
	off_t	st_size;
	time_t	st_atime;
	time_t	st_mtime;
	time_t	st_ctime;
};

#define	S_IFMT	0170000		/* type of file */
#define		S_IFDIR	0040000	/* directory */
#define		S_IFCHR	0020000	/* character special */
#define		S_IFBLK	0060000	/* block special */
#define		S_IFREG	0100000	/* regular */
#define		S_IFMPC	0030000	/* multiplexed char special */
#define		S_IFMPB	0070000	/* multiplexed block special */
#define	S_ISUID	0004000		/* set user id on execution */
#define	S_ISGID	0002000		/* set group id on execution */
#define	S_ISVTX	0001000		/* save swapped text even after use */
#define	S_IREAD	0000400		/* read permission, owner */
#define	S_IWRITE	0000200		/* write permission, owner */
#define	S_IEXEC	0000100		/* execute/search permission, owner */
ecial */
#define		S_IFREG	0100000	/* regular */
#define		S_IFMPC	0030000	/* mlib86/include/stdio.h                                                                                  644     140      12         1524  3347424414   7746                                                                                                                                                                                                                                                                                                                                                                      #define	BUFSIZ	512
#define	_NFILE	20
# ifndef FILE
extern	struct	_iobuf {
	char	*_ptr;
	int	_cnt;
	char	*_base;
	char	_flag;
	char	_file;
} _iob[_NFILE];
# endif

#define	_IOREAD	01
#define	_IOWRT	02
#define	_IONBF	04
#define	_IOMYBUF	010
#define	_IOEOF	020
#define	_IOERR	040
#define	_IOSTRG	0100
#define	NULL	0
#define	FILE	struct _iobuf
#define	EOF	(-1)

#define	stdin	(&_iob[0])
#define	stdout	(&_iob[1])
#define	stderr	(&_iob[2])
#define	getc(p)		(--(p)->_cnt>=0? *(p)->_ptr++&0377:_filbuf(p))
#define	getchar()	getc(stdin)
#define putc(x,p) (--(p)->_cnt>=0? ((int)(*(p)->_ptr++=(unsigned)(x))):_flsbuf((unsigned)(x),p))
#define	putchar(x)	putc(x,stdout)
#define	feof(p)		(((p)->_flag&_IOEOF)!=0)
#define	ferror(p)	(((p)->_flag&_IOERR)!=0)
#define	fileno(p)	(p)->_file

FILE	*fopen();
FILE	*freopen();
FILE	*fdopen();
long	ftell();
char	*fgets();
#define	EOF	(-1)

#define	stdin	(&_iob[0])
#define	stdout	(&_iob[1])
#define	stderr	(&_iob[2])
#define	getc(p)		(--(p)->_cnt>=0? *(p)->_ptr++&0377:_filbuf(p))
#define	getchlib86/include/symbol.h                                                                                 644     140      12          160  3347424414  10104                                                                                                                                                                                                                                                                                                                                                                      /*
 * Structure of a symbol table entry
 */

struct	symbol {
	char	sy_name[8];
	char	sy_type;
	int	sy_value;
};
)
#define	putchar(x)	putc(x,stdout)
#define	feof(p)		(((p)->_flag&_IOEOF)!=0)
#define	ferror(p)	(((p)->_flag&_IOERR)!=0)
#define	fileno(p)	(p)->_file

FILE	*fopen();
FILE	*freopen();
FILE	*fdopen();
long	ftell();
char	*fgets();
#define	EOF	(-1)

#define	stdin	(&_iob[0])
#define	stdout	(&_iob[1])
#define	stderr	(&_iob[2])
#define	getc(        ØÕÿÄÕÿ<                ÖÿðÕÿ           ,ÖÿôÕÿlib86/include/sys/                                                                                     777     140      12            0  3523723676   7216                                                                                                                                                                                                                                                                                                                                                                      lib86/include/sys/acct.h                                                                               644     140      12         1466  3523723664  10366                                                                                                                                                                                                                                                                                                                                                                      /*
 * Accounting structures
 */

typedef	unsigned short comp_t;	/* "floating pt": 3 bits base 8 exp, 13 bits fraction */
struct	acct
{
	char	ac_comm[10];		/* Accounting command name */
	comp_t	ac_utime;		/* Accounting user time */
	comp_t	ac_stime;		/* Accounting system time */
	comp_t	ac_etime;		/* Accounting elapsed time */
	time_t	ac_btime;		/* Beginning time */
	short	ac_uid;			/* Accounting user ID */
	short	ac_gid;			/* Accounting group ID */
	short	ac_mem;			/* average memory usage */
	comp_t	ac_io;			/* number of disk IO blocks */
	dev_t	ac_tty;			/* control typewriter */
	char	ac_flag;		/* Accounting flag */
};

extern	struct	acct	acctbuf;
extern	struct	inode	*acctp;		/* inode of accounting file */

#define	AFORK	01		/* has executed fork, but no exec */
#define	ASU	02		/* used super-user privileges */
g elapsed time */
	time_t	ac_btime;		/* Beginning time */
	short	ac_uid;			/* Accounting user ID */
	short	ac_gid;			/* Accounting group ID */
	short	ac_mem;			/* average memory usage */
	comp_t	ac_io;	lib86/include/sys/buf.h                                                                                644     140      12         5722  3523723664  10227                                                                                                                                                                                                                                                                                                                                                                      /*
 * Each buffer in the pool is usually doubly linked into 2 lists:
 * the device with which it is currently associated (always)
 * and also on a list of blocks available for allocation
 * for other use (usually).
 * The latter list is kept in last-used order, and the two
 * lists are doubly linked to make it easy to remove
 * a buffer from one list when it was found by
 * looking through the other.
 * A buffer is on the available list, and is liable
 * to be reassigned to another disk block, if and only
 * if it is not marked BUSY.  When a buffer is busy, the
 * available-list pointers can be used for other purposes.
 * Most drivers use the forward ptr as a link in their I/O
 * active queue.
 * A buffer header contains all the information required
 * to perform I/O.
 * Most of the routines which manipulate these things
 * are in bio.c.
 */
struct buf
{
	short	b_flags;		/* see defines below */
	struct	buf *b_forw;		/* headed by d_tab of conf.c */
	struct	buf *b_back;		/*  "  */
	struct	buf *av_forw;		/* position on free list, */
	struct	buf *av_back;		/*     if not BUSY*/
	dev_t	b_dev;			/* major+minor device name */
	long b_bcount;			/* transfer count */
	union {
	    caddr_t b_addr;		/* low order core address */
	    long *b_words;		/* words for clearing */
	    struct filsys *b_filsys;	/* superblocks */
	    struct dinode *b_dino;	/* ilist */
	    daddr_t *b_daddr;		/* indirect block */
	} b_un;
	struct dkparam
	{
		long dkp_nxadr;		/* address for next command */
		short dkp_nxc1;		/* first cmd word for next command */
		short dkp_nxc2;		/* second cmd word for next command */
		short dkp_nxc3;		/* third cmd word for next command */
		short dkp_nxctl;	/* control word for next command */
		char dkp_sretry;	/* number of soft error retries left */
		char dkp_fretry;	/* number of drive fault retries left*/
	}	b_dkp;		/* disk parameter block */
	daddr_t	b_blkno;		/* block # on device */
	char	b_error;		/* returned after I/O */
	long b_resid;			/* words not transferred after error */
};

extern struct buf buf[];		/* The buffer pool itself */
extern struct buf bfreelist;		/* head of available list */

/*
 * These flags are kept in b_flags.
 */
#define	B_WRITE	0	/* non-read pseudo-flag */
#define	B_READ	01	/* read when I/O occurs */
#define	B_DONE	02	/* transaction finished */
#define	B_ERROR	04	/* transaction aborted */
#define	B_BUSY	010	/* not on av_forw/back list */
#define	B_PHYS	020	/* Physical IO potentially using UNIBUS map */
#define	B_MAP	040	/* This block has the UNIBUS map allocated */
#define	B_WANTED 0100	/* issue wakeup when BUSY goes off */
#define	B_AGE	0200	/* delayed write for correct aging */
#define	B_ASYNC	0400	/* don't wait for I/O completion */
#define	B_DELWRI 01000	/* don't write till block leaves available list */
#define	B_TAPE 02000	/* this is a magtape (no bdwrite) */

/*
 * special redeclarations for
 * the head of the queue per
 * device driver.
 */
#define	b_actf	av_forw
#define	b_actl	av_back
#define	b_active b_bcount
#define	b_errcnt b_resid
UNIBUS map allocated */
#define	B_WANTED 0100	lib86/include/sys/callo.h                                                                              644     140      12          613  3523723664  10517                                                                                                                                                                                                                                                                                                                                                                      /*
 * The callout structure is for
 * a routine arranging
 * to be called by the clock interrupt
 * (clock.c) with a specified argument,
 * in a specified amount of time.
 * Used, for example, to time tab
 * delays on typewriters.
 */

struct	callo
{
	int	c_time;		/* incremental time */
	caddr_t	c_arg;		/* argument to routine */
	int	(*c_func)();	/* routine */
};
struct	callo	callout[NCALL];
fine	b_actl	av_back
#define	b_active b_bcount        èÒÿÌÒÿ«H        ä            ,Óÿ Óÿû/         ,ÓÿÓÿlib86/include/sys/conf.h                                                                               644     140      12         1302  3523723664  10366                                                                                                                                                                                                                                                                                                                                                                      /*
 * Declaration of block device
 * switch. Each entry (row) is
 * the only link between the
 * main unix code and the driver.
 * The initialization of the
 * device switches is in the
 * file conf.c.
 */
extern struct bdevsw
{
	int	(*d_open)();
	int	(*d_close)();
	int	(*d_strategy)();
	struct buf *d_tab;
} bdevsw[];

/*
 * Character device switch.
 */
extern struct cdevsw
{
	int	(*d_open)();
	int	(*d_close)();
	int	(*d_read)();
	int	(*d_write)();
	int	(*d_ioctl)();
	struct tty *d_ttys;
} cdevsw[];

/*
 * tty line control switch.
 */
extern struct linesw
{
	int	(*l_open)();
	int	(*l_close)();
	int	(*l_read)();
	int	(*l_write)();
	int	(*l_ioctl)();
	int	(*l_rint)();
	int	(*l_start)();
} linesw[];
conf.c.
 */
extern struct bdevsw
{
	int	(*d_open)();
	int	(*d_close)();
	int	(*d_strategy)();
	struct buf *d_tab;
} bdevsw[];

/*
 * Character device switch.
 */
extern struct cdevsw
{
	int	(*d_open)();
	int	(*d_close)();
	int	(*d_read)();
	int	(*d_write)();
	int	(*d_ioctl)();
	struct tty *d_ttys;
} cdevsw[];

/*
 * lib86/include/sys/devmap.h                                                                             755     140      12         1751  3523723664  10730                                                                                                                                                                                                                                                                                                                                                                      /* Mappings of virtual memory */

#define IOBASE		0x70000				/* start below stack */
#define PAGESIZE	1024				/* size of page */
#define SYNCSIZE	0x1400

#define SCRATCHSEG1	IOBASE
#define SCRATCHSEG2	(SCRATCHSEG1 + PAGESIZE)
#define UNIX_IOB	(SCRATCHSEG2 + PAGESIZE)	/* io board */
#define UNIX_DMA	(UNIX_IOB + PAGESIZE)		/* dma board */
#define UNIX_SYNC	(UNIX_DMA + PAGESIZE)		/* sync board */
#define UNIX_VCON	(UNIX_SYNC + SYNCSIZE)		/* vcon board */
#define UNIX_VLTBL	(UNIX_VCON + PAGESIZE)		/* vcon line table */
#define	UNIX_VCON1	(UNIX_VLTBL + LTBLSIZE)		/* second vcon board */
#define	UNIX_VLTBL1	(UNIX_VCON1 + PAGESIZE)		/* second vcon ltbl */
#define UNIX_COLOR	(UNIX_VLTBL1 + LTBLSIZE)	/* color map */
#define UNIX_JMA	(UNIX_COLOR + PAGESIZE)		/* J. ARNOLDS */

#define UNIX_VMEM	VMEM				/* video memory */


/* Event data */
#define NVECS		256		/* maximum number of events */
#define IOB_EVENT	64		/* io board event number (upto 80) */
#define DMA_EVENT	80		/* event number for dma */
AGESIZE)		/* vcon line lib86/include/sys/dir.h                                                                                644     140      12          137  3523723664  10204                                                                                                                                                                                                                                                                                                                                                                      #ifndef	DIRSIZ
#define	DIRSIZ	14
#endif
struct	direct
{
	ino_t	d_ino;
	char	d_name[DIRSIZ];
};
1	(UNIX_VCON1 + PAGESIZE)		/* second vcon ltbl */
#define UNIX_COLOR	(UNIX_VLTBL1 + LTBLSIZE)	/* color map */
#define UNIX_JMA	(UNIX_COLOR + PAGESIZE)		/* J. ARNOLDS */

#define UNIX_VMEM	VMEM				/* video memory */


/* Event data */
#define NVECS		256		/* maximum number of events */
#define IOB_EVENT	64		/* io board event number (upto 80) */
        èÒÿÌÒÿ«H        ä            ,Óÿ Óÿû/         ,ÓÿÓÿlib86/include/sys/dkerrs.h                                                                             644     140      12          635  3523723664  10723                                                                                                                                                                                                                                                                                                                                                                      /* Statistics for DMA errors */

struct dkerrs
{
	long dk_rpe;		/* read or parity errors */
	long dk_timeout;	/* missed interrupt timeouts */
	long dk_fault;		/* drive faults */
	long dk_uwe;		/* unit or write count error */
	long dk_bsf;		/* bad sector found */
	long dk_bto;		/* bus timeout */
	long dk_ovr;		/* fifo overflow */
	long dk_und;		/* fifo underflow */
	long dk_dke;		/* disk not ready error */
};

 event number (upto 80) */
        èÒÿÌÒÿ«H        ä            ,Óÿ Óÿû/         ,ÓÿÓÿlib86/include/sys/fblk.h                                                                               644     140      12           77  3523723664  10327                                                                                                                                                                                                                                                                                                                                                                      struct fblk
{
	short  	df_nfree;
	daddr_t	df_free[NICFREE];
};
	/* read or parity errors */
	long dk_timeout;	/* missed interrupt timeouts */
	long dk_fault;		/* drive faults */
	long dk_uwe;		/* unit or write count error */
	long dk_bsf;		/* bad sector found */
	long dk_bto;		/* bus timeout */
	long dk_ovr;		/* fifo overflow */
	long dk_und;		/* fifo underflow */
	long dk_dke;		/* disk not ready error */
};

 event number (upto 80) */
        èÒÿÌÒÿ«H        ä            ,Óÿ Óÿû/         ,ÓÿÓÿlib86/include/sys/file.h                                                                               644     140      12         1100  3523723665  10355                                                                                                                                                                                                                                                                                                                                                                      /*
 * One file structure is allocated
 * for each open/creat/pipe call.
 * Main use is to hold the read/write
 * pointer associated with each open
 * file.
 */
struct	file
{
	char	f_flag;
	char	f_count;	/* reference count */
	struct inode *f_inode;	/* pointer to inode structure */
	union {
		off_t	f_offset;	/* read/write character pointer */
		struct chan *f_chan;	/* mpx channel pointer */
	} f_un;
};

extern struct file file[];	/* The file table itself */

/* flags */
#define	FREAD	01
#define	FWRITE	02
#define	FPIPE	04
#define FMPX	010
#define	FMPY	020
#define	FMP	030
e call.
 * Main use is to hold the read/write
 * pointer associated with each open
 * file.
 */
struct	file
{
	char	f_flag;
	char	f_count;	/* reference count */
	struct inode *f_inode;	/* pointer to inode structure */
	union {
		off_t	f_offset;	/* read/write character pointer */
		struct chan *f_chan;	/* mpx channel pointer */
	} f_un;
};

extern struct file file[];	/* The file table itself */

/* flags */
#define	FREAD	01
#define	FWRITE	02
#delib86/include/sys/filsys.h                                                                             644     140      12         1721  3523723665  10760                                                                                                                                                                                                                                                                                                                                                                      /*
 * Structure of the super-block
 */
struct	filsys {
	unsigned short s_isize;	/* size in blocks of i-list */
	daddr_t	s_fsize;   	/* size in blocks of entire volume */
	short  	s_nfree;   	/* number of addresses in s_free */
	daddr_t	s_free[NICFREE];/* free block list */
	short  	s_ninode;  	/* number of i-nodes in s_inode */
	ino_t  	s_inode[NICINOD];/* free i-node list */
	char   	s_flock;   	/* lock during free list manipulation */
	char   	s_ilock;   	/* lock during i-list manipulation */
	char   	s_fmod;    	/* super block modified flag */
	char   	s_ronly;   	/* mounted read-only flag */
	time_t 	s_time;    	/* last super block update */
	/* remainder not maintained by this version of the system */
	daddr_t	s_tfree;   	/* total free blocks*/
	ino_t  	s_tinode;  	/* total free inodes */
	short  	s_m;       	/* interleave factor */
	short  	s_n;       	/* " " */
	char   	s_fname[6];	/* file system name */
	char   	s_fpack[6];	/* file system pack name */
};
lock during i-list manipulation */
	char   	s_flib86/include/sys/ino.h                                                                                644     140      12         1160  3523723666  10232                                                                                                                                                                                                                                                                                                                                                                      /*
 * Inode structure as it appears on
 * a disk block.
 */
struct dinode
{
	unsigned short	di_mode;     	/* mode and type of file */
	short	di_nlink;    	/* number of links to file */
	short	di_uid;      	/* owner's user id */
	short	di_gid;      	/* owner's group id */
	off_t	di_size;     	/* number of bytes in file */
	char  	di_addr[40];	/* disk block addresses */
	time_t	di_atime;   	/* time last accessed */
	time_t	di_mtime;   	/* time last modified */
	time_t	di_ctime;   	/* time created */
};
#define	INOPB	8	/* 8 inodes per block */
/*
 * the 40 address bytes:
 *	39 used; 13 addresses
 *	of 3 bytes each.
 */
e and type of file */
	short	di_nlink;    	/* number of links to file */
	short	di_uid;      	/* owner's user id */
	short	di_gid;      	/* owner's group id */
	off_t	di_size;     	/* number of bytes in file */
	char  	di_addr[40];	/* disk block addresses */
	time_t	di_atime;   	/* time last accessed */
	time_t	di_mtime;   	/* time last modified */
	time_t	di_ctime;   	/* time created */
};
#definlib86/include/sys/inode.h                                                                              644     140      12         4362  3523723666  10552                                                                                                                                                                                                                                                                                                                                                                      /*
 * The I node is the focus of all
 * file activity in unix. There is a unique
 * inode allocated for each active file,
 * each current directory, each mounted-on
 * file, text file, and the root. An inode is 'named'
 * by its dev/inumber pair. (iget/iget.c)
 * Data, from mode on, is read in
 * from permanent inode on volume.
 */

#define	NADDR	13
#define	NINDEX	16

struct group {
	short	g_state;
	char	g_index;
	char	g_rot;
	struct	group	*g_group;
	struct	inode	*g_inode;
	short	g_rotmask;
	short	g_datq;
	struct	chan *g_chans[NINDEX];
};

struct	inode
{
	char	i_flag;
	char	i_count;	/* reference count */
	dev_t	i_dev;		/* device where inode resides */
	ino_t	i_number;	/* i number, 1-to-1 with device address */
	unsigned short	i_mode;
	short	i_nlink;	/* directory entries */
	short	i_uid;		/* owner */
	short	i_gid;		/* group of owner */
	off_t	i_size;		/* size of file */
	union {
		struct {
			daddr_t I_addr[NADDR];	/* if normal file/directory */
			daddr_t	I_lastr;	/* last logical block read (for read-ahead) */
		} i_norm;
#define i_addr	i_norm.I_addr
#define i_lastr	i_norm.I_lastr
		struct	{
			daddr_t	I_rdev;			/* i_addr[0] */
			struct	group	I_group;	/*  multiplexor group file */
		} i_dev;
#define i_rdev	i_dev.I_rdev
#define i_group	i_dev.I_group
	} i_un;
};


extern struct inode inode[];	/* The inode table itself */

/* flags */
#define	ILOCK	01		/* inode is locked */
#define	IUPD	02		/* file has been modified */
#define	IACC	04		/* inode access time to be updated */
#define	IMOUNT	010		/* inode is mounted on */
#define	IWANT	020		/* some process waiting on lock */
#define	ITEXT	040		/* inode is pure text prototype */
#define	ICHG	0100		/* inode has been changed */

/* modes */
#define	IFMT	0170000		/* type of file */
#define		IFDIR	0040000	/* directory */
#define		IFCHR	0020000	/* character special */
#define		IFBLK	0060000	/* block special */
#define		IFREG	0100000	/* regular */
#define		IFMPC	0030000	/* multiplexed char special */
#define		IFMPB	0070000	/* multiplexed block special */
#define	ISUID	04000		/* set user id on execution */
#define	ISGID	02000		/* set group id on execution */
#define ISVTX	01000		/* save swapped text even after use */
#define	IREAD	0400		/* read, write, execute permissions */
#define	IWRITE	0200
#define	IEXEC	0100
directory */
#define		IFCHR	0020000	/* character special */
#define		IFBLK	0060000	/* block special */
#define		IFREG	0100000	/* regular */
#define		IFMPC	0030000	/* multiplexed char special */
#define		IFMPB	0070000	/* multiplexed block special */
#define	ISUID	04000		lib86/include/sys/kprof.h                                                                              644     140      12          373  3523723666  10553                                                                                                                                                                                                                                                                                                                                                                      /* Kernel profiling data */

struct kprof
{
	unsigned short kp_scale;	/* 16 bit binary fraction to scale pc*/
	long kp_offs;			/* base address of profiling area */
	long kp_size;			/* size of the buffer area */
	char *kp_ptr;			/* ptr to buffer */
};
 */
#define		IFCHR	0020000	/* character special */
#define		IFBLK	0060000	/* block special */
#define		IFREG	0100000	/* regular */
#define		IFMPC	0030000	/* multiplexed char special */
#def        èÒÿÌÒÿ«H        ä            ,Óÿ Óÿû/         ,ÓÿÓÿlib86/include/sys/m68.h                                                                                644     140      12         3111  3523723666  10055                                                                                                                                                                                                                                                                                                                                                                      /* Machine dependent information for 68000 system */

#define NPAGES 1024		/* number of pages in pagetbl */

/* Status bits:							*/

#define	S_TRACE	0x8000		/* Trace enabled		*/
#define	S_PMASK	0x0700		/* Priority mask		*/
#define	S_PRONE	0x0100		/* Priority level one.		*/
#define	S_SUPER	0x2000		/* Super-mode enabled		*/

#define	MMAP	0x800000	/* Memory map location		*/
#define	MCTRL	0x801000	/* Control word location	*/
#define MM_CTL	0x1		/* mmgt ctl on */
#define MM_AVE	0x2		/* access violation enable */
#define MM_PEE	0x4		/* parity error enable */
#define MM_TME	0x8		/* timeout enable */

#define PID	0x802000	/* Processor number */
#define PNUMREG	0x803000	/* process number for mmap	*/
#define PERROR	0x804000	/* Error register */
#define SEGMENT_ERROR	1	/* segmentation error */
#define TIMEOUT_ERROR	2	/* bus timeout error */
#define PARITY_ERROR	4	/* Memory parity error */

#define	INTON	0xFF		/* mmgt and interrupts on	*/
#define	PAGES	1024		/* Number of pages		*/
#define	PSIZE	10		/* Number of bits in page offset*/

#define	INT0	64		/* first I/O interrupt number	*/
#define	IOEVRAM	0x7F0000	/* adr of I/O event rams	*/
#define	EVNUM	16		/* Number of event rams		*/
#define	IOCTRL	0x7F0060	/* I/O control reg		*/
#define	IOENAB	0x2000		/* bit for event enables	*/
#define	INTTTI	72		/* Interrupt number for tty inp	*/
#define	INTTTO	74		/* Interrupt number for tty outp*/

union map_word		/* details of 68000 page map entries */
{
	long map_long_form;
	struct
	{
		int map_high_part:3;
		int map_access:4;
		int map_dirty:1;
		int map_pnum:8;
		int map_low_part:16;
	} map_detail;
};


	IOEVRAM	0x7F0000	/* adr of I/O event rams	*/
#define	EVNUM	16		/* Number of event rams		*/
#define	IOCTRL	0x7F0060	/* I/O control reg		*/
#define	IOENAB	0x2000		/* bit for event enables	*/
#define	INTTTI	72		/* Interrupt number for tty inp	*/
#define	INTTTO	74		/* Interrupt number for tty outp*/

union map_word		/* details of 68000 page map entries */
{
	long map_long_form;
	struct
	{
		int map_high_part:3;
		int map_access:4;
		int mlib86/include/sys/map.h                                                                                644     140      12          251  3523723666  10202                                                                                                                                                                                                                                                                                                                                                                      struct map
{
	mem_t	m_size;
	mem_t	m_addr;
};

struct map coremap[CMAPSIZ];	/* space for core allocation */
struct map swapmap[SMAPSIZ];	/* space for swap allocation */
ine	IOCTRL	0x7F0060	/* I/O control reg		*/
#define	IOENAB	0x2000		/* bit for event enables	*/
#define	INTTTI	72		/* Interrupt number for tty inp	*/
#define	INTTTO	74		/* Interrupt number for tty outp*/

union map_word		/* details of 68000 page map entries */
{
	long map_        èÒÿÌÒÿ«H        ä            ,Óÿ Óÿû/         ,ÓÿÓÿlib86/include/sys/mount.h                                                                              644     140      12          414  3523723666  10570                                                                                                                                                                                                                                                                                                                                                                      /*
 * Mount structure.
 * One allocated on every mount.
 * Used to find the super block.
 */
struct	mount
{
	dev_t	m_dev;		/* device mounted */
	struct buf *m_bufp;	/* pointer to superblock */
	struct inode *m_inodp;	/* pointer to mounted on inode */
} mount[NMOUNT];
ne	INTTTI	72		/* Interrupt number for tty inp	*/
#define	INTTTO	74		/* Interrupt number for tty outp*/

union map_word		/* details of 68000 page map entries */
{
	long map_        èÒÿÌÒÿ«H        ä            ,Óÿ Óÿû/         ,ÓÿÓÿlib86/include/sys/mx.h                                                                                 644     140      12         3210  3523723666  10067                                                                                                                                                                                                                                                                                                                                                                      #define NGROUPS		10
#define	NCHANS		20

#define	DCHAN		1
#define	CCHAN		0

struct chan {
	short	c_flags;
	char	c_index;
	char	c_iline;
	struct	group	*c_group;
	struct	tty	*c_ittyp;
	struct	tty	*c_ottyp;
	struct	file	*c_fy;
	int	c_pgrp;
	char	c_oline;
	union {
		struct	clist	datq;
	} cx;
	union {
		struct	clist	datq;
		struct	chan	*c_chan;
	} cy;
	struct	clist	c_ctlx;
	struct	clist	c_ctly;
};




struct	header {
	short	index;
	short	count;
	short	ccount;
	caddr_t	addr;
};


struct	group *groups[NGROUPS];
int	mpxline;


/*
 * flags
 */
#define	INUSE	01
#define COPEN	02
#define	XGRP	04
#define	YGRP	010
#define	WCLOSE	020
#define	TTYO	040
#define	ISGRP	0100
#define	BLOCK	0200
#define	BLOCK1	0400
#define	SIGBLK	01000
#define	BLKMSG	01000
#define	ENAMSG	02000
#define	WFLUSH	04000
#define	RZERO	010000


/*
 * mpxchan command codes
 */
#define	MPX	5
#define	MPXN	6
#define	CHAN	1
#define JOIN	2
#define EXTR	3
#define	ATTACH	4
#define	CONNECT	7
#define	DETACH	8
#define	DISCON	9
#define DEBUG	10
#define	NPGRP	11
#define	CSIG	12
#define PACK	13

#define NDEBUGS	30
/*
 * control channel message codes
 */
#define	WATTCH	1
#define M_WATCH 1
#define	SCLOSE	2
#define M_CLOSE 2
#define	M_ATTACH 3
#define	M_BLK	4
#define	M_UBLK	5
#define	DO_BLK	6
#define	DO_UBLK	7
#define	M_XINT	8
#define	M_RINT	9
#define	M_ACK	10
#define	M_NAK	11


/*
 * debug codes other than mpxchan cmds
 */
#define MCCLOSE 29
#define MCOPEN	28
#define	ALL	27
#define SCON	26
#define	MSREAD	25
#define	SDATA	24
#define	MCREAD	23
#define MCWRITE	22

#define	HDRSIZE		4
#define	CNTLSIZ		10
#define NLEVELS		2
union u_index {
	short val;
	char	bytes[NLEVELS];
};
typedef	short	index_t;
int	mxread();

#define M_CLOSE 2
#define	M_ATTACH 3
#define	M_BLK	4
#define	M_UBLK	5
#define	DO_BLK	6
#define	DO_UBLK	7
#define	M_XINT	8
#define	M_RINT	9
#define	M_ACK	10
#define	M_NAK	11


/*
 * debug codes other than mpxchan cmds
 */
#define MCCLOSE 29
#define MCOPEN	28
#define	ALL	27
#define SCON	26
#define	MSREAD	25
#define	SDATA	24
#define	MCREAD	23
#define MCWRITE	22

#define	HDRSlib86/include/sys/param.h                                                                              644     140      12        10337  3523723667  10574                                                                                                                                                                                                                                                                                                                                                                       /*
 * tunable variables
 */

#define	NBUF	15		/* size of buffer cache */
#define	NINODE	20		/* number of in core inodes */
#define	NFILE	20		/* number of in core file structures */
#define	NMOUNT	2		/* number of mountable file systems */
#define	MAXUPRC	25		/* max processes per user */
#define USRBASE	1		/* starting page of usr processes */
#define USRTOP	(0x80000/0x400)	/* page number of top of usr proc */
#define	MAXMEM	(USRTOP)	/* max core per process - first # is Kw */
#define	SSIZE	16		/* initial stack size (*1K bytes) */
#define	SINCR	16		/* increment of stack (*1K bytes) */
#define	NOFILE	20		/* max open files per process */
#define	CANBSIZ	256		/* max size of typewriter line */
#define	CMAPSIZ	20		/* size of core allocation area */
#define	SMAPSIZ	20		/* size of swap allocation area */
#define	NCALL	10		/* max simultaneous time callouts */
#define	NPROC	20		/* max number of processes */
#define	NTEXT	10		/* max number of pure texts */
#define	NCLIST	200		/* max total clist size */
#define	HZ	50		/* Ticks/second of the clock */
#define	TIMEZONE (5*60)		/* Minutes westward from Greenwich */
#define	DSTFLAG	1		/* Daylight Saving Time applies in this locality */
#define	MSGBUFS	128		/* Characters saved from error messages */
#define	NCARGS	5120		/* # characters in exec arglist */

/*
 * priorities
 * probably should not be
 * altered too much
 */

#define	PSWP	0
#define	PINOD	10
#define	PRIBIO	20
#define	PZERO	25
#define	NZERO	20
#define	PPIPE	26
#define	PWAIT	30
#define	PSLEP	40
#define	PUSER	50

/*
 * signals
 * dont change
 */

#include "../signal.h"

/*
 * fundamental constants of the implementation--
 * cannot be changed easily
 */

#define	NBPW	sizeof(int)	/* number of bytes in an integer */
#define	BSIZE	512		/* size of secondary block (bytes) */
/* BSLOP can be 0 unless you have a TIU/Spider */
#define	BSLOP	0		/* In case some device needs bigger buffers */
#define	NINDIR	(BSIZE/sizeof(daddr_t))
#define	BMASK	0777		/* BSIZE-1 */
#define	BSHIFT	9		/* LOG2(BSIZE) */
#define	NMASK	0177		/* NINDIR-1 */
#define	NSHIFT	7		/* LOG2(NINDIR) */
#define	USIZE	2		/* size of user block (*1K) */
#define	UBASE	(0x100000 - USIZE*0x400)	/* abs. addr of user block */
#define	NULL	0
#define	CMASK	0		/* default mask for file creation */
#define	NODEV	(dev_t)(-1)
#define	ROOTINO	((ino_t)2)	/* i number of all roots */
#define	SUPERB	((daddr_t)1)	/* block number of the super block */
#define	DIRSIZ	14		/* max characters per directory */
#define	NICINOD	100		/* number of superblock inodes */
#define	NICFREE	50		/* number of superblock free blocks */
#define	INFSIZE	138		/* size of per-proc info for users */
#define	CBSIZE	4		/* number of chars in a clist block */
#define	CROUND	07		/* clist rounding: sizeof(int *) + CBSIZE - 1*/

/*
 * Some macros for units conversion
 */
/* Core clicks (1K bytes) to segments and vice versa */
#define	ctos(x)	(x)
#define stoc(x) (x)

/* Core clicks (1K bytes) to disk blocks */
#define	ctod(x)	(x<<1)

/* inumber to disk address */
#define	itod(x)	(daddr_t)((((unsigned)x+15)>>3))

/* inumber to disk offset */
#define	itoo(x)	(int)((x+15)&07)

/* clicks to bytes */
#define	ctob(x)	(x<<10)

/* bytes to clicks */
#define	btoc(x)	((((unsigned)(x)+1023)>>10))

/* major part of a device */
#define	major(x)	(int)(((unsigned)x>>8))

/* minor part of a device */
#define	minor(x)	(int)(x&0377)

/* make a device number */
#define	makedev(x,y)	(dev_t)((x)<<8 | (y))

typedef	struct { int r[1]; } *	physadr;
typedef	long		daddr_t;
typedef char *		caddr_t;
typedef	long		mem_t;
typedef	unsigned short	ino_t;
typedef	long		time_t;
typedef	long		label_t[13];	/* regs d2-d7, a2-a7, pc */
typedef	short		dev_t;
typedef	long		off_t;

/*
 * Machine-dependent bits and macros
 */
#define	SMODE	0x2000		/* supervisor mode bit,note no user mode bit*/
#define	USERMODE(ps)	(((ps) & SMODE)==0)

#define	INTPRI	0x700		/* Priority bits */
#define	BASEPRI(ps)	(((ps) & INTPRI) != 0)


#define fuibyte(x)	fubyte(x)
#define fuiword(x)	fuword(x)
#define suibyte(x,y)	subyte(x,y)
#define suiword(x,y)	suword(x,y)
#define copyin(x,y,z)	copy(x,y,z)
#define copyiin(x,y,z)	copy(x,y,z)
#define copyout(x,y,z)	copy(x,y,z)
#define copyiout(x,y,z)	copy(x,y,z)

#define void int	/* so berkeley void coersions will work */
#define gsignal signal
#define MIN(a,b)	((a < b)?a:b)
t*/
#define	USERMODE(ps)	(((ps) & SMODE)==0)

#define	INTPRI	0x700		/* Priority bits */
#define	BASEPRI(ps)	(((ps) & INTPRI) != 0)


#define fuibyte(x)	fubyte(x)
#define fuiword(x)	fuword(x)
#define suibyte(x,y)	subyte(x,y)
#define suiword(x,y)	suword(x,y)
#define copyin(x,y,z)	copy(x,y,zlib86/include/sys/pmx.h                                                                                644     140      12          301  3523723667  10226                                                                                                                                                                                                                                                                                                                                                                      #define	NINDEX	16

struct group {
	short	g_state;
	char	g_index;
	char	g_rot;
	struct	group	*g_group;
	struct	inode	*g_inode;
	short	g_rotmask;
	short	g_datq;
	struct	chan *g_chans[NINDEX];
};
define MIN(a,b)	((a < b)?a:b)
t*/
#define	USERMODE(ps)	(((ps) & SMODE)==0)

#define	INTPRI	0x700		/* Priority bits */
#define	BASEPRI(ps)	(((ps) & INTPRI) != 0)


#define fuibyte(x)	fubyte(x)
#define fuiword(x)	fuword(x)
#define suibyte(x,y)	subyt        èÒÿÌÒÿ«H        ä            ,Óÿ Óÿû/         ,ÓÿÓÿlib86/include/sys/proc.h                                                                               644     140      12         4602  3523723667  10415                                                                                                                                                                                                                                                                                                                                                                      /*
 * One structure allocated per active
 * process. It contains all data needed
 * about the process while the
 * process may be swapped out.
 * Other per process data (user.h)
 * is swapped with the process.
 */
struct	proc {
	char	p_stat;
	char	p_flag;
	char	p_pri;		/* priority, negative is high */
	char	p_time;		/* resident time for scheduling */
	char	p_cpu;		/* cpu usage for scheduling */
	char	p_nice;		/* nice for cpu usage */
	long	p_sig;		/* signals pending to this process */
	short	p_uid;		/* user id, used to direct tty signals */
	short	p_pgrp;		/* name of process group leader */
	short	p_pid;		/* unique process id */
	short	p_ppid;		/* process id of parent */
	short	p_addr;		/* address of swappable image */
	short	p_size;		/* size of swappable image (clicks) */
	caddr_t p_wchan;	/* event process is awaiting */
	struct text *p_textp;	/* pointer to text structure */
	struct proc *p_link;	/* linked list of running processes */
	int	p_clktim;	/* time to alarm clock signal */
};

extern struct proc proc[];	/* the proc table itself */

/* stat codes */
#define	SSLEEP	1		/* awaiting an event */
#define	SWAIT	2		/* (abandoned state) */
#define	SRUN	3		/* running */
#define	SIDL	4		/* intermediate state in process creation */
#define	SZOMB	5		/* intermediate state in process termination */
#define	SSTOP	6		/* process being traced */

/* flag codes */
#define	SLOAD	01		/* in core */
#define	SSYS	02		/* scheduling process */
#define	SLOCK	04		/* process cannot be swapped */
#define	SSWAP	010		/* process is being swapped out */
#define	STRC	020		/* process is being traced */
#define	SWTED	040		/* another tracing flag */
#define	SULOCK	0100		/* user settable lock in core */

/*
 * parallel proc structure
 * to replace part with times
 * to be passed to parent process
 * in ZOMBIE state.
 */
struct	xproc {
	char	xp_stat;
	char	xp_flag;
	char	xp_pri;		/* priority, negative is high */
	char	xp_time;	/* resident time for scheduling */
	char	xp_cpu;		/* cpu usage for scheduling */
	char	xp_nice;	/* nice for cpu usage */
	long	xp_sig;		/* signals pending to this process */
	short	xp_uid;		/* user id, used to direct tty signals */
	short	xp_pgrp;	/* name of process group leader */
	short	xp_pid;		/* unique process id */
	short	xp_ppid;	/* process id of parent */
	short	xp_xstat;	/* Exit status for wait */
	time_t	xp_utime;	/* user time, this proc */
	time_t	xp_stime;	/* system time, this proc */
};
_time;	/* resident time for scheduling */
	char	xp_cpu;		/* cpu usage for scheduling */
	char	xp_nice;	/* nice for cpu usage *lib86/include/sys/reg.h                                                                                644     140      12          670  3523723667  10210                                                                                                                                                                                                                                                                                                                                                                      /*
 * Location of the users' stored
 * registers relative to R0.
 * Usage is u.u_ar0[XX].
 */

#define	R0	(0)
#define	R1	(1)
#define	R2	(2)
#define	R3	(3)
#define	R4	(4)
#define	R5	(5)
#define	R6	(6)
#define	R7	(7)
#define AR0	(8)
#define	AR1	(9)
#define	AR2	(10)
#define	AR3	(11)
#define	AR4	(12)
#define	AR5	(13)
#define	AR6	(14)
#define	AR7	(15)
#define	SP	(15)
#define	PC	(18)
#define	RPS	(17)

#define	TBIT	0100000		/* PS trace bit */
        èÒÿÌÒÿ«H        ä            ,Óÿ Óÿû/         ,ÓÿÓÿlib86/include/sys/seg.h                                                                                644     140      12            0  3523723667  10134                                                                                                                                                                                                                                                                                                                                                                      lib86/include/sys/setjmp.h                                                                             644     140      12           31  3523723667  10704                                                                                                                                                                                                                                                                                                                                                                      typedef int jmp_buf[13];
rs' stored
 * registers relative to R0.
 * Usage is u.u_ar0[XX].
 */

#define	R0	(0)
#define	R1	(1)
#define	R2	(2)
#define	R3	(3)
#define	R4	(4)
#define	R5	(5)
#define	R6	(6)
#define	R7	(7)
#define AR0	(8)
#define	AR1	(9)
#define	AR2	(10)
#define	AR3	(11)
#define	AR4	(12)
#define	AR5	(13)
#define	AR6	(14)
#define	AR7	(15)
#define	SP	(15)
#define	PC	(18)
#define	RPS	(17)

#define	TBIT	0100000		/* PS trace bit */
        èÒÿÌÒÿ«H        ä            ,Óÿ Óÿû/         ,ÓÿÓÿlib86/include/sys/smallparam.h                                                                         644     140      12        10512  3523723667  11620                                                                                                                                                                                                                                                                                                                                                                      /*
 * tunable variables
 */

#define	NBUF	8		/* size of buffer cache */
#define	NINODE	75		/* number of in core inodes */
#define	NFILE	75		/* number of in core file structures */
#define	NMOUNT	3		/* number of mountable file systems */
#define	MAXMEM	(64*32)		/* max core per process - first # is Kw */
#define	MAXUPRC	15		/* max processes per user */
#define	SSIZE	20		/* initial stack size (*64 bytes) */
#define	SINCR	20		/* increment of stack (*64 bytes) */
#define	NOFILE	20		/* max open files per process */
#define	CANBSIZ	256		/* max size of typewriter line */
#define	CMAPSIZ	50		/* size of core allocation area */
#define	SMAPSIZ	50		/* size of swap allocation area */
#define	NCALL	20		/* max simultaneous time callouts */
#define	NPROC	50		/* max number of processes */
#define	NTEXT	25		/* max number of pure texts */
#define	NCLIST	100		/* max total clist size */
#define	HZ	60		/* Ticks/second of the clock */
#define	TIMEZONE (5*60)		/* Minutes westward from Greenwich */
#define	DSTFLAG	1		/* Daylight Saving Time applies in this locality */
#define	MSGBUFS	128		/* Characters saved from error messages */
#define	NCARGS	5120		/* # characters in exec arglist */

/*
 * priorities
 * probably should not be
 * altered too much
 */

#define	PSWP	0
#define	PINOD	10
#define	PRIBIO	20
#define	PZERO	25
#define	NZERO	20
#define	PPIPE	26
#define	PWAIT	30
#define	PSLEP	40
#define	PUSER	50

/*
 * signals
 * dont change
 */

#define	NSIG	17
/*
 * No more than 16 signals (1-16) because they are
 * stored in bits in a word.
 */
#define	SIGHUP	1	/* hangup */
#define	SIGINT	2	/* interrupt (rubout) */
#define	SIGQUIT	3	/* quit (FS) */
#define	SIGINS	4	/* illegal instruction */
#define	SIGTRC	5	/* trace or breakpoint */
#define	SIGIOT	6	/* iot */
#define	SIGEMT	7	/* emt */
#define	SIGFPT	8	/* floating exception */
#define	SIGKIL	9	/* kill, uncatchable termination */
#define	SIGBUS	10	/* bus error */
#define	SIGSEG	11	/* segmentation violation */
#define	SIGSYS	12	/* bad system call */
#define	SIGPIPE	13	/* end of pipe */
#define	SIGCLK	14	/* alarm clock */
#define	SIGTRM	15	/* Catchable termination */

/*
 * fundamental constants of the implementation--
 * cannot be changed easily
 */

#define	NBPW	sizeof(int)	/* number of bytes in an integer */
#define	BSIZE	512		/* size of secondary block (bytes) */
/* BSLOP can be 0 unless you have a TIU/Spider */
#define	BSLOP	2		/* In case some device needs bigger buffers */
#define	NINDIR	(BSIZE/sizeof(daddr_t))
#define	BMASK	0777		/* BSIZE-1 */
#define	BSHIFT	9		/* LOG2(BSIZE) */
#define	NMASK	0177		/* NINDIR-1 */
#define	NSHIFT	7		/* LOG2(NINDIR) */
#define	USIZE	16		/* size of user block (*64) */
#define	UBASE	0140000		/* abs. addr of user block */
#define	NULL	0
#define	CMASK	0		/* default mask for file creation */
#define	NODEV	(dev_t)(-1)
#define	ROOTINO	((ino_t)2)	/* i number of all roots */
#define	SUPERB	((daddr_t)1)	/* block number of the super block */
#define	DIRSIZ	14		/* max characters per directory */
#define	NICINOD	100		/* number of superblock inodes */
#define	NICFREE	50		/* number of superblock free blocks */
#define	INFSIZE	138		/* size of per-proc info for users */
#define	CBSIZE	4		/* number of chars in a clist block */
#define	CROUND	07		/* clist rounding: sizeof(int *) + CBSIZE - 1*/

/*
 * Some macros for units conversion
 */
/* Core clicks (64 bytes) to segments and vice versa */
#define	ctos(x)	((x+127)/128)
#define stoc(x) ((x)*128)

/* Core clicks (64 bytes) to disk blocks */
#define	ctod(x)	((x+7)>>3)

/* inumber to disk address */
#define	itod(x)	(daddr_t)((((unsigned)x+15)>>3))

/* inumber to disk offset */
#define	itoo(x)	(int)((x+15)&07)

/* clicks to bytes */
#define	ctob(x)	(x<<6)

/* bytes to clicks */
#define	btoc(x)	((((unsigned)x+63)>>6))

/* major part of a device */
#define	major(x)	(int)(((unsigned)x>>8))

/* minor part of a device */
#define	minor(x)	(int)(x&0377)

/* make a device number */
#define	makedev(x,y)	(dev_t)((x)<<8 | (y))

typedef	struct { int r[1]; } *	physadr;
typedef	long		daddr_t;
typedef char *		caddr_t;
typedef	long		mem_t;
typedef	unsigned int	ino_t;
typedef	long		time_t;
typedef	int		label_t[6];	/* regs 2-7 */
typedef	int		dev_t;
typedef	long		off_t;

/*
 * Machine-dependent bits and macros
 */
#define	UMODE	0170000		/* usermode bits */
#define	USERMODE(ps)	((ps & UMODE)==UMODE)

#define	INTPRI	0340		/* Priority bits */
#define	BASEPRI(ps)	((ps & INTPRI) != 0)
ice number */
#define	makedev(x,y)	(dev_t)((x)<<8 | (y))

typedef	struct { int r[1]; } *	physadr;
typedef	long		daddr_t;
typedef char *		caddr_t;
typedef	long		mem_t;
typedef	unsignelib86/include/sys/stat.h                                                                               644     140      12         1600  3523723667  10420                                                                                                                                                                                                                                                                                                                                                                      struct	stat
{
	dev_t	st_dev;
	ino_t	st_ino;
	unsigned short   	st_mode;
	short  	st_nlink;
	short  	st_uid;
	short  	st_gid;
	dev_t	st_rdev;
	off_t	st_size;
	time_t	st_atime;
	time_t	st_mtime;
	time_t	st_ctime;
};

#define	S_IFMT	0170000		/* type of file */
#define		S_IFDIR	0040000	/* directory */
#define		S_IFCHR	0020000	/* character special */
#define		S_IFBLK	0060000	/* block special */
#define		S_IFREG	0100000	/* regular */
#define		S_IFMPC	0030000	/* multiplexed char special */
#define		S_IFMPB	0070000	/* multiplexed block special */
#define	S_ISUID	0004000		/* set user id on execution */
#define	S_ISGID	0002000		/* set group id on execution */
#define	S_ISVTX	0001000		/* save swapped text even after use */
#define	S_IREAD	0000400		/* read permission, owner */
#define	S_IWRITE	0000200		/* write permission, owner */
#define	S_IEXEC	0000100		/* execute/search permission, owner */
ecial */
#define		S_IFREG	0100000	/* regular */
#define		S_IFMPC	0030000	/* multiplexed char special */
#define		S_IFMPB	0070000lib86/include/sys/systm.h                                                                              644     140      12         4134  3523723670  10623                                                                                                                                                                                                                                                                                                                                                                      /*
 * Random set of variables
 * used by more than one
 * routine.
 */
char	canonb[CANBSIZ];	/* buffer for erase and kill (#@) */
struct inode *rootdir;		/* pointer to inode of root directory */
struct proc *runq;		/* head of linked list of running processes */
int	cputype;		/* type of cpu =40, 45, or 70 */
int	lbolt;			/* time of day in 60th not in time */
time_t	time;			/* time in sec from 1970 */

/*
 * Nblkdev is the number of entries
 * (rows) in the block switch. It is
 * set in binit/bio.c by making
 * a pass over the switch.
 * Used in bounds checking on major
 * device numbers.
 */
int	nblkdev;

/*
 * Number of character switch entries.
 * Set by cinit/tty.c
 */
int	nchrdev;

int	mpid;			/* generic for unique process id's */
char	runin;			/* scheduling flag */
char	runout;			/* scheduling flag */
char	runrun;			/* scheduling flag */
char	curpri;			/* more scheduling */
int	maxmem;			/* actual max memory per process */
physadr	lks;			/* pointer to clock device */
daddr_t	swplo;			/* block number of swap space */
int	nswap;			/* size of swap space */
int	updlock;		/* lock for sync */
daddr_t	rablock;		/* block to be read ahead */
extern	char	regloc[];	/* locs. of saved user registers (trap.c) */
char	msgbuf[MSGBUFS];	/* saved "printf" characters */
dev_t	rootdev;		/* device of the root */
dev_t	swapdev;		/* swapping device */
dev_t	pipedev;		/* pipe device */
extern	short	icode[];	/* user init code */
extern	int	szicode;	/* its size */

dev_t getmdev();
daddr_t	bmap();
struct inode *ialloc();
struct inode *iget();
struct inode *owner();
struct inode *maknode();
struct inode *namei();
struct buf *alloc();
struct buf *getblk();
struct buf *geteblk();
struct buf *bread();
struct buf *breada();
struct filsys *getfs();
struct file *getf();
struct file *falloc();
int	uchar();
/*
 * Instrumentation
 */
int	dk_busy;
long	dk_time[32];
long	dk_numb[6];
long	dk_wds[6];
long	tk_nin;
long	tk_nout;

/*
 * Structure of the system-entry table
 */
extern struct sysent {
	char	sy_narg;		/* total number of arguments */
	char	sy_nrarg;		/* number of args in registers */
	int	(*sy_call)();		/* handler */
} sysent[];
 *alloc();
struct buf *getblk();
struct buf *geteblk();
struct buf *bread();
struct buf *breada();
struct filsys *getfs();
struct file *getf();
struct file *falloc();
int	uchar();
/*
 * Instrumentation
 */
int	dk_busy;
long	dk_time[32];
long	dk_numb[6];
long	dk_wds[6];
long	tk_nin;
long	tk_nout;

/*
 * Structure of the system-entry table
 */
extern struct sysent {
	char	sy_narg;		/* total number of arguments */
	charlib86/include/sys/text.h                                                                               644     140      12         1346  3523723670  10432                                                                                                                                                                                                                                                                                                                                                                      /*
 * Text structure.
 * One allocated per pure
 * procedure on swap device.
 * Manipulated by text.c
 */
struct text
{
	short	x_daddr;	/* disk address of segment (relative to swplo) */
	mem_t	x_caddr;	/* core address, if loaded */
	mem_t	x_size;		/* size (clicks) */
	struct inode *x_iptr;	/* inode of prototype */
	char	x_count;	/* reference count */
	char	x_ccount;	/* number of loaded references */
	char	x_flag;		/* traced, written flags */
};

extern struct text text[];

#define	XTRC	01		/* Text may be written, exclusive use */
#define	XWRIT	02		/* Text written into, must swap out */
#define	XLOAD	04		/* Currently being read from file */
#define	XLOCK	010		/* Being swapped in or out */
#define	XWANT	020		/* Wanted for swapping */
/
	mem_t	x_size;		/* size (clicks) */
	struct inode *x_iptr;	/* inode of prototype */
	char	x_count;	/* reference count */
	char	x_ccount;	/* number of loaded references */
	char	x_flag;		/* traced, written flags */
};

extern struct text text[];

#define	XTRC	01		/* Text may be wrlib86/include/sys/timeb.h                                                                              644     140      12          214  3523723670  10517                                                                                                                                                                                                                                                                                                                                                                      /*
 * Structure returned by ftime system call
 */
struct timeb {
	time_t	time;
	unsigned short millitm;
	short	timezone;
	short	dstflag;
};
ine	XLOCK	010		/* Being swapped in or out */
#define	XWANT	020		/* Wanted for swapping */
/
	mem_t	x_size;		/* size (clicks) */
	struct inode *x_iptr;	/* inode of prototype */
	char	x_count;	/* reference count */
	char	x_ccount;	/* number of loaded references */
	char	x_flag;		/* traced, written fla        èÒÿÌÒÿ«H        ä            ,Óÿ Óÿû/         ,ÓÿÓÿlib86/include/sys/times.h                                                                              644     140      12          342  3523723670  10542                                                                                                                                                                                                                                                                                                                                                                      /*
 * Structure returned by times()
 */
struct tms {
	time_t	tms_utime;		/* user time */
	time_t	tms_stime;		/* system time */
	time_t	tms_cutime;		/* user time, children */
	time_t	tms_cstime;		/* system time, children */
};
 */
/
	mem_t	x_size;		/* size (clicks) */
	struct inode *x_iptr;	/* inode of prototype */
	char	x_count;	/* reference count */
	char	x_ccount;	/* number of loaded references */
	char	x_flag;		/* traced, written fla        èÒÿÌÒÿ«H        ä            ,Óÿ Óÿû/         ,ÓÿÓÿlib86/include/sys/tty.h                                                                                644     140      12        10416  3523723671  10305                                                                                                                                                                                                                                                                                                                                                                      /*	tty.h	4.2	12/17/80	*/

#include <sgtty.h>

/*
 * A clist structure is the head
 * of a linked list queue of characters.
 * The characters are stored in
 * blocks containing a link and CBSIZE (param.h)
 * characters.  The routines getc, putc, ... in prim.c
 * manipulate these structures.
 */
struct clist
{
	int	c_cc;		/* character count */
	char	*c_cf;		/* pointer to first char */
	char	*c_cl;		/* pointer to last char */
};

/*
 * A tty structure is needed for
 * each UNIX character device that
 * is used for normal terminal IO.
 * The routines in tty.c handle the
 * common code associated with
 * these structures.  The definition
 * and device dependent code is in
 * each driver. (cons.c, dh.c, dz.c, kl.c)
 */
struct tty
{
	union {
		struct {
			struct	clist T_rawq;
			struct	clist T_canq;
		} t_t;
#define	t_rawq	t_nu.t_t.T_rawq		/* raw characters or partial line */
#define	t_canq	t_nu.t_t.T_canq		/* complete input lines */
		struct {
			struct	buf *T_bufp;
			char	*T_cp;
			int	T_inbuf;
			int	T_rec;
		} t_n;
#define	t_bufp	t_nu.t_n.T_bufp		/* buffer allocated to protocol */
#define	t_cp	t_nu.t_n.T_cp		/* pointer into the ripped off buffer */
#define	t_inbuf	t_nu.t_n.T_inbuf	/* number chars in the buffer */
#define	t_rec	t_nu.t_n.T_rec		/* have a complete record */
	} t_nu;
	struct	clist t_outq;	/* output list to device */
	int	(*t_oproc)();	/* routine to start output */
	int	(*t_iproc)();	/* routine to start input */
	struct chan *t_chan;	/* destination channel */
	caddr_t	t_linep;	/* aux line discipline pointer */
	caddr_t	t_addr;		/* device address */
	dev_t	t_dev;		/* device number */
	short	t_flags;	/* mode, settable by ioctl call */
	short	t_state;	/* internal state, not visible externally */
	short	t_pgrp;		/* process group name */
	char	t_delct;	/* number of delimiters in raw q */
	char	t_line;		/* line discipline */
	char	t_col;		/* printing column of device */
	char	t_erase;	/* erase character */
	char	t_kill;		/* kill character */
	char	t_char;		/* character temporary */
	char	t_ispeed;	/* input speed */
	char	t_ospeed;	/* output speed */
/* begin local */
	char	t_rocount;	/* chars input since a ttwrite() */
	char	t_rocol;	/* t_col when first input this line */
	struct	ltchars t_lchr;	/* local special characters */
	short	t_local;	/* local mode word */
	short	t_lstate;	/* local state bits */
/* end local */
	union {
		struct tchars t_chr;
		struct clist t_ctlq;
	} t_un;
	struct	buf *t_ibp, *t_obp;
};

#define	tun	tp->t_un.t_chr
#define	tlun	tp->t_lchr

#define	TTIPRI	28
#define	TTOPRI	29

#define	CTRL(c)	('c'&037)

/* default special characters */
#define	CERASE	0177
#define	CEOT	CTRL(d)
#define	CKILL	CTRL(u)
#define	CQUIT	CTRL(b)
#define	CINTR	CTRL(c)
#define	CSTOP	CTRL(s)
#define	CSTART	CTRL(q)
#define	CBRK	0377
#define CSUSP	0200		/* for now, later ^z */
#define CDSUSP	0200		/* for now, later ^y */
#define CRPRNT	CTRL(r)
#define CFLUSH	CTRL(o)
#define CWERAS	CTRL(w)
#define CLNEXT	CTRL(v)
#define CCLEAR	CTRL(l)

/* limits */
#define	NSPEEDS	16
#define	TTMASK	15
#ifdef KERNEL
short	tthiwat[NSPEEDS], ttlowat[NSPEEDS];
#define	TTHIWAT(tp)	tthiwat[(tp)->t_ospeed&TTMASK]
#define	TTLOWAT(tp)	ttlowat[(tp)->t_ospeed&TTMASK]
#endif
#define	TTYHOG	256

/* hardware bits */
#define	DONE	0200
#define	IENABLE	0100

/* internal state bits */
#define	TIMEOUT	01		/* delay timeout in progress */
#define	WOPEN	02		/* waiting for open to complete */
#define	ISOPEN	04		/* device is open */
#define	FLUSH	010		/* outq has been flushed during DMA */
#define	CARR_ON	020		/* software copy of carrier-present */
#define	BUSY	040		/* output in progress */
#define	ASLEEP	0100		/* wakeup when output done */
#define	XCLUDE	0200		/* exclusive-use flag against open */
#define	TTSTOP	0400		/* output stopped by ctl-s */
#define	HUPCLS	01000		/* hang up upon last close */
#define	TBLOCK	02000		/* tandem queue blocked */
#define	SPEEDS	04000		/* t_ispeed and t_ospeed used by driver */
#define	NDQB	010000
#define	EXTPROC	020000		/* external processor (kmc) */
#define	FSLEEP	040000		/* Wakeup on input framing */
#define	BEXT	0100000		/* use (external) system buffers */

/* define partab character types */
#define	ORDINARY	0
#define	CONTROL		1
#define	BACKSPACE	2
#define	NEWLINE		3
#define	TAB		4
#define	VTAB		5
#define	RETURN		6

/* define dmctl actions */
#define	DMSET		0
#define	DMBIS		1
#define	DMBIC		2
m queue blocked */
#define	SPEEDS	04000		/* t_ispeed and t_ospeed used by driver */
#define	NDQB	010000
#define	EXTPROC	020000		/* external processor (kmc) */
#define	FSLEEP	040000		/* Wakeup on input framing */
#define	BEXT	0100000		/* use (lib86/include/sys/types.h                                                                              644     140      12          602  3523723671  10565                                                                                                                                                                                                                                                                                                                                                                      typedef	long		daddr_t;
typedef char *		caddr_t;
typedef	long		mem_t;
typedef	unsigned short	ino_t;
typedef	long		time_t;
typedef	long		label_t[13];	/* regs d2-d7, a2-a7, pc */
typedef	short		dev_t;
typedef	long		off_t;

	/* selectors and constructor for device code */
#define	major(x)  	(int)(((unsigned)x>>8))
#define	minor(x)  	(int)(x&0377)
#define	makedev(x,y)	(dev_t)((x)<<8|(y))
ROC	020000		/* external processor (kmc) */
#define	FSL        èÒÿÌÒÿ«H        ä            ,Óÿ Óÿû/         ,ÓÿÓÿlib86/include/sys/user.h                                                                               644     140      12        10331  3523723671  10437                                                                                                                                                                                                                                                                                                                                                                      /*
 * The user structure.
 * One allocated per process.
 * Contains all per process data
 * that doesn't need to be referenced
 * while the process is swapped.
 * The user block is USIZE*1K bytes
 * long; resides at virtual kernel
 * loc 0xFC000; contains the system
 * stack per user; is cross referenced
 * with the proc structure for the
 * same process.
 */

#define	EXCLOSE	01

struct	user
{
	label_t	u_rsav;			/* save info when exchanging stacks */
	char	u_segflg;		/* IO flag: 0:user D; 1:system; 2:user I */
	char	u_error;		/* return error code */
	short	u_uid;			/* effective user id */
	short	u_gid;			/* effective group id */
	short	u_ruid;			/* real user id */
	short	u_rgid;			/* real group id */
	struct proc *u_procp;		/* pointer to proc structure */
	int	*u_ap;			/* pointer to arglist */
	union {				/* syscall return values */
		struct	{
			int	R_val1;
			int	R_val2;
		} r_val;
#define r_val1	r_val.R_val1
#define r_val2	r_val.R_val2
		off_t	r_off;
		time_t	r_time;
	} u_r;
	caddr_t	u_base;			/* base address for IO */
	unsigned int u_count;		/* bytes remaining for IO */
	off_t	u_offset;		/* offset in file for IO */
	struct inode *u_cdir;		/* pointer to inode of current directory */
	struct inode *u_rdir;		/* root directory of current process */
	char	u_dbuf[DIRSIZ];		/* current pathname component */
	caddr_t	u_dirp;			/* pathname pointer */
	struct direct u_dent;		/* current directory entry */
	struct inode *u_pdir;		/* inode of parent directory of dirp */
	struct file *u_ofile[NOFILE];	/* pointers to file structures of open files */
	char	u_pofile[NOFILE];	/* per-process flags of open files */
	int	u_arg[5];		/* arguments to current system call */
	unsigned u_tsize;		/* text size (clicks) */
	unsigned u_dsize;		/* data size (clicks) */
	unsigned u_ssize;		/* stack size (clicks) */
	label_t	u_qsav;			/* label variable for quits and interrupts */
	label_t	u_ssav;			/* label variable for swapping */
	int	u_signal[NSIG];		/* disposition of signals */
	time_t	u_utime;		/* this process user time */
	time_t	u_stime;		/* this process system time */
	time_t	u_cutime;		/* sum of childs' utimes */
	time_t	u_cstime;		/* sum of childs' stimes */
	int	*u_ar0;			/* address of users saved R0 */
	struct {			/* profile arguments */
		short	*pr_base;	/* buffer base */
		unsigned pr_size;	/* buffer size */
		unsigned pr_off;	/* pc offset */
		unsigned pr_scale;	/* pc scaling */
	} u_prof;
	char	u_intflg;		/* catch intr from sys */
	struct tty *u_ttyp;		/* controlling tty pointer */
	dev_t	u_ttyd;			/* controlling tty dev */
	struct {			/* header of executable file */
		long	ux_mag;		/* magic number */
		long	ux_tsize;	/* text size */
		long	ux_dsize;	/* data size */
		long	ux_bsize;	/* bss size */
		long	ux_ssize;	/* symbol table size */
		long	ux_rtsize;
		long	ux_rdsize;
		long	ux_entloc;	/* entry location */
	} u_exdata;
	char	u_comm[DIRSIZ];
	time_t	u_start;
	char 	u_pnum;			/* process number for use in pagemap */
	char	u_acflag;
	short	u_fpflag;		/* unused now, will be later */
	short	u_cmask;		/* mask for file creation */
	short	u_fcode;		/* function code on bus errors */
	long	u_aaddr;		/* access address on bus errors */
	short	u_ireg;			/* instruction register on bus errors*/
	unsigned u_ptsize;		/* text size (clicks) for sureg */
	unsigned u_pdsize;		/* data size (clicks) for sureg */
	unsigned u_pssize;		/* stack size (clicks)for sureg */
	int	u_xrw;			/* rw flag for sureg */
	int	u_stack[1];
					/* kernel stack per user
					 * extends from u + USIZE*64
					 * backward not to reach here
					 */
};

#define u (*((struct user *)0xFF800))

/* u_error codes */
#define	EPERM	1
#define	ENOENT	2
#define	ESRCH	3
#define	EINTR	4
#define	EIO	5
#define	ENXIO	6
#define	E2BIG	7
#define	ENOEXEC	8
#define	EBADF	9
#define	ECHILD	10
#define	EAGAIN	11
#define	ENOMEM	12
#define	EACCES	13
#define	EFAULT	14
#define	ENOTBLK	15
#define	EBUSY	16
#define	EEXIST	17
#define	EXDEV	18
#define	ENODEV	19
#define	ENOTDIR	20
#define	EISDIR	21
#define	EINVAL	22
#define	ENFILE	23
#define	EMFILE	24
#define	ENOTTY	25
#define	ETXTBSY	26
#define	EFBIG	27
#define	ENOSPC	28
#define	ESPIPE	29
#define	EROFS	30
#define	EMLINK	31
#define	EPIPE	32
#define	EDOM	33
#define	ERANGE	34


/* flags to estabur */

#define RW	0		/* text segment r/w */
#define RO	1		/* text segment r/o */
1
#define	ENOMEM	12
#define	EACCES	13
#define	EFAULT	14
#define	ENOTBLK	15
#define	EBUSY	16
#define	EEXIST	17
#define	EXDEV	18
#define	ENODEV	19
#define	ENOTDIR	20
#define	EISDIR	21
#define	EINVAL	22
#define	ENFILE	23
#define	EMFILE	24
#define	ENOTTY	25
#define	ETXTBSY	26
#define	EFBIG	27
#defilib86/include/time.h                                                                                   644     140      12          236  3347424414   7541                                                                                                                                                                                                                                                                                                                                                                      struct tm { /* see ctime(3) */
	int	tm_sec;
	int	tm_min;
	int	tm_hour;
	int	tm_mday;
	int	tm_mon;
	int	tm_year;
	int	tm_wday;
	int	tm_yday;
	int	tm_isdst;
};
of(p)		(((p)->_flag&_IOEOF)!=0)
#define	ferror(p)	(((p)->_flag&_IOERR)!=0)
#define	fileno(p)	(p)->_file

FILE	*fopen();
FILE	*freopen();
FILE	*fdopen();
long	ftell();
char	*fgets();
#define	EOF	(-1)

#define	stdin	(&_iob[0])
#define	stdout	(&_iob[1])
#define	stderr	(&_iob[2])
#defi        ØÕÿ¼Õÿ«H        ä            ,ÖÿðÕÿû/         ,ÖÿôÕÿlib86/include/tp_defs.h                                                                                644     140      12          212  3347424414  10221                                                                                                                                                                                                                                                                                                                                                                      char	mt[]	= "/dev/mt0";
char	tc[]	= "/dev/tapx";
int	flags	= flu;
char	mheader[] = "/usr/mdec/mboot";
char	theader[] = "/usr/mdec/tboot";
;
	int	tm_isdst;
};
of(p)		(((p)->_flag&_IOEOF)!=0)
#define	ferror(p)	(((p)->_flag&_IOERR)!=0)
#define	fileno(p)	(p)->_file

FILE	*fopen();
FILE	*freopen();
FILE	*fdopen();
long	ftell();
char	*fgets();
#define	EOF	(-1)

#define	stdin	(&_iob[0])
#define	stdout	(&_iob[1])
#define	stderr	(&_iob[2])
#defi        ØÕÿ¼Õÿ«H        ä            ,ÖÿðÕÿû/         ,ÖÿôÕÿlib86/include/utmp.h                                                                                   644     140      12          162  3347424415   7567                                                                                                                                                                                                                                                                                                                                                                      struct utmp {
	char	ut_line[8];		/* tty name */
	char	ut_name[8];		/* user id */
	long	ut_time;		/* time on */
};
[] = "/usr/mdec/tboot";
;
	int	tm_isdst;
};
of(p)		(((p)->_flag&_IOEOF)!=0)
#define	ferror(p)	(((p)->_flag&_IOERR)!=0)
#define	fileno(p)	(p)->_file

FILE	*fopen();
FILE	*freopen();
FILE	*fdopen();
long	ftell();
char	*fgets();
#define	EOF	(-1)

#define	stdin	(&_iob[0])
#define	stdout	(&_iob[1])
#define	stderr	(&_iob[2])
#defi        ØÕÿ¼Õÿ«H        ä            ,ÖÿðÕÿû/         ,ÖÿôÕÿlib86/include/varargs.h                                                                                644     140      12          275  3347424415  10254                                                                                                                                                                                                                                                                                                                                                                      typedef char *va_list;
# define va_dcl int va_alist;
# define va_start(list) list = (char *) &va_alist
# define va_end(list)
# define va_arg(list,mode) ((mode *)(list += sizeof(mode)))[-1]

#define	ferror(p)	(((p)->_flag&_IOERR)!=0)
#define	fileno(p)	(p)->_file

FILE	*fopen();
FILE	*freopen();
FILE	*fdopen();
long	ftell();
char	*fgets();
#define	EOF	(-1)

#define	stdin	(&_iob[0])
#define	stdout	(&_iob[1])
#define	stderr	(&_iob[2])
#defi        ØÕÿ¼Õÿ«H        ä            ,ÖÿðÕÿû/         ,ÖÿôÕÿlib86/crt0.a86                                                                                         664     140      12        12737  3347640545   6257                                                                                                                                                                                                                                                                                                                                                                      | C startup routine for IBM DOS
| Non-8087 version
| Modified for MSDOS 2.0, 6/26/83 SAW
| Modified again, 9/7/84 PZ + SAW

| proper operation requires that this be linked as first file.

	.globl	_main		| user program
	.globl	__bomb		| jmp here when stack and data overlap
	.globl	__memtop	| current top of user data
	.globl	__stdi		| file names, for i/o redirection (used
	.globl	__stdo		|  by dos_ini, if nonzer)
	.globl	__stde

	.globl	__exit		| exit code
	.globl	_etext		| end of text segment
	.globl	_edata		| end of data segment
	.globl	_end		| end of bss segment
	.globl	fpinit		| 8087 initialization
	.globl	_dos_ini	| system call writearound initialization
	.globl	_prints		| trivial string i/o for messages

qmark = 077	| question mark character
space = 040	| space character
grt	= 62	| greater than
lt	= 60	| less than
and	= 38	| ampersand

| format of memory:
|	---------------  <- 0x0 (CS, plus on entry DS, ES, SS)
|	 DOS Interface
|	---------------  <- 0x100
|	     code
|	---------------  <- mod 16 boundary (after setup: DS, ES, SS)
|	   data,bss
|
|
|
|	    stack
|	---------------  <- min(base of data + 64K, top of memory)

|| set up segment registers and stack pointer
	cli			| turn off interupts until segment hacking complete
	mov	ax,#_etext+15	| top of program segment
	movb	cl,*4		| convert into segment value
	shr	ax,cl
	mov	bx,cs		| now add in base of "instruction space"
	add	ax,bx
	mov	es,ax		| set up "data space" segment regs
	mov	ss,ax		| we'll do DS after copying JCL

	mov	sp,*0		| start stack at top of "data space"
	mov	bx,0x2		| see how big memory is... (in 16 byte hunks)
	sub	bx,ax		| calculate how much is available for data space
	cmp	bx,#0x1000	| if larger than 64K, sp is set correctly
	jae	spok
	shl	bx,cl		| if smaller, convert what we have into offset
	mov	sp,bx		| and use that as top of stack
spok:	sti

| Now SP and SS have their final values... compute total size, in pp, to
|   tell DOS how much we're using:
	mov	ax,sp
	shr	ax,cl		| data seg size, in pp.
	jne	spnz
	mov	ax,#0x1000
spnz:	mov	cx,ss
	add	ax,cx		| pp ptr beyond data segment.
	mov	cx,cs
	sub	ax,cx		| Total size, in pp, of whole shebang.
	push	es
	push	cs
	pop	es		| set es to base for DOS call
	mov	bx,ax
	mov	ah,#0x4A	| SETBLOCK dos call
	int	0x21
	pop	es

|| create argc and argv from JCL provided by DOS.
	cld
	mov	si,#0x80	| start of JCL string
	lodb			| AL gets string length
	movb	cl,al		| make it into full word => CX
	movb	ch,*0

	sub	sp,*3		| reserve space for "?" + nulls
	sub	sp,cx		| space for JCL string
	and	sp,*0xFFFE	| word align stack for 8086...

	mov	di,sp		| argv[0] = "?"
	movb	al,*qmark
	stob
	movb	al,*0
	stob

	movb	bl,*1		| temporary copy of argc
	movb	bh,*0		| last character seen

	jcxz	aend		| if (length(JCL) == 0) punt following code

aloop:	lodb			| get next character from jcl
	cmpb	al,*space	| spacing chars mark end of current token
	jg	L1
	movb	al,*0		| change spacing chars into nulls
	cmpb	bh,*0		| incr argc (bl) if last char was end of token 
	je	L1
	incb	bl
L1:	stob			| save next character into argv
	movb	bh,al		| keep track of last character read
	loop	aloop		| run through all the characters

aend:	movb	al,*0		| finish last element of argv with a null
	stob
	cmp	bh,*0		| and bump argc if appropriate
	je	L2
	incb	bl

L2:	mov	cx,es		| make data segment point to real data segment
	mov	ds,cx
	mov	si,sp		| SI = beginning of argv datum
	mov	cl,bl		| CX = argc
	mov	ch,*0
	sub	sp,cx		| allocate space for argv vector
	sub	sp,cx		| remember to allocate words!

	mov	di,sp		| DI = &argv[0]
	mov	dx,*-1		| will be used for count below
	j	L4

L3:	movb	al,*0		| set up to use scab to search for nulls
	xchg	si,di		| get pointers into correct regs
	xchg	cx,dx

	repnz			| else, its a standard arg.
	scab			| skip over first token
	repz
	scab			| skip over nulls
	xchg	cx,dx
	xchg	si,di
	dec	si		| backup argv datum pointer

L4:	mov	al,(si)		| Check for special cases:
	cmp	al,*grt		| redirect output?
	jz	stdo		| yup.
	cmp	al,*lt		| input?
	jz	stdi

	mov	ax,si		| stick current pointer into argv
	stow
L41:	loop	L3

	mov	ax,sp		| set up two arguments to _main, first argv
	push	ax	
	mov	bh,*0
	push	bx		| and then argc

	mov	ax,sp		| compute lower stack limit
	sub	ax,*64		| give ourselves a little breathing room
	cmp	ax,#_end	| have we already run out of space?
	ja	Lok

__bomb:	mov	ax,#Lmsg	| oops, tell user and then abort
	push	ax
	call	_prints
	int	0x20

Lok:	mov	cx,#_end	| zero bss storage
	mov	di,#_edata	| starting at end of initialized data
	sub	cx,di
	jz	Lclear		| no bss => nothing to do
	shr	cx,*1		| change into word count
	xor	ax,ax		| ax will be stored into each word of bss
	repz			| don't let the "z" fool you!
	stow

Lclear:
|	call	fpinit		| set up 8087 modes
	call	_dos_ini	| set up for system calls

	call	_main		| let user do his thing...
	add	sp,*4

	push	ax
	call	__exit		| clean up, etc.

	mov	bx,sp		| if anyone cares, put exit status in ax
	mov	ax,*2(bx)
	int	0x20		| this really exits

| I/O redirect hackery:

stdi:	inc	si		| Skip over the '<'
	mov	__stdi,si	| Just tuck away name, for dos_init.
	dec	bx		| but correct argc.
	jmp	L41		| and return to loop.

stdo:	inc	si		| skip the '>'
	mov	al,(si)		| check for std err redirection.
	cmp	al,*and		| (blah) csh syntax.
	jnz	stdo1		| nope, just stdout.
	inc	si
	mov	__stde,si	| save both away.
stdo1:	mov	__stdo,si
	dec	bx		| argc adjustment
	jmp	L41

	.data
	.even
__memtop:
	.word	_end		| current top of user data
__stdi:	.word	0		| file names, for i/o redirection.
__stdo:	.word	0
__stde:	.word	0

Lmsg:	.ascii	"*** Not enough memory, aborting..."
	.byte	0xa,0xd,0
| but correct argc.
	jmp	L41		| alib86/crt/Makefile                                                                                     444     140      12          332  3347424345   7235                                                                                                                                                                                                                                                                                                                                                                      # Description file for crt: primitive functions, arithmetic etc.

OBJECTS =	abort.b arith.b mcount.b

all:		$(OBJECTS)

abort.b:	abort.a86
		a86 abort

arith.b:	arith.a86
		a86 arith

mcount.b:	mcount.a86
		a86 mcount
stdo,si
	dec	bx		| argc adjustment
	jmp	L41

	.data
	.even
__memtop:
	.word	_end		| current top of user data
__stdi:	.word	0		| file names, for i/o redirection.
__stdo:	.word	0
__stde:	.word	0

Lmsg:	.ascii	"*** Not enough memory, aborting..."
	.byte	/usr/src/local/Machines/8086/lib86/crt     lib86/crt/abort.a86                                                                                    444     140      12          137  3347424345   7227                                                                                                                                                                                                                                                                                                                                                                      |C library -- abort

	.globl	_abort
	.text
_abort:
	int	0x20		| this'll go back to DOS...
	ret
unt.b

all:		$(OBJECTS)

abort.b:	abort.a86
		a86 abort

arith.b:	arith.a86
		a86 arith

mcount.b:	mcount.a86
		a86 mcount
stdo,si
	dec	bx		| argc adjustment
	jmp	L41

	.data
	.even
__memtop:
	.word	_end		| current top of user data
__stdi:	.word	0		| file names, for i/o redirection.
__stdo:	.word	0
__stde:	.word	0

Lmsg:	.ascii	"*** Not enough memory, aborting..."
	.byte	/usr/src/local/Machines/8086/lib86/crt     lib86/crt/arith.a86                                                                                    444     140      12        11503  3347424346   7267                                                                                                                                                                                                                                                                                                                                                                      | 8087 based arithmetic support.

	.text

	.globl	fpinit
fpinit:	finit			| initialize 8087 to known state
	push	ax		| get of word of storage to play with
	mov	bx,sp
	fwait
	fstcw	(bx)		| get control word so we can diddle bits
	fwait
	or	(bx),#0x0C00	| set rounding control to chop mode
	fwait
	fldcw	(bx)
	fwait
	pop	ax
	ret

|	double modf (value, iptr)
|		double value;
|		double *iptr;
|
|	Modf returns the fractional part of "value", and stores the integer
|	part indirectly through "iptr".
|

	.globl	_modf
_modf:	mov	bx,sp		| so we can address operands
	fwait
	fldd	*2(bx)		| get VALUE
	fwait
	fld	0		| and make a copy
	fwait
	frndint			| get integer part
	mov	bx,*10(bx)	| get IPTR
	fstd	(bx)		| and save integer part where ever it says
	fwait
	fsubrp	1,0		| now calculate fraction
	fwait
	fabs			| and make positive
	ret			| fractional part returned as result

|	double ldexp (value, exp)
|		double value;
|		int exp;
|
|	Ldexp returns value*2**exp, if that result is in range.
|	If underflow occurs, it returns zero.  If overflow occurs,
|	it returns a value of appropriate sign and largest
|	possible magnitude.  In case of either overflow or underflow,
|	the external int "errno" is set to ERANGE.  Note that errno is
|	not modified if no error occurs, so if you intend to test it
|	after you use ldexp, you had better set it to something
|	other than ERANGE first (zero is a reasonable value to use).

	erange = 34

	.data
	.globl	_errno		| error flag

Lhuge:	.word	0xffff		| The largest number that can
	.word	0xffff		|   be represented in a long floating
	.word	0xffff		|   number.  This is given in hex in order
	.word	0x7fff		|   to avoid floating conversions

	.text
	.globl	_ldexp

_ldexp:	mov	bx,sp		| so we can address operands
	mov	ax,*8(bx)	| get word containing exponent
	movb	cl,*4		| shift and mask to get it
	shr	ax,cl
	and	ax,*0x7FF
	jz	Ld1

	add	ax,*10(bx)	| ax = new biased exponent
	jle	Lunder		| if it's <= 0, we have an underflow
	cmp	ax,#0x7FF	| otherwise check it it's too big
	jg	Lover		| jump if overflow

	shl	ax,cl		| shift exponent back to where it belongs
	and	*8(bx),#0x800F	| get rid of old one
	or	*8(bx),ax	| and install new
	fldd	*2(bx)		| return resulting number as answer
	fwait
Ld1:	ret

Lunder:	fldz			| Result is zero
	j	Lerr		| Join general error code

Lover:	fldd	Lhuge		| Largest possible floating magnitude
	test	*8(bx),#0x8000	| make answer same sign as operand
	jz	Lerr
	fchs

Lerr:	mov	_errno,#erange	| Indicate range error
	ret

| long arithmetic routines...  uses 8087.

	.globl	lmul
lmul:	mov	bx,sp
	fwait
	fldl	*2(bx)
	fwait
	fmull	*6(bx)
	fwait
	fstpl	*2(bx)
	fwait
	mov	ax,*2(bx)
	mov	dx,*4(bx)
	ret

	.globl	ldiv
ldiv:	mov	bx,sp
	fwait
	fldl	*2(bx)
	fwait
	fdivl	*6(bx)
	fwait
	fstpl	*2(bx)		| must be in chop mode
	fwait
	mov	ax,*2(bx)
	mov	dx,*4(bx)
	ret

	.globl	lrem
lrem:	mov	bx,sp
	fwait
	fldl	*6(bx)		| load divisor
	fwait
	fldl	*2(bx)		| load dividend
	fwait
	fprem			| do it
	fwait
	fstpl	*2(bx)		| must be in chop mode
	fwait
	mov	ax,*2(bx)
	mov	dx,*4(bx)
	fstpl	*6(bx)		| pop other arg off 8087 stack ??
	fwait
	ret

	.globl	alrem
alrem:	mov	bx,sp
	fwait
	fldl	*4(bx)
	mov	bx,*2(bx)
	fwait
	fldl	(bx)
	fwait
	fprem
	fwait
	fstpl	(bx)
	fwait
	mov	ax,(bx)
	mov	dx,*2(bx)
	mov	bx,sp		| hope nothing has changed
	fstpl	*6(bx)		| pop top of 8087 stack
	fwait
	ret

	.globl	almul
almul:	mov	bx,sp
	fwait
	fldl	*4(bx)
	mov	bx,*2(bx)
	fwait
	fmull	(bx)
	fwait
	fstpl	(bx)
	fwait
	mov	ax,(bx)
	mov	dx,*2(bx)
	ret

	.globl	aldiv
aldiv:	mov	bx,sp
	fwait
	fldl	*4(bx)
	mov	bx,*2(bx)
	fwait
	fdivrl	(bx)
	fwait
	fstpl	(bx)
	fwait
	mov	ax,(bx)
	mov	dx,*2(bx)
	ret


| hack uldiv routine (DG)
| This bombs bx,cx,ax,dx	result in dx,ax

	.globl	uldiv
uldiv:	mov	bx,sp

	mov	ax,*8(bx)	| Is divisor < 2 ** 16
	cmp	ax,#0;
	jne	4$
	mov	ax,*4(bx)	| get high word of dividend
	mov	dx,#0
	div	*6(bx)		| divide high
	mov	cx,ax		| store high quotient for a sec...
	mov	ax,*2(bx)	| dx,ax = diviend low + remainder * 2^16
	div	*6(bx)		| divide again 
	mov	dx,cx		| restore quotient high
	ret

4$:	mov	cx,#0		| clear cx to hold count
	mov	ax,*6(bx)
	mov	dx,*8(bx)	| get divisor
5$:	shr	dx,#1		| shift divisor until < 2^16
	rcr	ax,#1
	inc	cx
	or	dx,dx		| are we there yet?
	jne	5$		| No, try some more.
	push	ax		| store divisor for a sec..
	mov	ax,*2(bx)
	mov	dx,*4(bx)	| shift dividend by same amount
6$:	shr	dx,*1
	rcr	ax,*1
	dec	cx
	or	cx,cx
	jne	6$		| cx better be >0 to begin with
	div	*-2(bx)		| divide by stacked divisor
	add	sp,*2		| get rid of stacked divisor
	push	ax		| save proposed quotient
	push	bx		| we'll need it later
	mov	dx,*0
	push	dx
	push	ax
	push	*8(bx)
	push	*6(bx)		| stack args for ulmul
	call	lmul		| same as ulmul
	add	sp,*8		| get rid of args
	pop	bx		| restore bx

	sub	ax,*2(bx)	| a lot of trouble to do long compares
	sbb	dx,*4(bx)
	cmp	dx,#0
	jl	8$
	jne	7$
	or	ax,#0
	jz	8$

7$:	pop	ax
	mov	dx,*0
	sub	ax,*1
	sbb	dx,*0
	ret
8$:	pop	ax
	mov	dx,*0
	ret

 begin with
	div	*-2(bx)		| divide by stacked divisor
	add	sp,*2		| get rid of stacked divisor
	push	ax		| save proposed quotient
	push	bx		| we'll need it later
	mov	dx,*0
	push	dx
	push	alib86/crt/mcount.a86                                                                                   444     140      12         2265  3347424346   7452                                                                                                                                                                                                                                                                                                                                                                      |Count subroutine calls during profiling

|The basic idea here is a call of the form:
|
|	mov	bx,#LABEL
|	call	mcount
|	.data
|LABEL:	.word	0
|	.text
|
|which is generated automatically by the C compiler for each subroutine call.
|The first time mcount is called, the contents of LABEL will be 0 so mcount
|will allocate two words from its buffer like:
|
|struct
|{
|	char *fncptr;		/* ptr to subroutine */
|	long fnccnt;		/* number of calls to this function */
|};
|
|and fill int fncptr from the return pc, fill in LABEL with a ptr to
|the newly allocated structure and bump the count.  On subsequent calls,
|the contents of LABEL will be used to just bump the count.

.globl	mcount
.comm	cntbase,2

mcount:	mov	ax,(bx)		| fetch contents of LABEL
	or	ax,ax
	jnz	L1		| something there
	push	di
	mov	di,cntbase	| ptr to next available cnt structure
	add	cntbase,*4	| bump cntbase to followng structure
	push	bx
	mov	bx,sp
	mov	ax,*4(bx)	| first store return addr as function pointer
	stow
	pop	bx		| put pointer to count into LABEL
	mov	(bx),di
	mov	(di),*1		| finally put initial count into structure
	mov	*2(di),*0
	pop	di
	ret

L1:	mov	bx,ax
	add	(bx),*1		| bump the function count
	adc	*2(bx),*0
	ret
tbase,2

mcount:	mov	ax,(bx)		| fetch contents of LABEL
	or	ax,ax
	jnz	L1		| something there
	push	di
	mov	di,cntbase	| ptr to next available cnt structure
	add	cntbase,*4	| bump cntbase to followng structure
	push	bx
	mov	bx,sp
	mov	ax,*4(bx)	| first store return addr as function pointer
	stow
	pop	bx		| put pointer to count intlib86/ncrt/Makefile                                                                                    444     140      12          165  3347424446   7421                                                                                                                                                                                                                                                                                                                                                                      # Description file for ncrt: primitive functions, arithmetic etc.

all:
	cd ../crt; make
	cp ../crt/*.b .
	a86 arith
,ax
	add	(bx),*1		| bump the function count
	adc	*2(bx),*0
	ret
tbase,2

mcount:	mov	ax,(bx)		| fetch contents of LABEL
	or	ax,ax
	jnz	L1		| something there
	push	di
	mov	di,cntbase	| ptr to next available cnt structure
	add	cntbase,*4	| bump cntbase to followng structure
	push	bx
	mov	bx,sp
	mov	ax,*4(bx)	| first store return addr as function point/usr/src/local/Machines/8086/lib86/ncrt     lib86/ncrt/arith.a86                                                                                   444     140      12        11163  3347424446   7450                                                                                                                                                                                                                                                                                                                                                                      | Long arithmetic routines for 8086. Does not use 8087

	.text

	.globl	fpinit
fpinit:	ret			| 8087 init. Dummy here for compatability


| long arithmetic routines...  does not 8087.

| This one should work for both lmul and ulmul 

	.globl	lmul
	.globl	ulmul
ulmul:
lmul:	mov	bx,sp
	mov	ax,*2(bx)	| alow into acc
	mul	*6(bx)		| alow * blow
	push	dx		| push high
	push	ax		| push low
	mov	ax,*2(bx)	| load alow
	mul	*8(bx)		| bhigh * alow
	push	ax		| only save low half
	mov	ax,*4(bx)	| load ahigh
	mul	*6(bx)		| ahigh * blow
	add	ax,*-2(bx)	| ahigh*blow + alow * bhigh
	mov	dx,ax		| ax << 16
	mov	ax,*-4(bx)	| low half of result
	add	dx,*-6(bx)	| add high halves
	add	sp,*6		| restore stack pointer
	ret

| This one is weird
| This should work for almul and aulmul

	.globl	almul
almul:	mov	bx,sp
	mov	bx,*2(bx)	| load ptr to arg in bx
	push	*2(bx)		| push high
	push	(bx)		| push low
	mov	bx,sp		| I don't believe this
	
	mov	ax,(bx)		| alow into acc
	mul	*8(bx)		| alow * blow
	push	dx		| push high
	push	ax		| push low
	mov	ax,(bx)	 	| load alow
	mul	*10(bx)		| bhigh * alow
	push	ax		| only save low half
	mov	ax,*2(bx)	| load ahigh
	mul	*8(bx)		| ahigh * blow
	add	ax,*-2(bx)	| ahigh*blow + alow * bhigh
	mov	dx,ax		| ax << 16
	mov	ax,*-4(bx)	| low half of result
	add	dx,*-6(bx)	| add high halves
	add	sp,*10		| restore stack pointer
	mov 	bx,sp		| store result sp should be in right place
	mov	bx,*2(bx)	| get pointer to result
	mov	(bx),ax		| store low word
	mov	*2(bx),dx	| store high word
	ret


| hack uldiv routine
| This bombs bx,cx,ax,dx	result in dx,ax

	.globl	uldiv
uldiv:	mov	bx,sp

	mov	ax,*8(bx)	| Is divisor < 2 ** 16
	cmp	ax,#0;
	jne	4$
	mov	ax,*4(bx)	| get high word of dividend
	mov	dx,#0
	div	*6(bx)		| divide high
	mov	cx,ax		| store high quotient for a sec...
	mov	ax,*2(bx)	| dx,ax = diviend low + remainder * 2^16
	div	*6(bx)		| divide again 
	mov	dx,cx		| restore quotient high
	ret

4$:	mov	cx,#0		| clear cx to hold count
	mov	ax,*6(bx)
	mov	dx,*8(bx)	| get divisor
5$:	shr	dx,#1		| shift divisor until < 2^16
	rcr	ax,#1
	inc	cx
	or	dx,dx		| are we there yet?
	jne	5$		| No, try some more.
	push	ax		| store divisor for a sec..
	mov	ax,*2(bx)
	mov	dx,*4(bx)	| shift dividend by same amount
6$:	shr	dx,*1
	rcr	ax,*1
	dec	cx
	or	cx,cx
	jne	6$		| cx better be >0 to begin with
	div	*-2(bx)		| divide by stacked divisor
	add	sp,*2		| get rid of stacked divisor
	push	ax		| save proposed quotient
	push	bx		| we'll need it later
	mov	dx,*0
	push	dx
	push	ax
	push	*8(bx)
	push	*6(bx)		| stack args for ulmul
	call	lmul		| same as ulmul
	add	sp,*8		| get rid of args
	pop	bx		| restore bx

	sub	ax,*2(bx)	| a lot of trouble to do long compares
	sbb	dx,*4(bx)
	cmp	dx,#0
	jl	8$
	jne	7$
	or	ax,#0
	jz	8$

7$:	pop	ax
	mov	dx,*0
	sub	ax,*1
	sbb	dx,*0
	ret
8$:	pop	ax
	mov	dx,*0
	ret


| A really cheap ldiv. I remember the sign, convert the args and call uldiv
| Later I'll do it better (inline)

	.globl	ldiv
ldiv:	mov	bx,sp
	mov	cx,*0		| clear cx to hold sign of result
	push	bx		| for later
	push	cx		| cx = *-4(bx)
	mov	ax,*6(bx)	| get divisor
	mov	dx,*8(bx)
	cmp	dx,*0
	jge	9$
	inc	*-4(bx)		| remember one negation
	neg	dx
	neg	ax
	sbb	dx,*0
9$:	push	dx
	push	ax
	mov	ax,*2(bx)	| get dividend
	mov	dx,*4(bx)
	cmp	dx,*0
	jge	10$
	inc	*-4(bx)		| remember one negation
	neg	dx
	neg	ax
	sbb	dx,*0
10$:	push	dx
	push	ax
	call	uldiv
	add	sp,*8
	pop	cx
	pop	bx		| clean up stack, restore bx,cx
	and	cx,*1		| test sign
	jz	11$		| result should be positive return
	not	ax		| else negate result; ignore overflow issues
	not	dx
	add	ax,*1
	adc	dx,*0
11$:	ret

| Another cheapy. Calls ldiv and lmul  rem = dividend - dnd/dvsr * dvsr

	.globl	lrem
lrem:	mov	bx,sp
	push	bx
	push	*8(bx)
	push	*6(bx)
	push	*4(bx)
	push	*2(bx)
	call	ldiv
	add	sp,*8		| clean up stack
	pop	bx
	push	bx		| bx gets creamed by ldiv and lmul
	push	dx
	push	ax
	push	*8(bx)
	push	*6(bx)
	call	lmul
	add	sp,*8
	pop	bx
	sub	ax,*2(bx)
	sbb	dx,*4(bx)
	neg	dx		| negate to get right sign
	neg	ax
	sbb	dx,*0
	ret

| Another cheapy. Calls uldiv and ulmul  rem = dividend - dnd/dvsr * dvsr

	.globl	ulrem
ulrem:	mov	bx,sp
	push	bx
	push	*8(bx)
	push	*6(bx)
	push	*4(bx)
	push	*2(bx)
	call	uldiv
	add	sp,*8		| clean up stack
	pop	bx
	push	bx		| bx gets creamed by ldiv and lmul
	push	dx
	push	ax
	push	*8(bx)
	push	*6(bx)
	call	ulmul
	add	sp,*8
	pop	bx
	sub	ax,*2(bx)
	sbb	dx,*4(bx)
	neg	dx		| negate to get right sign
	neg	ax
	sbb	dx,*0
	ret

	.globl	aldiv
aldiv:	push	bp		| This one is REALLY cheap! -SAW.
	mov	bp,sp
	push	bx

	mov	bx,*4(bp)	| adr for result.
	mov	ax,*6(bp)	| divisor.
	mov	dx,*8(bp)

	push	bx
	push	dx
	push	ax
	push	*2(bx)
	push	*0(bx)
	call	ldiv
	add	sp,*8
	pop	bx

	mov	*0(bx),ax
	mov	*2(bx),dx

	pop	bx
	pop	bp

	ret

bx
	push	bx		| bx gets creamed by ldiv and lmul
	push	dx
	push	ax
	push	*8(bx)
	push	*6(bx)
	call	ulmul
	add	sp,*8
	pop	bx
	sub	ax,*2(bx)
	sbb	dx,*4(bx)
	neg	dx		| negate to get right sign
	neg	ax
	sbb	dx,*0
	ret

	.globl	aldiv
aldiv:	push	bp		| This one is REALLY cheap! -SAW.
	mov	bp,sp
	push	bx

	mov	bx,*4(bp)	| adr for result.
	mov	ax,*6(bp)	| divisor.
	mov	dx,*8(bp)

	push	bx
	push	dx
	pushlib86/gen/Makefile                                                                                     444      30      12         1322  3355666516   7223                                                                                                                                                                                                                                                                                                                                                                      .SUFFIXES: .b
.c.b: ; cc86 -c $<

OBJECTS =	abs.b atoi.b blt.b atof.b atol.b  calloc.b crypt.b\
		ctime.b ctype_.b cuexit.b ecvt.b errlst.b execvp.b clear.b\
		getlogin.b index.b l3.b\
		malloc.b mfill.b frexp.b\
		mktemp.b mon.b perror.b qsort.b rand.b\
		rindex.b sleep.b strcat.b strcatn.b strcmp.b strcmpn.b\
		strcpy.b strcpyn.b strlen.b strncat.b strncmp.b strncpy.b\
		stty.b swab.b tell.b timezone.b ttyname.b ttyslot.b\
		setjmp.b access.b stat.b

all:		$(OBJECTS)

blt.b:		blt.a86
		a86 blt

clear.b:	clear.a86
		a86 clear

mfill.b:	mfill.a86
		a86 mfill

setjmp.b:	setjmp.a86
		a86 setjmp

atof.b:		atof.c
		cc86 -8087 -c atof.c

ecvt.b:		ecvt.c
		cc86 -8087 -c ecvt.c

frexp.b:	frexp.c
		cc86 -8087 -c frexp.c
b\
		mktemp.b mon.b perror.b qsort.b rand.b\
		rindex.b sleep.b strcat.b strcatn.b strcmp.b strcmpn.b\
		strcpy.b strcpyn.b strlen.b strncat.b strncmp.b strncpy.b\
		stty.b swab.b tell.b timezone.b ttyname.b ttyslot.b\
		setjmp.b access.b stat.b

all:		$(OBJECTS)

blt.b:		blt.a86
		a86 blt

clear.b:	clib86/gen/abs.c                                                                                        444     140      12           67  3347642165   6456                                                                                                                                                                                                                                                                                                                                                                      abs(arg)
{

	if(arg < 0)
		arg = -arg;
	return(arg);
}
etjmp.b:	setjmp.a86
		a86 setjmp

atof.b:		atof.c
		cc86 -8087 -c atof.c

ecvt.b:		ecvt.c
		cc86 -8087 -c ecvt.c

frexp.b:	frexp.c
		cc86 -8087 -c frexp.c
b\
		mktemp.b mon.b perror.b qsort.b rand.b\
		rindex.b sleep.b strcat.b strcatn.b strcmp.b strcmpn.b\
		strcpy.b strcpyn.b strlen.b strncat.b strncmp.b strncpy.b\
		stty.b swab.b tell.b timezone.b ttyname.b ttyslot.b\
		setjmp.b access.b stat.b

all:		$(OBJE/usr/src/local/Machines/8086/lib86/gen     lib86/gen/access.c                                                                                     664      30      12          245  3355657625   7160                                                                                                                                                                                                                                                                                                                                                                      access(name, mode)
 char *name;
 { int fid = open(name, 0), nmode=0;
   if (fid >= 0) { close(fid);
		   return 0;
		 }
   if (mode == 2) return 0;
   return -1;
 }
.c

frexp.b:	frexp.c
		cc86 -8087 -c frexp.c
b\
		mktemp.b mon.b perror.b qsort.b rand.b\
		rindex.b sleep.b strcat.b strcatn.b strcmp.b strcmpn.b\
		strcpy.b strcpyn.b strlen.b strncat.b strncmp.b strncpy.b\
		stty.b swab.b tell.b timezone.b ttyname.b ttyslot.b\
		setjmp.b access.b stat.b

all:		$(OBJE/usr/src/local/Machines/8086/lib86/gen     lib86/gen/allocs.c                                                                                     444     140      12          265  3347642165   7206                                                                                                                                                                                                                                                                                                                                                                      #define FREESIZE 16384		/* number of bytes in free storage */

char heap[FREESIZE];				/* this will go in bss */
int allocs[2] = { (int)heap, FREESIZE };	/* this will go in data */
xp.c
		cc86 -8087 -c frexp.c
b\
		mktemp.b mon.b perror.b qsort.b rand.b\
		rindex.b sleep.b strcat.b strcatn.b strcmp.b strcmpn.b\
		strcpy.b strcpyn.b strlen.b strncat.b strncmp.b strncpy.b\
		stty.b swab.b tell.b timezone.b ttyname.b ttyslot.b\
		setjmp.b access.b stat.b

all:		$(OBJE/usr/src/local/Machines/8086/lib86/gen     lib86/gen/atof.c                                                                                       444     140      12         2061  3347642165   6676                                                                                                                                                                                                                                                                                                                                                                      /*
	C library - ascii to floating
*/

#include <ctype.h>

double	twoe56	= 72057594037927936.; /*2^56*/
double	exp5[]	= {5.,25.,625.,390625.,152587890625.,23232710361480712890625.};

double
atof(p)
register char *p;
{
	extern double ldexp();
	register c, exp = 0, eexp = 0;
	double fl = 0, flexp = 1.0;
	int bexp, neg = 1, negexp = 1;

	while((c = *p++) == ' ');
	if (c == '-') neg = -1;	else if (c == '+'); else --p;

	while ((c = *p++), isdigit(c))
		if (fl < twoe56) fl = 10*fl + (c-'0'); else exp++;
	if (c == '.')
	while ((c = *p++), isdigit(c))
		if (fl < twoe56)
		{
			fl = 10*fl + (c-'0');
			exp--;
		}
	if ((c == 'E') || (c == 'e'))
	{
		if ((c= *p++) == '+'); else if (c=='-') negexp = -1; else --p;
		while ((c = *p++), isdigit(c)) eexp = 10*eexp + (c-'0');
		if (negexp < 0) eexp = -eexp; exp += eexp;
	}
	bexp = exp;
	if (exp < 0) exp = -exp;

	for (c = 0; c < 6; c++)
	{
		if (exp & 01) flexp *= exp5[c];
		exp >>= 1; if (exp == 0) break;
	}

	if (bexp < 0) fl /= flexp; else fl *= flexp;
	fl = ldexp(fl, bexp);
	if (neg < 0) return(-fl); else return(fl);
}
twoe56)
		{
			fl = 10*fl + (c-'0');
			exp--;
		}
	if ((c == 'E') || (c == 'e'))
	{
		if ((c= *p++) == '+'); else if (c=='-') negexp = -1; else --p;
		while ((c = *p++), isdigit(c)) eexp = 10*eexp + (c-'0');
		if (negexp < 0) eexp = -eexp; exp += eexp;
	}
	bexp = exp;
	if (exp < 0) exp = -exp;

	for (c = 0; c < 6; c++)
	{
		if (exp & 01) flexp *= exp5[c];
		exp >>= 1; if (exp == 0) break;
	}

	if (bexp < 0) fl /= flexp; else fl *= flexp;
	fl = ldexp(fl, bexplib86/gen/atoi.c                                                                                       444     140      12          427  3347642165   6665                                                                                                                                                                                                                                                                                                                                                                      atoi(p)
register char *p;
{
	register int n;
	register int f;

	n = 0;
	f = 0;
	for(;;p++) {
		switch(*p) {
		case ' ':
		case '\t':
			continue;
		case '-':
			f++;
		case '+':
			p++;
		}
		break;
	}
	while(*p >= '0' && *p <= '9')
		n = n*10 + *p++ - '0';
	return(f? -n: n);
}
p = -eexp; exp += eexp;
	}
	bexp = exp;
	if (exp < 0) exp = -exp;

	for (c = 0; c < 6; c++)
	{
		if (exp & 01) flexp *= exp5[c];
		exp >>= 1; if (exp == 0) break;
	}

	if (bexp < 0) fl /= fl/usr/src/local/Machines/8086/lib86/gen     lib86/gen/atol.c                                                                                       444     140      12          424  3347642166   6666                                                                                                                                                                                                                                                                                                                                                                      long
atol(p)
register char *p;
{
	long n;
	register int f;

	n = 0;
	f = 0;
	for(;;p++) {
		switch(*p) {
		case ' ':
		case '\t':
			continue;
		case '-':
			f++;
		case '+':
			p++;
		}
		break;
	}
	while(*p >= '0' && *p <= '9')
		n = n*10 + *p++ - '0';
	return(f? -n: n);
}

}
p = -eexp; exp += eexp;
	}
	bexp = exp;
	if (exp < 0) exp = -exp;

	for (c = 0; c < 6; c++)
	{
		if (exp & 01) flexp *= exp5[c];
		exp >>= 1; if (exp == 0) break;
	}

	if (bexp < 0) fl /= fl/usr/src/local/Machines/8086/lib86/gen     lib86/gen/calloc.c                                                                                     444     140      12          701  3347642166   7162                                                                                                                                                                                                                                                                                                                                                                      /*	calloc - allocate and clear memory block
*/
#define CHARPERINT (sizeof(int)/sizeof(char))
#define NULL 0

char *
calloc(num, size)
unsigned num, size;
{
	register char *mp;
	char *malloc();
	register int *q;
	register m;

	num *= size;
	mp = malloc(num);
	if(mp == NULL)
		return(NULL);
	q = (int *) mp;
	m = (num+CHARPERINT-1)/CHARPERINT;
	while(--m>=0)
		*q++ = 0;
	return(mp);
}

cfree(p, num, size)
char *p;
unsigned num, size;
{
	free(p);
}
 (bexp < 0) fl /= fl/usr/src/local/Machines/8086/lib86/gen     lib86/gen/crypt.c                                                                                      444     140      12        16617  3347642167   7144                                                                                                                                                                                                                                                                                                                                                                      /*
 * This program implements the
 * Proposed Federal Information Processing
 *  Data Encryption Standard.
 * See Federal Register, March 17, 1975 (40FR12134)
 */

/*
 * Initial permutation,
 */
static	char	IP[] {
	58,50,42,34,26,18,10, 2,
	60,52,44,36,28,20,12, 4,
	62,54,46,38,30,22,14, 6,
	64,56,48,40,32,24,16, 8,
	57,49,41,33,25,17, 9, 1,
	59,51,43,35,27,19,11, 3,
	61,53,45,37,29,21,13, 5,
	63,55,47,39,31,23,15, 7,
};

/*
 * Final permutation, FP = IP^(-1)
 */
static	char	FP[] {
	40, 8,48,16,56,24,64,32,
	39, 7,47,15,55,23,63,31,
	38, 6,46,14,54,22,62,30,
	37, 5,45,13,53,21,61,29,
	36, 4,44,12,52,20,60,28,
	35, 3,43,11,51,19,59,27,
	34, 2,42,10,50,18,58,26,
	33, 1,41, 9,49,17,57,25,
};

/*
 * Permuted-choice 1 from the key bits
 * to yield C and D.
 * Note that bits 8,16... are left out:
 * They are intended for a parity check.
 */
static	char	PC1_C[] {
	57,49,41,33,25,17, 9,
	 1,58,50,42,34,26,18,
	10, 2,59,51,43,35,27,
	19,11, 3,60,52,44,36,
};

static	char	PC1_D[] {
	63,55,47,39,31,23,15,
	 7,62,54,46,38,30,22,
	14, 6,61,53,45,37,29,
	21,13, 5,28,20,12, 4,
};

/*
 * Sequence of shifts used for the key schedule.
*/
static	char	shifts[] {
	1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1,
};

/*
 * Permuted-choice 2, to pick out the bits from
 * the CD array that generate the key schedule.
 */
static	char	PC2_C[] {
	14,17,11,24, 1, 5,
	 3,28,15, 6,21,10,
	23,19,12, 4,26, 8,
	16, 7,27,20,13, 2,
};

static	char	PC2_D[] {
	41,52,31,37,47,55,
	30,40,51,45,33,48,
	44,49,39,56,34,53,
	46,42,50,36,29,32,
};

/*
 * The C and D arrays used to calculate the key schedule.
 */

static	char	C[28];
static	char	D[28];
/*
 * The key schedule.
 * Generated from the key.
 */
static	char	KS[16][48];

/*
 * Set up the key schedule from the key.
 */

setkey(key)
char *key;
{
	register i, j, k;
	int t;

	/*
	 * First, generate C and D by permuting
	 * the key.  The low order bit of each
	 * 8-bit char is not used, so C and D are only 28
	 * bits apiece.
	 */
	for (i=0; i<28; i++) {
		C[i] = key[PC1_C[i]-1];
		D[i] = key[PC1_D[i]-1];
	}
	/*
	 * To generate Ki, rotate C and D according
	 * to schedule and pick up a permutation
	 * using PC2.
	 */
	for (i=0; i<16; i++) {
		/*
		 * rotate.
		 */
		for (k=0; k<shifts[i]; k++) {
			t = C[0];
			for (j=0; j<28-1; j++)
				C[j] = C[j+1];
			C[27] = t;
			t = D[0];
			for (j=0; j<28-1; j++)
				D[j] = D[j+1];
			D[27] = t;
		}
		/*
		 * get Ki. Note C and D are concatenated.
		 */
		for (j=0; j<24; j++) {
			KS[i][j] = C[PC2_C[j]-1];
			KS[i][j+24] = D[PC2_D[j]-28-1];
		}
	}
}

/*
 * The E bit-selection table.
 */
static	char	E[48];
static	char	e[] {
	32, 1, 2, 3, 4, 5,
	 4, 5, 6, 7, 8, 9,
	 8, 9,10,11,12,13,
	12,13,14,15,16,17,
	16,17,18,19,20,21,
	20,21,22,23,24,25,
	24,25,26,27,28,29,
	28,29,30,31,32, 1,
};

/*
 * The 8 selection functions.
 * For some reason, they give a 0-origin
 * index, unlike everything else.
 */
static	char	S[8][64] {
	14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7,
	 0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8,
	 4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0,
	15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13,

	15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10,
	 3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5,
	 0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15,
	13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9,

	10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8,
	13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1,
	13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7,
	 1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12,

	 7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15,
	13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9,
	10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4,
	 3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14,

	 2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9,
	14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6,
	 4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14,
	11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3,

	12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11,
	10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8,
	 9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6,
	 4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13,

	 4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1,
	13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6,
	 1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2,
	 6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12,

	13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7,
	 1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2,
	 7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8,
	 2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11,
};

/*
 * P is a permutation on the selected combination
 * of the current L and key.
 */
static	char	P[] {
	16, 7,20,21,
	29,12,28,17,
	 1,15,23,26,
	 5,18,31,10,
	 2, 8,24,14,
	32,27, 3, 9,
	19,13,30, 6,
	22,11, 4,25,
};

/*
 * The current block, divided into 2 halves.
 */
static	char	L[32], R[32];
static	char	tempL[32];
static	char	f[32];

/*
 * The combination of the key and the input, before selection.
 */
static	char	preS[48];

/*
 * The payoff: encrypt a block.
 */

encrypt(block, edflag)
char *block;
{
	int i, ii;
	register t, j, k;

	/*
	 * First, permute the bits in the input
	 */
	for (j=0; j<64; j++)
		L[j] = block[IP[j]-1];
	/*
	 * Perform an encryption operation 16 times.
	 */
	for (ii=0; ii<16; ii++) {
		/*
		 * Set direction
		 */
		if (edflag)
			i = 15-ii;
		else
			i = ii;
		/*
		 * Save the R array,
		 * which will be the new L.
		 */
		for (j=0; j<32; j++)
			tempL[j] = R[j];
		/*
		 * Expand R to 48 bits using the E selector;
		 * exclusive-or with the current key bits.
		 */
		for (j=0; j<48; j++)
			preS[j] = R[E[j]-1] ^ KS[i][j];
		/*
		 * The pre-select bits are now considered
		 * in 8 groups of 6 bits each.
		 * The 8 selection functions map these
		 * 6-bit quantities into 4-bit quantities
		 * and the results permuted
		 * to make an f(R, K).
		 * The indexing into the selection functions
		 * is peculiar; it could be simplified by
		 * rewriting the tables.
		 */
		for (j=0; j<8; j++) {
			t = 6*j;
			k = S[j][(preS[t+0]<<5)+
				(preS[t+1]<<3)+
				(preS[t+2]<<2)+
				(preS[t+3]<<1)+
				(preS[t+4]<<0)+
				(preS[t+5]<<4)];
			t = 4*j;
			f[t+0] = (k>>3)&01;
			f[t+1] = (k>>2)&01;
			f[t+2] = (k>>1)&01;
			f[t+3] = (k>>0)&01;
		}
		/*
		 * The new R is L ^ f(R, K).
		 * The f here has to be permuted first, though.
		 */
		for (j=0; j<32; j++)
			R[j] = L[j] ^ f[P[j]-1];
		/*
		 * Finally, the new L (the original R)
		 * is copied back.
		 */
		for (j=0; j<32; j++)
			L[j] = tempL[j];
	}
	/*
	 * The output L and R are reversed.
	 */
	for (j=0; j<32; j++) {
		t = L[j];
		L[j] = R[j];
		R[j] = t;
	}
	/*
	 * The final output
	 * gets the inverse permutation of the very original.
	 */
	for (j=0; j<64; j++)
		block[j] = L[FP[j]-1];
}

char *
crypt(pw,salt)
char *pw;
char *salt;
{
	register i, j, c;
	int temp;
	static char block[66], iobuf[16];
	for(i=0; i<66; i++)
		block[i] = 0;
	for(i=0; (c= *pw) && i<64; pw++){
		for(j=0; j<7; j++, i++)
			block[i] = (c>>(6-j)) & 01;
		i++;
	}
	
	setkey(block);
	
	for(i=0; i<66; i++)
		block[i] = 0;

	for(i=0;i<48;i++)
		E[i] = e[i];

	for(i=0;i<2;i++){
		c = *salt++;
		iobuf[i] = c;
		if(c>'Z') c -= 6;
		if(c>'9') c -= 7;
		c -= '.';
		for(j=0;j<6;j++){
			if((c>>j) & 01){
				temp = E[6*i+j];
				E[6*i+j] = E[6*i+j+24];
				E[6*i+j+24] = temp;
				}
			}
		}
	
	for(i=0; i<25; i++)
		encrypt(block,0);
	
	for(i=0; i<11; i++){
		c = 0;
		for(j=0; j<6; j++){
			c <<= 1;
			c |= block[6*i+j];
			}
		c += '.';
		if(c>'9') c += 7;
		if(c>'Z') c += 6;
		iobuf[i+2] = c;
	}
	iobuf[i+2] = 0;
	if(iobuf[1]==0)
		iobuf[1] = iobuf[0];
	return(iobuf);
}
r(i=0;i<2;i++){
		c = *salt++;
		iobuf[i] = c;
		if(c>'Z') c -= 6;
		if(c>'9') c -= 7;
		c -= '.';
		for(j=0;j<6;lib86/gen/ctime.c                                                                                      444     140      12        10653  3347642167   7076                                                                                                                                                                                                                                                                                                                                                                      /*
 * This routine converts time as follows.
 * The epoch is 0000 Jan 1 1970 GMT.
 * The argument time is in seconds since then.
 * The localtime(t) entry returns a pointer to an array
 * containing
 *  seconds (0-59)
 *  minutes (0-59)
 *  hours (0-23)
 *  day of month (1-31)
 *  month (0-11)
 *  year-1970
 *  weekday (0-6, Sun is 0)
 *  day of the year
 *  daylight savings flag
 *
 * The routine calls the system to determine the local
 * timezone and whether Daylight Saving Time is permitted locally.
 * (DST is then determined by the current US standard rules)
 * There is a table that accounts for the peculiarities
 * undergone by daylight time in 1974-1975.
 *
 * The routine does not work
 * in Saudi Arabia which runs on Solar time.
 *
 * asctime(tvec))
 * where tvec is produced by localtime
 * returns a ptr to a character string
 * that has the ascii time in the form
 *	Thu Jan 01 00:00:00 1970n0\\
 *	01234567890123456789012345
 *	0	  1	    2
 *
 * ctime(t) just calls localtime, then asctime.
 */

#include <time.h>
#include <sys/types.h>
#include <sys/timeb.h>

static	char	cbuf[26];
static	int	dmsize[12] =
{
	31,
	28,
	31,
	30,
	31,
	30,
	31,
	31,
	30,
	31,
	30,
	31
};

/*
 * The following table is used for 1974 and 1975 and
 * gives the day number of the first day after the Sunday of the
 * change.
 */
static struct {
	int	daylb;
	int	dayle;
} daytab[] = {
	5,	333,	/* 1974: Jan 6 - last Sun. in Nov */
	58,	303,	/* 1975: Last Sun. in Feb - last Sun in Oct */
};

struct tm	*gmtime();
char		*ct_numb();
struct tm	*localtime();
char	*ctime();
char	*ct_num();
char	*asctime();

char *
ctime(t)
long *t;
{
	return(asctime(localtime(t)));
}

struct tm *
localtime(tim)
long *tim;
{
	register int dayno;
	register struct tm *ct;
	register daylbegin, daylend;
	long copyt;
	struct timeb systime;

	ftime(&systime);
	copyt = *tim - (long)systime.timezone*60;
	ct = gmtime(&copyt);
	dayno = ct->tm_yday;
	daylbegin = 119;	/* last Sun in Apr */
	daylend = 303;		/* Last Sun in Oct */
	if (ct->tm_year==74 || ct->tm_year==75) {
		daylbegin = daytab[ct->tm_year-74].daylb;
		daylend = daytab[ct->tm_year-74].dayle;
	}
	daylbegin = sunday(ct, daylbegin);
	daylend = sunday(ct, daylend);
	if (systime.dstflag &&
	    (dayno>daylbegin || (dayno==daylbegin && ct->tm_hour>=2)) &&
	    (dayno<daylend || (dayno==daylend && ct->tm_hour<1))) {
		copyt += 1*60*60;
		ct = gmtime(&copyt);
		ct->tm_isdst++;
	}
	return(ct);
}

/*
 * The argument is a 0-origin day number.
 * The value is the day number of the first
 * Sunday on or after the day.
 */
static
sunday(t, d)
register struct tm *t;
register int d;
{
	if (d >= 58)
		d += dysize(t->tm_year) - 365;
	return(d - (d - t->tm_yday + t->tm_wday + 700) % 7);
}

struct tm *
gmtime(tim)
long *tim;
{
	/*register*/ int d0, d1;
	long hms, day;
	register int *tp;
	static struct tm xtime;

	/*
	 * break initial number into days
	 */
	hms = *tim % 86400;
	day = *tim / 86400;
	if (hms<0) {
		hms += 86400;
		day -= 1;
	}
	tp = (int *)&xtime;

	/*
	 * generate hours:minutes:seconds
	 */
	*tp++ = hms%60;
	d1 = hms/60;
	*tp++ = d1%60;
	d1 = d1/60;
	*tp++ = d1;

	/*
	 * day is the day number.
	 * generate day of the week.
	 * The addend is 4 mod 7 (1/1/1970 was Thursday)
	 */

	xtime.tm_wday = (day+7340036)%7;

	/*
	 * year number
	 */
	if (day>=0) for(d1=70; day >= dysize(d1); d1++)
		day -= dysize(d1);
	else for (d1=70; day<0; d1--)
		day += dysize(d1-1);
	xtime.tm_year = d1;
	xtime.tm_yday = d0 = day;

	/*
	 * generate month
	 */

	if (dysize(d1)==366)
		dmsize[1] = 29;
	for(d1=0; d0 >= dmsize[d1]; d1++)
		d0 -= dmsize[d1];
	dmsize[1] = 28;
	*tp++ = d0+1;
	*tp++ = d1;
	xtime.tm_isdst = 0;
	return(&xtime);
}

char *
asctime(t)
struct tm *t;
{
	register char *cp, *ncp;
	register int *tp;

	cp = cbuf;
	for (ncp = "Day Mon 00 00:00:00 1900\n"; *cp++ = *ncp++;);
	ncp = &"SunMonTueWedThuFriSat"[3*t->tm_wday];
	cp = cbuf;
	*cp++ = *ncp++;
	*cp++ = *ncp++;
	*cp++ = *ncp++;
	cp++;
	tp = &t->tm_mon;
	ncp = &"JanFebMarAprMayJunJulAugSepOctNovDec"[(*tp)*3];
	*cp++ = *ncp++;
	*cp++ = *ncp++;
	*cp++ = *ncp++;
	cp = ct_numb(cp, *--tp);
	cp = ct_numb(cp, *--tp+100);
	cp = ct_numb(cp, *--tp+100);
	cp = ct_numb(cp, *--tp+100);
	if (t->tm_year>=100) {
		cp[1] = '2';
		cp[2] = '0';
	}
	cp += 2;
	cp = ct_numb(cp, t->tm_year+100);
	return(cbuf);
}

dysize(y)
{
	if((y%4) == 0)
		return(366);
	return(365);
}

static char *
ct_numb(cp, n)
register char *cp;
{
	cp++;
	if (n>=10)
		*cp++ = (n/10)%10 + '0';
	else
		*cp++ = ' ';
	*cp++ = n%10 + '0';
	return(cp);
}
"[(*tp)*3];
	*cp++ = *ncp++;
	*cp++ = *ncp++;
	*cp++ = *ncp++;
	cp = ct_numb(cp, *--tlib86/gen/ctype_.c                                                                                     444     140      12         1073  3347642167   7234                                                                                                                                                                                                                                                                                                                                                                      #include	<ctype.h>

char _ctype_[] {
	0,
	_C,	_C,	_C,	_C,	_C,	_C,	_C,	_C,
	_C,	_S,	_S,	_S,	_S,	_S,	_C,	_C,
	_C,	_C,	_C,	_C,	_C,	_C,	_C,	_C,
	_C,	_C,	_C,	_C,	_C,	_C,	_C,	_C,
	_S,	_P,	_P,	_P,	_P,	_P,	_P,	_P,
	_P,	_P,	_P,	_P,	_P,	_P,	_P,	_P,
	_N,	_N,	_N,	_N,	_N,	_N,	_N,	_N,
	_N,	_N,	_P,	_P,	_P,	_P,	_P,	_P,
	_P,	_U,	_U,	_U,	_U,	_U,	_U,	_U,
	_U,	_U,	_U,	_U,	_U,	_U,	_U,	_U,
	_U,	_U,	_U,	_U,	_U,	_U,	_U,	_U,
	_U,	_U,	_U,	_P,	_P,	_P,	_P,	_P,
	_P,	_L,	_L,	_L,	_L,	_L,	_L,	_L,
	_L,	_L,	_L,	_L,	_L,	_L,	_L,	_L,
	_L,	_L,	_L,	_L,	_L,	_L,	_L,	_L,
	_L,	_L,	_L,	_P,	_P,	_P,	_P,	_C
};
C,	_C,	_C,	_C,
	_C,	_S,	_S,	_S,	_S,	_S,	_C,	_C,
	_C,	_C,	_C,	_C,	_C,	_C,	_C,	_C,
	_C,	_C,	_C,	_C,	_C,	_C,	_C,	_C,
	_S,	_P,	_P,	_P,	_P,	_P,	_P,	_P,
	_P,	_P,	_P,	_P,	_P,	_P,	_P,	_P,
	_N,	_N,	_N,	_N,	_N,	_N,	_N,	_N,
	_N,	_N,	_P,	_P,	_P,	_P,	_P,	_P,
	_P,	_U,	_U,	_U,	_U,	_U,	_U,	_U,
	_U,	_U,	_U,	_U,	_U,	_U,	_U,	_U,
	_U,	_U,	_U,	_U,	_U,	_U,	_U,	_U,
	_U,	_U,	_U,	_P,	_P,	_P,	_P,	_P,
	_P,	_L,	_L,	_L,	_L,	_L,	_L,	_L,
	_L,	_L,	_L,	_L,	_L,	_L,	_L,	_L,
	_L,	_L,	lib86/gen/cuexit.c                                                                                     664     140      12           36  3347642370   7210                                                                                                                                                                                                                                                                                                                                                                      exit(code)
 {	_exit(code);
 }
L,	_L,	_P,	_P,	_P,	_P,	_C
};
C,	_C,	_C,	_C,
	_C,	_S,	_S,	_S,	_S,	_S,	_C,	_C,
	_C,	_C,	_C,	_C,	_C,	_C,	_C,	_C,
	_C,	_C,	_C,	_C,	_C,	_C,	_C,	_C,
	_S,	_P,	_P,	_P,	_P,	_P,	_P,	_P,
	_P,	_P,	_P,	_P,	_P,	_P,	_P,	_P,
	_N,	_N,	_N,	_N,	_N,	_N,	_N,	_N,
	_N,	_N,	_P,	_P,	_P,	_P,	_P,	_P,
	_P,	_U,	_U,	_U,	_U,	_U,	_U,	_U,
	_U,	_U,	_U,	_U,	_U,	_U,	_U,	_U,
	_U,	_U,	_U,	_U,	_U,	_U,	_U,	_U,
	_U,	_U,	_U,	_P,	_P,	_P,	_P,	_P,
	_P,	_L,	_L,	_L,	_L,	_L,	_L,	_L,/usr/src/local/Machines/8086/lib86/gen     lib86/gen/ecvt.c                                                                                       444     140      12         3143  3347642170   6704                                                                                                                                                                                                                                                                                                                                                                      /*
 *	ecvt converts to decimal
 *	the number of digits is specified by ndigit
 *	decpt is set to the position of the decimal point
 *	sign is set to 0 for positive, 1 for negative
 */

char	*cvt();

#define	NDIG	80
char*
ecvt(arg, ndigits, decpt, sign)
double arg;
int ndigits, *decpt, *sign;
{
	return(cvt(arg, ndigits, decpt, sign, 1));
}

char*
fcvt(arg, ndigits, decpt, sign)
double arg;
int ndigits, *decpt, *sign;
{
	return(cvt(arg, ndigits, decpt, sign, 0));
}

static char*
cvt(arg, ndigits, decpt, sign, eflag)
double arg;
int ndigits, *decpt, *sign;
{
	register int r2;
	double fi, fj;
	register char *p, *p1;
	static char buf[NDIG];
	double modf();

	if (ndigits<0)
		ndigits = 0;
	if (ndigits>=NDIG-1)
		ndigits = NDIG-2;
	r2 = 0;
	*sign = 0;
	p = &buf[0];
	if (arg<0) {
		*sign = 1;
		arg = -arg;
	}
	arg = modf(arg, &fi);
	p1 = &buf[NDIG];
	/*
	 * Do integer part
	 */
	if (fi != 0) {
		p1 = &buf[NDIG];
		while (fi != 0) {
			fj = modf(fi/10, &fi);
			*--p1 = (int)((fj+.03)*10) + '0';
			r2++;
		}
		while (p1 < &buf[NDIG])
			*p++ = *p1++;
	} else if (arg > 0) {
		while ((fj = arg*10) < 1) {
			arg = fj;
			r2--;
		}
	}
	p1 = &buf[ndigits];
	if (eflag==0)
		p1 += r2;
	*decpt = r2;
	if (p1 < &buf[0]) {
		buf[0] = '\0';
		return(buf);
	}
	while (p<=p1 && p<&buf[NDIG]) {
		arg *= 10;
		arg = modf(arg, &fj);
		*p++ = (int)fj + '0';
	}
	if (p1 >= &buf[NDIG]) {
		buf[NDIG-1] = '\0';
		return(buf);
	}
	p = p1;
	*p1 += 5;
	while (*p1 > '9') {
		*p1 = '0';
		if (p1>buf)
			++*--p1;
		else {
			*p1 = '1';
			(*decpt)++;
			if (eflag==0) {
				if (p>buf)
					*p = '0';
				p++;
			}
		}
	}
	*p = '\0';
	return(buf);
}
			r2--;
		}
	}
	p1 = &buf[ndigits];
	if (eflag==0)
		p1 += r2;
	*decpt = r2;
	if (p1 < &buf[0]) {
		buf[0] = '\0';
		return(buf);
	}
	while (p<=p1 && p<&buf[NDIG]) {
		arg *= 10;
		arg = modf(arg, &fj);
		*p++ = (int)fj + '0';
	}
	if (p1 >= &buf[NDIG]) {
		buf[NDIG-1] = '\0';
		return(buf);
	}
	p = p1;
	*p1 += 5;
	while (*p1 > '9') {
		*p1 = '0';
		if (p1>buf)
			++*--p1;
		else {
			*p1 = '1';
			(*decpt)++;lib86/gen/errlst.c                                                                                     444     140      12         1456  3347642170   7263                                                                                                                                                                                                                                                                                                                                                                      char	*sys_errlist[] {
	"Error 0",
	"Not owner",
	"No such file or directory",
	"No such process",
	"Interrupted system call",
	"I/O error",
	"No such device or address",
	"Arg list too long",
	"Exec format error",
	"Bad file number",
	"No children",
	"No more processes",
	"Not enough core",
	"Permission denied",
	"Bad address",
	"Block device required",
	"Mount device busy",
	"File exists",
	"Cross-device link",
	"No such device",
	"Not a directory",
	"Is a directory",
	"Invalid argument",
	"File table overflow",
	"Too many open files",
	"Not a typewriter",
	"Text file busy",
	"File too large",
	"No space left on device",
	"Illegal seek",
	"Read-only file system",
	"Too many links",
	"Broken pipe",
	"Argument too large",
	"Result too large",
};
int	sys_nerr { sizeof sys_errlist/sizeof sys_errlist[0] };
on denied",
	"Bad address",
	"Block device required",
	"Mount device busy",
	"File exists",
	"Cross-device link",
	"No such device",
	"Not a directory",
	"Is a directory",
	"Invalid argument",
	"File table overlib86/gen/execvp.c                                                                                     444     140      12         2570  3347642171   7241                                                                                                                                                                                                                                                                                                                                                                      /*
 *	execlp(name, arg,...,0)	(like execl, but does path search)
 *	execvp(name, argv)	(like execv, but does path search)
 */
#include <errno.h>
#define	NULL	0

static	char shell[] =	"/bin/sh";
char	*execat(), *getenv();
extern	errno;

execlp(name, argv)
char *name, *argv;
{
	return(execvp(name, &argv));
}

execvp(name, argv)
char *name, **argv;
{
	char *pathstr;
	register char *cp;
	char fname[128];
	char *newargs[256],*ctemp;
	int i;
	register unsigned etxtbsy = 1;
	register eacces = 0;

	if ((pathstr = getenv("PATH")) == NULL)
		pathstr = ":/bin:/usr/bin";
	cp = index(name, '/')? "": pathstr;

	do {
		cp = execat(cp, name, fname);
	retry:
		execv(fname, argv);
		switch(errno) {
		case ENOEXEC:
			newargs[0] = "sh";
			newargs[1] = fname;
			for (i=1; ctemp = argv[i], newargs[i+1]=ctemp; i++) {
				if (i>=254) {
					errno = E2BIG;
					return(-1);
				}
			}
			execv(shell, newargs);
			return(-1);
		case ETXTBSY:
			if (++etxtbsy > 5)
				return(-1);
			sleep(etxtbsy);
			goto retry;
		case EACCES:
			eacces++;
			break;
		case ENOMEM:
		case E2BIG:
			return(-1);
		}
	} while (cp);
	if (eacces)
		errno = EACCES;
	return(-1);
}

static char *
execat(s1, s2, si)
register char *s1, *s2;
char *si;
{
	register char *s;

	s = si;
	while (*s1 && *s1 != ':' && *s1 != '-')
		*s++ = *s1++;
	if (si != s)
		*s++ = '/';
	while (*s2)
		*s++ = *s2++;
	*s = '\0';
	return(*s1? ++s1: 0);
}
, newargs);
			return(-1);
		case ETXTBSY:
			if (++etxtbsy > 5)
				return(-1);
			sleep(etxtbsy);
			goto retry;
		case EACCES:
			eaclib86/gen/frexp.c                                                                                      444     140      12          726  3347642171   7054                                                                                                                                                                                                                                                                                                                                                                      /* @(#)frexp.c	4.1 (Berkeley) 12/21/80 */
/*
	the call
		x = frexp(arg,&exp);
	must return a double fp quantity x which is <1.0
	and the corresponding binary exponent "exp".
	such that
		arg = x*2^exp
*/

double
frexp(x,i)
double x;
int *i;
{
	int neg;
	int j;
	j = 0;
	neg = 0;
	if(x<0){
		x = -x;
		neg = 1;
		}
	if(x>1.0)
		while(x>1){
			j = j+1;
			x = x/2;
			}
	else if(x<0.5)
		while(x<0.5){
			j = j-1;
			x = 2*x;
			}
	*i = j;
	if(neg) x = -x;
	return(x);
	}
usr/src/local/Machines/8086/lib86/gen     lib86/gen/getlogin.c                                                                                   444     140      12          710  3347642171   7531                                                                                                                                                                                                                                                                                                                                                                      #include <utmp.h>

static	char	UTMP[]	= "/etc/utmp";
static	struct	utmp ubuf;

char *
getlogin()
{
	register me, uf;
	register char *cp;

	if( !(me = ttyslot()) )
		return(0);
	if( (uf = open( UTMP, 0 )) < 0 )
		return(0);
	lseek( uf, (long)(me*sizeof(ubuf)), 0 );
	if (read(uf, (char *)&ubuf, sizeof(ubuf)) != sizeof(ubuf))
		return(0);
	close(uf);
	ubuf.ut_name[8] = ' ';
	for (cp=ubuf.ut_name; *cp++!=' ';)
		;
	*--cp = '\0';
	return( ubuf.ut_name );
}
return(x);
	}/usr/src/local/Machines/8086/lib86/gen     lib86/gen/index.c                                                                                      444     140      12          333  3347642172   7032                                                                                                                                                                                                                                                                                                                                                                      /*
 * Return the ptr in sp at which the character c appears;
 * NULL if not found
 */

#define	NULL	0

char *
index(sp, c)
register char *sp, c;
{
	do {
		if (*sp == c)
			return(sp);
	} while (*sp++);
	return(NULL);
}
0);
	lseek( uf, (long)(me*sizeof(ubuf)), 0 );
	if (read(uf, (char *)&ubuf, sizeof(ubuf)) != sizeof(ubuf))
		return(0);
	close(uf);
	ubuf.ut_name[8] = ' ';
	for (cp=ubuf.ut_name; *cp++!=' ';)
		;
	*--cp = '\0';
	return( ubuf.ut_name );
}
return(x);
	}/usr/src/local/Machines/8086/lib86/gen     lib86/gen/l3.c                                                                                         444     140      12         1127  3347642172   6263                                                                                                                                                                                                                                                                                                                                                                      /*
 * Convert longs to and from 3-byte disk addresses
 */
ltol3(cp, lp, n)
char	*cp;
long	*lp;
int	n;
{
	register i;
	register char *a, *b;

	a = cp;
	b = (char *)lp;
	for(i=0;i<n;i++) {
#ifndef pdp11
		b++;
		*a++ = *b++;
		*a++ = *b++;
		*a++ = *b++;
#else
		*a++ = *b++;
		b++;
		*a++ = *b++;
		*a++ = *b++;
#endif
	}
}

l3tol(lp, cp, n)
long	*lp;
char	*cp;
int	n;
{
	register i;
	register char *a, *b;

	a = (char *)lp;
	b = cp;
	for(i=0;i<n;i++) {
#ifndef pdp11
		*a++ = 0;
		*a++ = *b++;
		*a++ = *b++;
		*a++ = *b++;
#else
		*a++ = *b++;
		*a++ = 0;
		*a++ = *b++;
		*a++ = *b++;
#endif
	}
}
ng	*lp;
int	n;
{
	register i;
	register char *a, *b;

	a = cp;
	b = (char *)lp;
	for(i=0;i<n;i++) {
#ifndef pdp11
		b++;
		*a++ = *b++;
		*a++ = *b++;
		*a++ = *b++;
#else
		*a++ = *b++;
		b++;
		*a++ = *b++;
		*a++ = *b++;
#endif
	}
}

l3tol(lp, cp, n)
long	*lp;
char	*cp;
int	n;
{
	register i;
	register char *a, *b;

	a = (char *)lp;
	b = cp;
	for(i=0;i<n;i++) {
#ifndef pdp11
		*a++ = 0;
		*a++ = *b++;
		*a++ = *b++;
		*lib86/gen/malloc.c                                                                                     444     140      12        10222  3347642172   7230                                                                                                                                                                                                                                                                                                                                                                      #ifdef debug
#define ASSERT(p) if(!(p))botch("p");else
botch(s)
char *s;
{
	printf("assertion botched: %s\n",s);
	abort();
}
#else
#define ASSERT(p)
#endif

/*	avoid break bug */
#ifdef pdp11
#define GRANULE 64
#else
#define GRANULE 0
#endif
/*	C storage allocator
 *	circular first-fit strategy
 *	works with noncontiguous, but monotonically linked, arena
 *	each block is preceded by a ptr to the (pointer of) 
 *	the next following block
 *	blocks are exact number of words long 
 *	aligned to the data type requirements of ALIGN
 *	pointers to blocks must have BUSY bit 0
 *	bit in ptr is 1 for busy, 0 for idle
 *	gaps in arena are merely noted as busy blocks
 *	last block of arena (pointed to by alloct) is empty and
 *	has a pointer to first
 *	idle blocks are coalesced during space search
 *
 *	a different implementation may need to redefine
 *	ALIGN, NALIGN, BLOCK, BUSY, INT
 *	where INT is integer type to which a pointer can be cast
*/
#define INT int
#define ALIGN int
#define NALIGN 1
#define WORD sizeof(union store)
#define BLOCK 1024	/* a multiple of WORD*/
#define BUSY 1
#define NULL 0
#define testbusy(p) ((INT)(p)&BUSY)
#define setbusy(p) (union store *)((INT)(p)|BUSY)
#define clearbusy(p) (union store *)((INT)(p)&~BUSY)

union store { union store *ptr;
	      ALIGN dummy[NALIGN];
	      int calloc;	/*calloc clears an array of integers*/
};

int allocs[2] = { 0, 0 };
union store *allocp;	/*search ptr*/
union store *alloct;	/*arena top*/
union store *allocx;	/*for benefit of realloc*/
char	*sbrk();

char *
malloc(nbytes)
unsigned nbytes;
{
	register union store *p, *q;
	register nw;
	static temp;	/*coroutines assume no auto*/

	if(allocs[0]==0) {	/*first time*/
		allocs[0] = (int)setbusy(&allocs[1]);
		allocs[1] = (int)setbusy(&allocs[0]);
		alloct = (union store *)&allocs[1];
		allocp = (union store *)&allocs[0];
	}
	nw = (nbytes+WORD+WORD-1)/WORD;
	ASSERT(allocp>=(union store *)allocs && allocp<=alloct);
	ASSERT(allock());
	for(p=allocp; ; ) {
		for(temp=0; ; ) {
			if(!testbusy(p->ptr)) {
				while(!testbusy((q=p->ptr)->ptr)) {
					ASSERT(q>p&&q<alloct);
					p->ptr = q->ptr;
				}
				if(q>=p+nw && p+nw>=p)
					goto found;
			}
			q = p;
			p = clearbusy(p->ptr);
			if(p>q)
				ASSERT(p<=alloct);
			else if(q!=alloct || p!=(union store *)allocs) {
				ASSERT(q==alloct&&p==(union store *)allocs);
				return(NULL);
			} else if(++temp>1)
				break;
		}
		temp = ((nw+BLOCK/WORD)/(BLOCK/WORD))*(BLOCK/WORD);
		q = (union store *)sbrk(0);
		if(q+temp+GRANULE < q) {
			return(NULL);
		}
		q = (union store *)sbrk(temp*WORD);
		if((INT)q == -1) {
			return(NULL);
		}
		ASSERT(q>alloct);
		alloct->ptr = q;
		if(q!=alloct+1)
			alloct->ptr = setbusy(alloct->ptr);
		alloct = q->ptr = q+temp-1;
		alloct->ptr = setbusy((union store *)allocs);
	}
found:
	allocp = p + nw;
	ASSERT(allocp<=alloct);
	if(q>allocp) {
		allocx = allocp->ptr;
		allocp->ptr = p->ptr;
	}
	p->ptr = setbusy(allocp);
	return((char *)(p+1));
}

/*	freeing strategy tuned for LIFO allocation
*/
free(ap)
register char *ap;
{
	register union store *p = (union store *)ap;

	ASSERT(p>clearbusy(((union store *)allocs)[1].ptr)&&p<=alloct);
	ASSERT(allock());
	allocp = --p;
	ASSERT(testbusy(p->ptr));
	p->ptr = clearbusy(p->ptr);
	ASSERT(p->ptr > allocp && p->ptr <= alloct);
}

/*	realloc(p, nbytes) reallocates a block obtained from malloc()
 *	and freed since last call of malloc()
 *	to have new size nbytes, and old content
 *	returns new location, or 0 on failure
*/

char *
realloc(p, nbytes)
register union store *p;
unsigned nbytes;
{
	register union store *q;
	int *s, *t;
	register unsigned nw;
	unsigned onw;

	if(testbusy(p[-1].ptr))
		free((char *)p);
	onw = p[-1].ptr - p;
	q = (union store *)malloc(nbytes);
	if(q==NULL || q==p)
		return((char *)q);
	s = (int *)p;
	t = (int *)q;
	nw = (nbytes+WORD-1)/WORD;
	if(nw<onw)
		onw = nw;
	while(onw--!=0)
		*t++ = *s++;
	if(q<p && q+nw>=p)
		(q+(q+nw-p))->ptr = allocx;
	return((char *)q);
}

#ifdef debug
allock()
{
#ifdef longdebug
	register union store *p;
	int x;
	x = 0;
	for(p= &((union store *)allocs)[0];
		clearbusy(p->ptr) > p; p=clearbusy(p->ptr)) {
		if(p==allocp)
			x++;
	}
	ASSERT(p==alloct);
	return(x==1|p==allocp);
#else
	return(1);
#endif
}
#endif
nbytes);
	if(q==NULL || q==p)
		return((char *)q);
	s = (int *)p;
	t = (int *)q;
	nw = (nbytes+WORD-1)/WORD;
	if(nw<onw)
		onw = nw;
	while(onw--!=0)
		*t++ = *s++;
	if(q<p && q+nw>=p)
		(q+(q+nw-p))->ptr = allocx;
	return((char *)q);
}

#ifdef debug
allock()
{
#ifdef longdebug
	register union store *p;
	int x;
	x = 0;
	for(p= &((union store *)allocs)[0];
		clearblib86/gen/mktemp.c                                                                                     444     140      12          465  3347642173   7227                                                                                                                                                                                                                                                                                                                                                                      char *
mktemp(as)
char *as;
{
	register char *s;
	register unsigned pid;
	register i;

	pid = getpid();
	s = as;
	while (*s++)
		;
	s--;
	while (*--s == 'X') {
		*s = (pid%10) + '0';
		pid = pid/10;
	}
	s++;
	i = 'a';
	while (access(as, 0) != -1) {
		if (i=='z')
			return("/");
		*s = i++;
	}
	return(as);
}
;
	if(q<p && q+nw>=p)
		(q+(q+nw-p))->ptr = allocx;
	return((char *)q);
}

#ifdef debug
allock()
{
#ifdef longdebug
	register union store *p;
	int x;
	x = 0;
	f/usr/src/local/Machines/8086/lib86/gen     lib86/gen/mon.c                                                                                        444     140      12         2021  3347642173   6531                                                                                                                                                                                                                                                                                                                                                                      /* mcount uses an array like struct mcount mc[cntsiz] */
struct mcount
{
	long mc_addr;
	long mc_count;
};

/* file mon.out will have a header like: */
struct monhdr
{
	int (*lowpc)();
	int (*highpc)();
	long cntsiz;
};

monitor(lowpc, highpc, buf, bufsiz, cntsiz)
int (*lowpc)(), (*highpc)();
short *buf;
int bufsiz;	/* number of shorts in buf */
{
	int file;
	unsigned scale;
	int pbufsiz, pbufoffs;
	struct monhdr *mhp;
	static short *sbuf;
	static int ssiz;

	if (lowpc == 0) {
		profil(0, 0, 0, 0);
		file = creat("mon.out", 0666);
		write(file, sbuf, ssiz * sizeof(short));
		close(file);
		return;
	}

	ssiz = bufsiz;
	sbuf = buf;

	mhp = (struct monhdr *)buf;
	mhp->lowpc = lowpc;
	mhp->highpc = highpc;
	mhp->cntsiz = cntsiz;

	pbufoffs = sizeof(struct monhdr) + cntsiz * sizeof(struct mcount);
	pbufsiz = bufsiz * sizeof(short) - pbufoffs;
	if (pbufsiz <= 0) return;

	scale = pbufsiz << 16;
	scale /= (unsigned)((int)highpc - (int)lowpc);
	scale = scale - 1;

	profil(&((char *)buf)[pbufoffs], pbufsiz, (int)lowpc, (int)scale);
}
 0666);
		write(file, sbuf, ssiz * sizeof(short));
		close(file);
		return;
	}

	ssiz = bufsiz;
	sbuf = buf;

	mhp = (struct monhdr *)buf;
	mhp->lowpc = lowpc;
	mhp->highpc = highpc;
	mhp->cntsiz = cntsiz;

	pbufoffs = sizeof(struct monhdr) + cntsiz * sizeof(struct mcount);
	pbufsiz = bufsiz * sizeof(short) - pbufoffs;
	if (pbufsiz <= 0) return;

	scale = pbufsiz << 16;
	scale /= (unsigned)((int)highpc - (int)lowpc);
	scale = scale - 1;

	profil(&((char *)buf)[pbufoffs], pbufsiz, (int)lowpclib86/gen/nlist.c                                                                                      444     140      12         2211  3347642173   7072                                                                                                                                                                                                                                                                                                                                                                      #include <stdio.h>
#include <b.out.h>

long b_magic[] = {FMAGIC, NMAGIC, 0};

nlist(name, list)
char *name;
struct nlist *list;
{
	FILE *f;
	register struct nlist *p;
	register char *cp;
	int i, c;
	long pos;
	struct bhdr filhdr;
	char symbuf[SYMLENGTH];
	struct sym sym;

	for(p = list; p->n_name[0]; p++) {
		p->n_type = 0;
		p->n_value = 0;
	}
	f = fopen(name, "r");
	if(f == NULL) return(-1);
	fread((char *)&filhdr, sizeof filhdr, 1, f);
	if (feof(f)) goto bad;
	for(i=0; b_magic[i]; i++) if(b_magic[i] == filhdr.fmagic) break;
	if(b_magic[i] == 0) goto bad;
	fseek(f, (long)(SYMPOS), 0);
	for (pos = 0; pos < filhdr.ssize; pos += sizeof(sym)+strlen(symbuf)+1)
	{
		fread(&sym, sizeof sym, 1, f);
		if (feof(f)) goto bad;
		for (cp = symbuf; cp < &symbuf[SYMLENGTH - 1]; cp++)
		{
			if ((c = getc(f)) == EOF) goto bad;
			if (c == 0) break;
			*cp = c;
		}
		*cp = 0;
		for(p = list; p->n_name[0]; p++)
		{
			for(i=0;i<8;i++)
			{
				if (p->n_name[i] != symbuf[i]) goto cont;
				if (p->n_name[i] == 0) break;
			}
			p->n_value = sym.svalue;
			p->n_type = sym.stype;
			break;
		cont:		;
		}
	}
	fclose(f);
	return(0);

bad:	fclose(f);
	return(-1);
}
trlen(symbuf)+1)
	{
		fread(&sym, sizeof sym, 1, f);
		if (feof(f)) goto bad;
		for (cp = symbuf; cp < &symbuf[SYMLENGTH - 1]; cp++)
		{
			if ((c = getc(f)) == EOF) goto bad;
			if (c == 0) break;
			*cp = c;
		}
		*cp = 0;
		for(p = list; p->n_name[0]; p++)
		{
			for(i=0;i<8;i++)
			{
				if (p->n_name[i] != symbuf[i]) goto cont;
				if (p->n_name[i] == 0) break;
			}
	lib86/gen/perror.c                                                                                     444     140      12          530  3347642174   7235                                                                                                                                                                                                                                                                                                                                                                      /*
 * Print the error indicated
 * in the cerror cell.
 */

int	errno;
int	sys_nerr;
char	*sys_errlist[];
perror(s)
char *s;
{
	register char *c;
	register n;

	c = "Unknown error";
	if(errno < sys_nerr)
		c = sys_errlist[errno];
	n = strlen(s);
	if(n) {
		write(2, s, n);
		write(2, ": ", 2);
	}
	write(2, c, strlen(c));
	write(2, "\n", 1);
}
c;
		}
		*cp = 0;
		for(p = list; p->n_name[0]; p++)
		{
			for(i=0;i<8;i++)
			{
				if (p->n_name[i] != symbuf[i]) goto con/usr/src/local/Machines/8086/lib86/gen     lib86/gen/qsort.c                                                                                      444     140      12         2552  3347642175   7123                                                                                                                                                                                                                                                                                                                                                                      
static int	(*qscmp)();
static int	qses;

qsort(a, n, es, fc)
char *a;
unsigned n;
int es;
int (*fc)();
{
	qscmp = fc;
	qses = es;
	qs1(a, a+n*es);
}

static qs1(a, l)
char *a, *l;
{
	register char *i, *j;
	register es;
	char **k;
	char *lp, *hp;
	int c;
	unsigned n;


	es = qses;

start:
	if((n=l-a) <= es)
		return;
	n = es * (n / (2*es));
	hp = lp = a+n;
	i = a;
	j = l-es;
	for(;;) {
		if(i < lp) {
			if((c = (*qscmp)(i, lp)) == 0) {
				qsexc(i, lp -= es);
				continue;
			}
			if(c < 0) {
				i += es;
				continue;
			}
		}

loop:
		if(j > hp) {
			if((c = (*qscmp)(hp, j)) == 0) {
				qsexc(hp += es, j);
				goto loop;
			}
			if(c > 0) {
				if(i == lp) {
					qstexc(i, hp += es, j);
					i = lp += es;
					goto loop;
				}
				qsexc(i, j);
				j -= es;
				i += es;
				continue;
			}
			j -= es;
			goto loop;
		}


		if(i == lp) {
			if(lp-a >= l-hp) {
				qs1(hp+es, l);
				l = lp;
			} else {
				qs1(a, lp);
				a = hp+es;
			}
			goto start;
		}


		qstexc(j, lp -= es, i);
		j = hp -= es;
	}
}

static qsexc(i, j)
char *i, *j;
{
	register char *ri, *rj, c;
	int n;

	n = qses;
	ri = i;
	rj = j;
	do {
		c = *ri;
		*ri++ = *rj;
		*rj++ = c;
	} while(--n);
}

static qstexc(i, j, k)
char *i, *j, *k;
{
	register char *ri, *rj, *rk;
	int c;
	int n;

	n = qses;
	ri = i;
	rj = j;
	rk = k;
	do {
		c = *ri;
		*ri++ = *rk;
		*rk++ = *rj;
		*rj++ = c;
	} while(--n);
}
	qs1(hp+es, l);
				l = lp;
			} else {
				qs1(a, lp);
				a = hp+es;
			}
			goto start;
		}


		qstexc(j, lp -= es, i);
		j = hp -= es;
	}
}

statilib86/gen/rand.c                                                                                       444     140      12          205  3347642175   6650                                                                                                                                                                                                                                                                                                                                                                      static	long	randx = 1;

srand(x)
unsigned x;
{
	randx = x;
}

rand()
{
	return(((randx = randx*1103515245 + 12345)>>16) & 077777);
}
+ = c;
	} while(--n);
}

static qstexc(i, j, k)
char *i, *j, *k;
{
	register char *ri, *rj, *rk;
	int c;
	int n;

	n = qses;
	ri = i;
	rj = j;
	rk = k;
	do {
		c = *ri;
		*ri++ = *rk;
		*rk++ = *rj;
		*rj++ = c;
	} while(--n);
}
	qs1(hp+es, l);
				l = lp;
			} else {
				qs1(a, lp);
				a = hp+es;
			}
			goto start;
		}


		qstexc(j/usr/src/local/Machines/8086/lib86/gen     lib86/gen/rindex.c                                                                                     444     140      12          370  3347642175   7220                                                                                                                                                                                                                                                                                                                                                                      /*
 * Return the ptr in sp at which the character c last
 * appears; NULL if not found
*/

#define NULL 0

char *
rindex(sp, c)
register char *sp, c;
{
	register char *r;

	r = NULL;
	do {
		if (*sp == c)
			r = sp;
	} while (*sp++);
	return(r);
}
n = qses;
	ri = i;
	rj = j;
	rk = k;
	do {
		c = *ri;
		*ri++ = *rk;
		*rk++ = *rj;
		*rj++ = c;
	} while(--n);
}
	qs1(hp+es, l);
				l = lp;
			} else {
				qs1(a, lp);
				a = hp+es;
			}
			goto start;
		}


		qstexc(j/usr/src/local/Machines/8086/lib86/gen     lib86/gen/sleep.c                                                                                      444     140      12          772  3347642176   7046                                                                                                                                                                                                                                                                                                                                                                      #include <signal.h>
#include <setjmp.h>

static jmp_buf jmp;

sleep(n)
unsigned n;
{
	int sleepx();
	unsigned altime;
	int (*alsig)() = SIG_DFL;

	if (n==0)
		return;
	altime = alarm(1000);	/* time to maneuver */
	if (setjmp(jmp)) {
		signal(SIGALRM, alsig);
		alarm(altime);
		return;
	}
	if (altime) {
		if (altime > n)
			altime -= n;
		else {
			n = altime;
			altime = 1;
		}
	}
	alsig = signal(SIGALRM, sleepx);
	alarm(n);
	for(;;)
		pause();
	/*NOTREACHED*/
}

static
sleepx()
{
	longjmp(jmp, 1);
}
n     lib86/gen/stat.c                                                                                       664      30      12         1060  3355667030   6675                                                                                                                                                                                                                                                                                                                                                                      #include <stat.h>

extern unsigned _dosax, _dosbx, _doscx, _dosdx;
long flength();

fstat(fid, ss)
 register struct stat *ss;
 {	register i;
	char *p;
	p = (char *) ss;
	for (i = sizeof *ss; i--; ) *p++ = 0;

	if (_ioctl(0, fid) < 0) return -1;
	i = _dosdx;
	ss -> st_dev = i & 0x8F;	/* Pseudo-device number.	*/

	if (i & 0x80)			/* A disk file...		*/
	 { ss->st_size = flength(fid);
	 }	
	return 0;
 }

stat(name, ss)
 char *name;
 struct stat *ss;
 {	int fid = open(name, 0), res;
	if (fid < 0) return -1;
	res = fstat(fid, ss);
	close(fid);
	return res;
 }
x, _doscx, _dosdx;
long flength();

fstat(fid, ss)
 register struct stat *ss;
 {	register i;
	char *p;
	p = (char *) ss;
	for (i = sizeof *ss; i--; ) *p++ = 0;

	if (_ioctl(0, fid) < 0) return -1;
	i = _dosdx;
	ss -> st_dev = i & 0x8F;	/* Pseudo-device number.	*/

	if (i & 0x80)			/* A disk file...		*/
	 { ss->st_size = flength(fid);
	 }	
	return 0;
 }

stat(name, ss)
 char *name;
 struct stat *ss;
 {	int fid = open(name, 0), res;
	if (fid < 0) return -1;
	reslib86/gen/strcat.c                                                                                     444     140      12          362  3347642176   7231                                                                                                                                                                                                                                                                                                                                                                      /*
 * Concatenate s2 on the end of s1.  S1's space must be large enough.
 * Return s1.
 */

char *
strcat(s1, s2)
register char *s1, *s2;
{
	register char *os1;

	os1 = s1;
	while (*s1++)
		;
	--s1;
	while (*s1++ = *s2++)
		;
	return(os1);
}
1;
	i = _dosdx;
	ss -> st_dev = i & 0x8F;	/* Pseudo-device number.	*/

	if (i & 0x80)			/* A disk file...		*/
	 { ss->st_size = flength(fid);
	 }	
	return 0;
 }

stat(name, ss)
 char *name;
 struct stat *ss;
 {	int fid = open(n/usr/src/local/Machines/8086/lib86/gen     lib86/gen/strcatn.c                                                                                    444     140      12          521  3347642177   7405                                                                                                                                                                                                                                                                                                                                                                      /*
 * Concatenate s2 on the end of s1.  S1's space must be large enough.
 * At most n characters are moved.
 * Return s1.
 */

char *
strcatn(s1, s2, n)
register char *s1, *s2;
register n;
{
	register char *os1;

	os1 = s1;
	while (*s1++)
		;
	--s1;
	while (*s1++ = *s2++)
		if (--n < 0) {
			*--s1 = '\0';
			break;
		}
	return(os1);
}
sk file...		*/
	 { ss->st_size = flength(fid);
	 }	
	return 0;
 }

stat(name, ss)
 char *name;
 struct stat *ss;
 {	int fid = open(n/usr/src/local/Machines/8086/lib86/gen     lib86/gen/strcmp.c                                                                                     444     140      12          266  3347642177   7245                                                                                                                                                                                                                                                                                                                                                                      /*
 * Compare strings:  s1>s2: >0  s1==s2: 0  s1<s2: <0
 */

strcmp(s1, s2)
register char *s1, *s2;
{

	while (*s1 == *s2++)
		if (*s1++=='\0')
			return(0);
	return(*s1 - *--s2);
}
ter n;
{
	register char *os1;

	os1 = s1;
	while (*s1++)
		;
	--s1;
	while (*s1++ = *s2++)
		if (--n < 0) {
			*--s1 = '\0';
			break;
		}
	return(os1);
}
sk file...		*/
	 { ss->st_size = flength(fid);
	 }	
	return 0;
 }

stat(name, ss)
 char *name;
 struct stat *ss;
 {	int fid = open(n/usr/src/local/Machines/8086/lib86/gen     lib86/gen/strcmpn.c                                                                                    444     140      12          360  3347642177   7416                                                                                                                                                                                                                                                                                                                                                                      /*
 * Compare strings (at most n bytes):  s1>s2: >0  s1==s2: 0  s1<s2: <0
 */

strcmpn(s1, s2, n)
register char *s1, *s2;
register n;
{

	while (--n >= 0 && *s1 == *s2++)
		if (*s1++ == '\0')
			return(0);
	return(n<0 ? 0 : *s1 - *--s2);
}
	;
	--s1;
	while (*s1++ = *s2++)
		if (--n < 0) {
			*--s1 = '\0';
			break;
		}
	return(os1);
}
sk file...		*/
	 { ss->st_size = flength(fid);
	 }	
	return 0;
 }

stat(name, ss)
 char *name;
 struct stat *ss;
 {	int fid = open(n/usr/src/local/Machines/8086/lib86/gen     lib86/gen/strcpy.c                                                                                     444     140      12          304  3347642177   7252                                                                                                                                                                                                                                                                                                                                                                      /*
 * Copy string s2 to s1.  s1 must be large enough.
 * return s1
 */

char *
strcpy(s1, s2)
register char *s1, *s2;
{
	register char *os1;

	os1 = s1;
	while (*s1++ = *s2++)
		;
	return(os1);
}
eturn(0);
	return(n<0 ? 0 : *s1 - *--s2);
}
	;
	--s1;
	while (*s1++ = *s2++)
		if (--n < 0) {
			*--s1 = '\0';
			break;
		}
	return(os1);
}
sk file...		*/
	 { ss->st_size = flength(fid);
	 }	
	return 0;
 }

stat(name, ss)
 char *name;
 struct stat *ss;
 {	int fid = open(n/usr/src/local/Machines/8086/lib86/gen     lib86/gen/strcpyn.c                                                                                    444     140      12          476  3347642200   7425                                                                                                                                                                                                                                                                                                                                                                      /*
 * Copy s2 to s1, truncating or null-padding to always copy n bytes
 * return s1
 */

char *
strcpyn(s1, s2, n)
register char *s1, *s2;
{
	register i;
	register char *os1;

	os1 = s1;
	for (i = 0; i < n; i++)
		if ((*s1++ = *s2++) == '\0') {
			while (++i < n)
				*s1++ = '\0';
			return(os1);
		}
	return(os1);
}
	}
	return(os1);
}
sk file...		*/
	 { ss->st_size = flength(fid);
	 }	
	return 0;
 }

stat(name, ss)
 char *name;
 struct stat *ss;
 {	int fid = open(n/usr/src/local/Machines/8086/lib86/gen     lib86/gen/strlen.c                                                                                     444     140      12          236  3347642200   7224                                                                                                                                                                                                                                                                                                                                                                      /*
 * Returns the number of
 * non-NULL bytes in string argument.
 */

strlen(s)
register char *s;
{
	register n;

	n = 0;
	while (*s++)
		n++;
	return(n);
}
ister char *os1;

	os1 = s1;
	for (i = 0; i < n; i++)
		if ((*s1++ = *s2++) == '\0') {
			while (++i < n)
				*s1++ = '\0';
			return(os1);
		}
	return(os1);
}
	}
	return(os1);
}
sk file...		*/
	 { ss->st_size = flength(fid);
	 }	
	return 0;
 }

stat(name, ss)
 char *name;
 struct stat *ss;
 {	int fid = open(n/usr/src/local/Machines/8086/lib86/gen     lib86/gen/strncat.c                                                                                    444     140      12          521  3347642200   7370                                                                                                                                                                                                                                                                                                                                                                      /*
 * Concatenate s2 on the end of s1.  S1's space must be large enough.
 * At most n characters are moved.
 * Return s1.
 */

char *
strncat(s1, s2, n)
register char *s1, *s2;
register n;
{
	register char *os1;

	os1 = s1;
	while (*s1++)
		;
	--s1;
	while (*s1++ = *s2++)
		if (--n < 0) {
			*--s1 = '\0';
			break;
		}
	return(os1);
}
sk file...		*/
	 { ss->st_size = flength(fid);
	 }	
	return 0;
 }

stat(name, ss)
 char *name;
 struct stat *ss;
 {	int fid = open(n/usr/src/local/Machines/8086/lib86/gen     lib86/gen/strncmp.c                                                                                    444     140      12          360  3347642200   7401                                                                                                                                                                                                                                                                                                                                                                      /*
 * Compare strings (at most n bytes):  s1>s2: >0  s1==s2: 0  s1<s2: <0
 */

strncmp(s1, s2, n)
register char *s1, *s2;
register n;
{

	while (--n >= 0 && *s1 == *s2++)
		if (*s1++ == '\0')
			return(0);
	return(n<0 ? 0 : *s1 - *--s2);
}
	;
	--s1;
	while (*s1++ = *s2++)
		if (--n < 0) {
			*--s1 = '\0';
			break;
		}
	return(os1);
}
sk file...		*/
	 { ss->st_size = flength(fid);
	 }	
	return 0;
 }

stat(name, ss)
 char *name;
 struct stat *ss;
 {	int fid = open(n/usr/src/local/Machines/8086/lib86/gen     lib86/gen/strncpy.c                                                                                    444     140      12          476  3347642201   7426                                                                                                                                                                                                                                                                                                                                                                      /*
 * Copy s2 to s1, truncating or null-padding to always copy n bytes
 * return s1
 */

char *
strncpy(s1, s2, n)
register char *s1, *s2;
{
	register i;
	register char *os1;

	os1 = s1;
	for (i = 0; i < n; i++)
		if ((*s1++ = *s2++) == '\0') {
			while (++i < n)
				*s1++ = '\0';
			return(os1);
		}
	return(os1);
}
	}
	return(os1);
}
sk file...		*/
	 { ss->st_size = flength(fid);
	 }	
	return 0;
 }

stat(name, ss)
 char *name;
 struct stat *ss;
 {	int fid = open(n/usr/src/local/Machines/8086/lib86/gen     lib86/gen/stty.c                                                                                       444     140      12          330  3347642201   6714                                                                                                                                                                                                                                                                                                                                                                      /*
 * Writearound to old stty and gtty system calls
 */

#include <sgtty.h>

stty(fd, ap)
struct sgtty *ap;
{
	return(ioctl(fd, TIOCSETP, ap));
}

gtty(fd, ap)
struct sgtty *ap;
{
	return(ioctl(fd, TIOCGETP, ap));
}
 ((*s1++ = *s2++) == '\0') {
			while (++i < n)
				*s1++ = '\0';
			return(os1);
		}
	return(os1);
}
	}
	return(os1);
}
sk file...		*/
	 { ss->st_size = flength(fid);
	 }	
	return 0;
 }

stat(name, ss)
 char *name;
 struct stat *ss;
 {	int fid = open(n/usr/src/local/Machines/8086/lib86/gen     lib86/gen/swab.c                                                                                       444     140      12          352  3347642201   6651                                                                                                                                                                                                                                                                                                                                                                      /*
 * Swap bytes in 16-bit [half-]words
 * for going between the 11 and the interdata
 */

swab(pf, pt, n)
register short *pf, *pt;
register n;
{

	n = n/2;
	while (--n >= 0) {
		*pt++ = (*pf << 8) + ((*pf >> 8) & 0377);
		pf++;
	}
}
== '\0') {
			while (++i < n)
				*s1++ = '\0';
			return(os1);
		}
	return(os1);
}
	}
	return(os1);
}
sk file...		*/
	 { ss->st_size = flength(fid);
	 }	
	return 0;
 }

stat(name, ss)
 char *name;
 struct stat *ss;
 {	int fid = open(n/usr/src/local/Machines/8086/lib86/gen     lib86/gen/tell.c                                                                                       444     140      12          134  3347642202   6654                                                                                                                                                                                                                                                                                                                                                                      /*
 * return offset in file.
 */

long	lseek();

long tell(f)
{
	return(lseek(f, 0L, 1));
}
wab(pf, pt, n)
register short *pf, *pt;
register n;
{

	n = n/2;
	while (--n >= 0) {
		*pt++ = (*pf << 8) + ((*pf >> 8) & 0377);
		pf++;
	}
}
== '\0') {
			while (++i < n)
				*s1++ = '\0';
			return(os1);
		}
	return(os1);
}
	}
	return(os1);
}
sk file...		*/
	 { ss->st_size = flength(fid);
	 }	
	return 0;
 }

stat(name, ss)
 char *name;
 struct stat *ss;
 {	int fid = open(n/usr/src/local/Machines/8086/lib86/gen     lib86/gen/timezone.c                                                                                   444     140      12         1655  3347642202   7577                                                                                                                                                                                                                                                                                                                                                                      /*
 * The arguments are the number of minutes of time
 * you are westward from Greenwich and whether DST is in effect.
 * It returns a string
 * giving the name of the local timezone.
 *
 * Sorry, I don't know all the names.
 */

static struct zone {
	int	offset;
	char	*stdzone;
	char	*dlzone;
} zonetab[] = {
	4*60, "AST", "ADT",		/* Atlantic */
	5*60, "EST", "EDT",		/* Eastern */
	6*60, "CST", "CDT",		/* Central */
	7*60, "MST", "MDT",		/* Mountain */
	8*60, "PST", "PDT",		/* Pacific */
	0, "GMT", 0,			/* Greenwich */
	-1
};

char *timezone(zone, dst)
{
	register struct zone *zp;
	static char czone[10];
	char *sign;

	for (zp=zonetab; zp->offset!=-1; zp++)
		if (zp->offset==zone) {
			if (dst && zp->dlzone)
				return(zp->dlzone);
			if (!dst && zp->stdzone)
				return(zp->stdzone);
		}
	if (zone<0) {
		zone = -zone;
		sign = "+";
	} else
		sign = "-";
	sprintf(czone, "GMT%s%d:%02d", sign, zone/60, zone%60);
	return(czone);
}
ST", "MDT",		/* Mountain */
	8*60, "PST", "PDT",		/* Pacific */
	0, "GMT", 0,			/* lib86/gen/ttyname.c                                                                                    444     140      12         1617  3347642202   7424                                                                                                                                                                                                                                                                                                                                                                      #

/*
 * ttyname(f): return "/dev/ttyXX" which the the name of the
 * tty belonging to file f.
 *  NULL if it is not a tty
 */

#define	NULL	0
#include <sys/types.h>
#include <sys/dir.h>
#include <sys/stat.h>

static	char	dev[]	= "/dev/";
char	*strcpy();
char	*strcat();

char *
ttyname(f)
{
	struct stat fsb;
	struct stat tsb;
	struct direct db;
	static char rbuf[32];
	register df;

	if (isatty(f)==0)
		return(NULL);
	if (fstat(f, &fsb) < 0)
		return(NULL);
	if ((fsb.st_mode&S_IFMT) != S_IFCHR)
		return(NULL);
	if ((df = open(dev, 0)) < 0)
		return(NULL);
	while (read(df, (char *)&db, sizeof(db)) == sizeof(db)) {
		if (db.d_ino == 0)
			continue;
		if (db.d_ino != fsb.st_ino)
			continue;
		strcpy(rbuf, dev);
		strcat(rbuf, db.d_name);
		if (stat(rbuf, &tsb) < 0)
			continue;
		if (tsb.st_dev==fsb.st_dev && tsb.st_ino==fsb.st_ino) {
			close(df);
			return(rbuf);
		}
	}
	close(df);
	return(NULL);
}
==0)
		return(NULL);
	if (fstat(f, &fsb) < 0)
		return(NULL);
	if ((fsb.st_mode&S_IFMT) != S_IFCHR)
		return(NULLlib86/gen/ttyslot.c                                                                                    444     140      12         1613  3347642202   7461                                                                                                                                                                                                                                                                                                                                                                      #

/*
 * Return the number of the slot in the utmp file
 * corresponding to the current user: try for file 0, 1, 2.
 * Definition is the line number in the /etc/ttys file.
 */

char	*ttyname();
char	*getttys();
char	*rindex();
static	char	ttys[]	= "/etc/ttys";

#define	NULL	0

ttyslot()
{
	register char *tp, *p;
	register s, tf;

	if ((tp=ttyname(0))==NULL && (tp=ttyname(1))==NULL && (tp=ttyname(2))==NULL)
		return(0);
	if ((p = rindex(tp, '/')) == NULL)
		p = tp;
	else
		p++;
	if ((tf=open(ttys, 0)) < 0)
		return(0);
	s = 0;
	while (tp = getttys(tf)) {
		s++;
		if (strcmp(p, tp)==0) {
			close(tf);
			return(s);
		}
	}
	close(tf);
	return(0);
}

static char *
getttys(f)
{
	static char line[32];
	register char *lp;

	lp = line;
	for (;;) {
		if (read(f, lp, 1) != 1)
			return(NULL);
		if (*lp =='\n') {
			*lp = '\0';
			return(line+2);
		}
		if (lp >= &line[32])
			return(line+2);
		lp++;
	}
}
ame(2))==NULL)
		return(0);
	if ((p = rindex(tp, '/')) == NULL)
		p = tp;
	else
		p++;
	if ((tf=open(ttys, 0)) < 0)
	lib86/gen/blt.a86                                                                                      444     140      12         1513  3347642166   6704                                                                                                                                                                                                                                                                                                                                                                      |Block transfer subroutine: blt(destination, source, count), returns count

	.globl	_blt
	.text

_blt:	push	bp
	mov	bp,sp
	push	si
	push	di

	cld
	mov	di,*4(bp)	| destination
	mov	si,*6(bp)	| source
	mov	bx,*8(bp)	| count
	or	bx,bx
	jz	Ldone

	cmp	si,di		| see what direction to use
	jae	Lok		| no interference here!
	lea	ax,(bx_si)	| end of source block
	cmp	ax,di
	jbe	Lok		| source and destination are disjoint
	lea	si,*-2(bx_si)	| they overlap, so start at other end
	lea	di,*-2(bx_di)
	std
	test	bx,*1		| using byte moves?
	jz	Lok
	inc	si		| then point to last byte
	inc	di

Lok:	mov	cx,bx		| set up count
	test	bx,*1
	jz	Lword
	repz			| movb doesn't use "z" part!
	movb
	j	Ldone

Lword:	shr	cx,*1		| change to word count
	repz
	movw

Ldone:	cld			| direction control back to usual
	mov	ax,bx		| return count
	pop	di
	pop	si
	pop	bp
	ret
)	| end of source block
	cmp	ax,di
	jbe	Lok		| source and destination are disjoint
	lea	si,*-2(bx_si)	| they overlap, so start at other end
	lea	di,*-2(bx_di)
	std
	test	bx,*1		| uslib86/gen/clear.a86                                                                                    444     140      12          641  3347642166   7172                                                                                                                                                                                                                                                                                                                                                                      |Clear memory: clear(p, n) writes n bytes of zeros, starting at p

	.globl	_clear
	.text

_clear:	push	bp
	mov	bp,sp
	push	di

	cld			| positive direction.
	mov	di,*4(bp)	| beginning of block
	mov	cx,*6(bp)	| count
	or	cx,cx
	jz	Ldone		| check for zero count
	mov	ax,*0		| used as source for sto

	test	cx,*1		| words or bytes?
	jz	Lword
	repz
	stob
	j	Ldone

Lword:	shr	cx,*1
	repz
	stow

Ldone:	pop	di
	pop	bp
	ret
a	si,*-2(bx_si)	| they overlap, so start at other en/usr/src/local/Machines/8086/lib86/gen     lib86/gen/mfill.a86                                                                                    444     140      12          475  3347642172   7211                                                                                                                                                                                                                                                                                                                                                                      |fill memory: mfill(p, n, data) writes n bytes of data starting at p

	.globl	_mfill
	.text

_mfill:	push	bp
	mov	bp,sp
	push	di

	cld
	mov	di,*4(bp)	| beginning of block
	mov	cx,*6(bp)	| count
	or	cx,cx
	jz	Ldone		| check for zero count
	mov	ax,*8(bp)	| used as source for sto
	repz
	stob
Ldone:	pop	di
	pop	bp
	ret
 or bytes?
	jz	Lword
	repz
	stob
	j	Ldone

Lword:	shr	cx,*1
	repz
	stow

Ldone:	pop	di
	pop	bp
	ret
a	si,*-2(bx_si)	| they overlap, so start at other en/usr/src/local/Machines/8086/lib86/gen     lib86/gen/setjmp.a86                                                                                   444     140      12         1375  3347642176   7434                                                                                                                                                                                                                                                                                                                                                                      |setjmp, longjmp
|
|	longjmp(a, v)
|causes a "return(v)" from the
|last call to
|
|	setjmp(v)
|by restoring all the registers and
|adjusting the stack
|
|jmp_buf is set up as:
|
|	_________________
|	|	pc	|
|	-----------------
|	|	sp	|
|	-----------------
|	|	di	|
|	-----------------
|	|	si	|
|	-----------------

	.globl _setjmp, _longjmp
	.text

_setjmp:
	mov	bx,sp
	mov	ax,(bx)		| pc
	mov	bx,*2(bx)	| address of jmp_buf
	mov	(bx),ax		| fill buffer...
	mov	*2(bx),sp
	mov	*4(bx),di
	mov	*6(bx),si
	mov	ax,*0		| return 0...
	ret

longjmp:
	mov	bx,sp
	mov	ax,*4(bx)	| value to be returned
	mov	bx,*2(bx)	| pointer to jmp_buf
	mov	si,*6(bx)
	mov	di,*4(bx)
	mov	sp,*2(bx)	| reset stack
	mov	cx,(bx)		| old return pc
	mov	bx,sp		| which we'll reuse
	mov	(bx),cx
	ret
--
|	|	di	|
|	-----------------
|	|	si	|
|	-----------------

	.globl _setjmp, _longjmp
	.text

_setjmp:
	mov	bx,sp
	mov	ax,(bx)		| pc
	mov	bx,*2(bx)	| address of jmp_buf
	mov	(bx),ax		| fill buffer...
	mov	*2(bx),sp
	mov	*4(bx),di
	mov	*6(bx),si
	mov	ax,*0		lib86/ngen/Makefile                                                                                    444     140      12          101  3347642204   7362                                                                                                                                                                                                                                                                                                                                                                      all:
	cd ../gen; make
	cp ../gen/*.b .
	rm atof.b ecvt.b frexp.b
 be returned
	mov	bx,*2(bx)	| pointer to jmp_buf
	mov	si,*6(bx)
	mov	di,*4(bx)
	mov	sp,*2(bx)	| reset stack
	mov	cx,(bx)		| old return pc
	mov	bx,sp		| which we'll reuse
	mov	(bx),cx
	ret
--
|	|	di	|
|	-----------------
|	|	si	|
|	-----------------

	.globl _setjmp, _longjmp
	.text

_setjmp:
	mov	bx,sp
	mov	ax,(bx)		| pc
	mov	bx,*2(bx)	| address of jmp_buf
	mov	(bx),ax		| fill buffer...
	mov	*2(bx),s/usr/src/local/Machines/8086/lib86/ngen     lib86/stdio/Makefile                                                                                   444      30      12          746  3355601322   7545                                                                                                                                                                                                                                                                                                                                                                      .SUFFIXES: .b
.c.b: ; cc86 -c $<

OBJECTS =	fprintf.b sprintf.b printf.b scanf.b clrerr.b doscan.b\
		doprnt.b fdopen.b fgetc.b fopen.b fgets.b fputc.b\
		fputs.b freopen.b fseek.b ftell.b gcvt.b gets.b getw.b \
		putchar.b puts.b putw.b	rdwr.b rew.b strout.b\
		ungetc.b setbuf.b flsbuf.b filbuf.b data.b

all:		$(OBJECTS)

$(OBJECTS):	../include/stdio.h

doprnt.b:	doprnt.c
		cc86 -8087 -c doprnt.c

doscan.b:	doscan.c
		cc86 -8087 -c doscan.c

gcvt.b:		gcvt.c
		cc86 -8087 -c gcvt.c
ines/8086/lib86/stdio     lib86/stdio/clrerr.c                                                                                   444     140      12          144  3347424521   7561                                                                                                                                                                                                                                                                                                                                                                      #include	<stdio.h>

clearerr(iop)
register struct _iobuf *iop;
{
	iop->_flag &= ~(_IOERR|_IOEOF);
}
		doprnt.b fdopen.b fgetc.b fopen.b fgets.b fputc.b\
		fputs.b freopen.b fseek.b ftell.b gcvt.b gets.b getw.b \
		putchar.b puts.b putw.b	rdwr.b rew.b strout.b\
		ungetc.b setbuf.b flsbuf.b filbuf.b data.b

all:		$(OBJECTS)

$(OBJECTS):	../include/stdio.h

doprnt.b:	doprnt.c
		cc86 -8087 -c doprnt.c

doscan.b:	doscan.c
		cc86 -8087 -c doscan.c

gcvt.b:		gcvt.c
		cc/usr/src/local/Machines/8086/lib86/stdio     lib86/stdio/data.c                                                                                     444     140      12          440  3347424521   7200                                                                                                                                                                                                                                                                                                                                                                      #include <stdio.h>
char	_sibuf[BUFSIZ];
char	_sobuf[BUFSIZ];

struct	_iobuf	_iob[_NFILE] = {
	{ _sibuf, 0, _sibuf, _IOREAD+_IONBF, 0},
	{ NULL, 0, NULL, _IOWRT+_IONBF, 1},
	{NULL, 0, NULL, _IOWRT+_IONBF, 2},
};
/*
 * Ptr to end of buffers
 */
struct	_iobuf	*_lastbuf = { &_iob[_NFILE] };
b filbuf.b data.b

all:		$(OBJECTS)

$(OBJECTS):	../include/stdio.h

doprnt.b:	doprnt.c
		cc86 -8087 -c doprnt.c

doscan.b:	doscan.c
		cc86 -8087 -c doscan.c

gcvt.b:		gcvt.c
		cc/usr/src/local/Machines/8086/lib86/stdio     lib86/stdio/doprnt.c                                                                                   664     140      12        10474  3347424522   7652                                                                                                                                                                                                                                                                                                                                                                      # include <stdio.h>

_doprnt(fmt, argp, file)
register char *fmt;
register int *argp;
register FILE *file;
{	register char c, *p, *q;
	register int d, width, ndigit, radix;
	long n;
	int sign, decpt;
	char t[128], digits[10], zfill, rjust, ndfnd;
	char *ecvt(), *fcvt();
	struct {
		short unsigned length;
		char dtype;
		char class;
		char *ptr;
	} desc;
	p = &t[0];
	while (c = *fmt++)
		if (c != '%')
			*p++ = c;
		else {
			if (p != &t[0]) {
				_strout(t, p-t, 0, file);
				p = &t[0];
			}
			rjust = 0;
			ndigit = 0;
			zfill = ' ';
			if (*fmt == '-') {
				rjust++;
				fmt++;
			}
			if (*fmt == '0') {
				zfill = '0';
				fmt++;
			}
			if(*fmt != '*') { 
				width = 0;
				while ((d = *fmt++ - '0') >= 0 && d <= 9)
					width = width*10+d;
			}
			else {
				fmt++;
				d = *fmt++ - '0';
				width = *argp++;
			}
			ndfnd = 0;
			if ((d += '0') == '.') {
			    if(*fmt != '*') {
				ndigit = 0;
				while ((d = *fmt++ - '0') >= 0 && d <= 9) {
					ndfnd++;
					ndigit = ndigit*10+d;
				}
				d += '0';
			    }
			    else {
				fmt++;
				d = *fmt++;
				ndfnd++;
				ndigit = *argp++;
			    }
			}
			switch (d) {
			case 'l':
			case 'L':
				switch(*fmt++) {
				case 'o': goto loct;
				case 'x': goto lhex;
				case 'd': goto ldec;
				case 'u': goto luns;
				default:
					fmt--;
					goto uns;
				}
			case 'o':
			case 'O':
			loct:	radix = 8;
				n = *argp++;
				goto compute;
			case 'X':
			lhex:	radix = 16;
				n = *(long *)argp;
				argp + = 2;
				goto hexcomp;

			case 'x':
				radix = 16;
				n = *argp++;
			hexcomp:
				if (n == 0 && ndigit == 0)
					*p++ = '0';
				for (q = &digits[0]; n != 0;
						n = (n>>4) & 0x0fffffff)
				{
					d = n & 0xF;
					*q++ = d + (d<10?'0':'a'-10);
				}
				while (q > &digits[0])
					*p++ = *--q;
				goto prbuf;


			case 'D':
			ldec:	
				radix = 10;
				n = *(long *)argp;
				if(n < 0){
					n = -n;
					*p++ = '-';
				}
				argp += 2;
				goto compute;

			case 'd':
				radix = 10;
			signed:	if (*argp < 0) {
					*p++ = '-';
					n = -*argp++;
				} else
					n = *argp++;
				goto compute;

			case 'u':
			case 'U':
			luns:
			uns:	n = *argp++;
				radix = 10;
			compute:
				if (n == 0 && ndigit == 0)
					*p++ = '0';
				for (q = &digits[0]; n != 0; n = n/radix)
				{
					d = n%radix; 
/*					d = n - ((n/radix) * radix); */
/*					d = n;
					while(d >= radix) d -= radix;
*/					if(d<0) d += radix;
					*q++ = d + (d<10?'0':'a'-10);
				}
				while (q > &digits[0])
					*p++ = *--q;
				goto prbuf;

			case 'c':
				for (q = (char *)argp++, d = 0; d < sizeof(int); d++)
					if ((*p++ = *q++) == 0)
						p--;
			prbuf:	q = &t[0];
			prstr:	if ((d = width - (p - q)) < 0)
					d = 0;
				if (rjust == 0)
					d = -d;
				_strout(q, p-q, d, file, zfill);
				p = &t[0];
				break;

			case 's':
				if ((q = (char *)*argp++) == 0)
					q = "(null)";
				if ((d = ndigit) == 0)
					d = 32767;
				for (p=q; *p!=0 && --d>=0; p++);
				goto prstr;

			case 'r':
				argp = (int *)*argp;
				fmt = (char *)*argp++;
				break;
			case 'f':
				if (ndfnd == 0)
					ndigit = 6;
				q = fcvt(*((double *)argp), ndigit,
					&decpt, &sign); argp += 
					sizeof *(double *) argp /
					  sizeof *argp;
				if (sign)
					*p++ = '-';
				if ((d = decpt) <= 0)
					*p++ = '0';
				else do {
						*p++ = *q++;
					} while (--d > 0);
				if (d = ndigit)
					*p++ = '.';
				if ((decpt = - decpt) > 0)
					while (--d >= 0) {
						*p++ = '0';
						if (--decpt <= 0)
							break;
					}
				if (d > 0)
					while (--d >= 0)
						*p++ = *q++;
				goto prbuf;

			case 'e':
				if (ndfnd == 0)
					ndigit = 6;
				else
					ndigit += 1;
				q = ecvt(*((double *)argp), ndigit,
					&decpt, &sign); argp +=
					sizeof *(double *) argp /
					  sizeof *argp;
				if (sign)
					*p++ = '-';
				if (*q == '0')
					decpt += 1;
				*p++ = *q++;
				*p++ = '.';
				for (d = ndigit; --d > 0; *p++ = *q++);
				*p++ = 'e';
				decpt -= 1;
				if (decpt >= 0)
					*p++ = '+';
				else {
					*p++ = '-';
					decpt = -decpt;
				}
				*p++ = (unsigned)decpt/10+'0';
				*p++ = (unsigned)decpt%10+'0';
				goto prbuf;

			case 'g':
				if (ndfnd == 0)
					ndigit = 6;
				gcvt(*((double *)argp), ndigit, p); argp +=
					sizeof *(double *) argp /
					  sizeof *argp;
				while (*p++ != 0);
				p -= 1;
				goto prbuf;
			case '%':
				*p++= '%';
				break;
			}
	}
	if (p != &t[0])
		_strout(t, p-t, 0, file);
}
q++);
				*p++ = 'e';
				decpt -= 1;
				if (decpt >= 0)
					*p++ = '+';
				else {
					*p++ = '-';
					decpt = -decpt;
				}
				*p++ = (unsigned)decpt/10+'0';
				*p++ = (unsigned)decpt%10+'lib86/stdio/doscan.c                                                                                   444     140      12        10745  3347424523   7611                                                                                                                                                                                                                                                                                                                                                                      #include <stdio.h>
#include	<ctype.h>

#define	SPC	01
#define	STP	02

#define	SHORT	0
#define	REGULAR	1
#define	LONG	2
#define	INT	0
#define	FLOAT	1

char	*_getccl();

char	_sctab[128] = {
	0,0,0,0,0,0,0,0,
	0,SPC,SPC,0,0,0,0,0,
	0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,
	SPC,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,
};

_doscan(iop, fmt, argp)
FILE *iop;
register char *fmt;
register int **argp;
{
	register int ch;
	int nmatch, len, ch1;
	int **ptr, fileended, size;

	nmatch = 0;
	fileended = 0;
	for (;;) switch (ch = *fmt++) {
	case '\0': 
		return (nmatch);
	case '%': 
		if ((ch = *fmt++) == '%')
			goto def;
		ptr = 0;
		if (ch != '*')
			ptr = argp++;
		else
			ch = *fmt++;
		len = 0;
		size = REGULAR;
		while (ch>='0' && ch <='9') {
			len = len*10 + ch - '0';
			ch = *fmt++;
		}
		if (len == 0)
			len = 30000;
		if (ch=='l') {
			ch = *fmt++;
			size = LONG;
		} else if (ch=='h') {
			size = SHORT;
			ch = *fmt++;
		} else if (ch=='[')
			fmt = _getccl(fmt);
		if (isupper(ch)) {
			ch = tolower(ch);
			size = LONG;
		}
		if (ch == '\0')
			return(-1);
		if (_innum(ptr, ch, len, size, iop, &fileended) && ptr)
			nmatch++;
		if (fileended)
			return(nmatch? nmatch: -1);
		break;

	case ' ':
	case '\r':
	case '\n':
	case '\t': 
	while ((ch1 = getc(iop))==' ' || ch1=='\t' || ch1=='\n'|| ch1 =='\r')
			;
		if (ch1 != EOF)
			ungetc(ch1, iop);
		break;

	default: 
	def:
		ch1 = getc(iop);
		if (ch1 != ch) {
			if (ch1==EOF)
				return(-1);
			ungetc(ch1, iop);
			return(nmatch);
		}
	}
}

_innum(ptr, type, len, size, iop, eofptr)
int **ptr, *eofptr;
struct _iobuf *iop;
{
	extern double atof();
	register char *np;
	char numbuf[64];
int c, base;
	int expseen, scale, negflg, c1, ndigit;
	long lcval;

	if (type=='c' || type=='s' || type=='[')
		return(_instr(ptr? *(char **)ptr: (char *)NULL, type, len, iop, eofptr));
	lcval = 0;
	ndigit = 0;
	scale = INT;
	if (type=='e'||type=='f')
		scale = FLOAT;
	base = 10;
	if (type=='o')
		base = 8;
	else if (type=='x')
		base = 16;
	np = numbuf;
	expseen = 0;
	negflg = 0;
	while ((c = getc(iop))==' ' || c=='\t' || c=='\n'|| c=='\r');
	if (c=='-') {
		negflg++;
		*np++ = c;
		c = getc(iop);
		len--;
	} else if (c=='+') {
		len--;
		c = getc(iop);
	}
	for ( ; --len>=0; *np++ = c, c = getc(iop)) {


		if ('0'<=c && c<='9'
		 || base==16 && ('a'<=c && c<='f' || 'A'<=c && c<='F')) {
			ndigit++;
			if (base==8)
				lcval <<=3;
			else if (base==10)
			lcval = ((lcval<<2) + lcval)<<1;

			else
				lcval <<= 4;
			c1 = c;
			if ('0'<=c && c<='9')
				c -= '0';
			else if ('a'<=c && c<='f')
				c -= 'a'-10;
			else
				c -= 'A'-10;
			lcval += c;
			c = c1;
			continue;
		} else if (c=='.') {
			if (base!=10 || scale==INT)
				break;
			ndigit++;
			continue;
		} else if ((c=='e'||c=='E') && expseen==0) {
			if (base!=10 || scale==INT || ndigit==0)
				break;
			expseen++;
			*np++ = c;
			c = getc(iop);
			if (c!='+'&&c!='-'&&('0'>c||c>'9'))
				break;
		} else
			break;
	}
	if (negflg)
		lcval = -lcval;
	if (c != EOF) {
		ungetc(c, iop);
		*eofptr = 0;
	} else
		*eofptr = 1;
	if (ptr==NULL || np==numbuf)
		return(0);
	*np++ = 0;
	switch((scale<<4) | size) {

	case (FLOAT<<4) | SHORT:
	case (FLOAT<<4) | REGULAR:
		*(*((float **)ptr)) = atof(numbuf);
		break;

	case (FLOAT<<4) | LONG:
		*(*((double **)ptr)) = atof(numbuf);
		break;

	case (INT<<4) | SHORT:
		**(short **)ptr = lcval;
		break;

	case (INT<<4) | REGULAR:
		**(int **)ptr = lcval;
		break;

	case (INT<<4) | LONG:
		**(long **)ptr = lcval;
		break;
	}
	return(1);
}

_instr(ptr, type, len, iop, eofptr)
register char *ptr;
register struct _iobuf *iop;
int *eofptr;
{
	register ch;
	register char *optr;
	int ignstp;

	*eofptr = 0;
	optr = ptr;
	if (type=='c' && len==30000)
		len = 1;
	ignstp = 0;
	if (type=='s')
		ignstp = SPC;
	while (_sctab[ch = getc(iop)] & ignstp)
		if (ch==EOF)
			break;
	ignstp = SPC;
	if (type=='c')
		ignstp = 0;
	else if (type=='[')
		ignstp = STP;
	while (ch!=EOF && (_sctab[ch]&ignstp)==0) {
		if (ptr)
			*ptr++ = ch;
		if (--len <= 0)
			break;
		ch = getc(iop);
	}
	if (ch != EOF) {
		if (len > 0)
			ungetc(ch, iop);
		*eofptr = 0;
	} else
		*eofptr = 1;
	if (ptr && ptr!=optr) {
		if (type!='c')
			*ptr++ = '\0';
		return(1);
	}
	return(0);
}

char *
_getccl(s)
register char *s;
{
	register c, t;

	t = 0;
	if (*s == '^') {
		t++;
		s++;
	}
	for (c = 0; c < 128; c++)
		if (t)
			_sctab[c] &= ~STP;
		else
			_sctab[c] |= STP;
	while (((c = *s++)&0177) != ']') {
		if (t)
			_sctab[c++] |= STP;
		else
			_sctab[c++] &= ~STP;
		if (c==0)
			return(--s);
	}
	return(s);
}
}
	if (ch != EOF) {
		if (llib86/stdio/fdopen.c                                                                                   444     140      12         1072  3347424523   7566                                                                                                                                                                                                                                                                                                                                                                      /*
 * Unix routine to do an "fopen" on file descriptor
 * The mode has to be repeated because you can't query its
 * status
 */

#include	<stdio.h>
#include	<errno.h>

struct _iobuf *
fdopen(fd, mode)
register char *mode;
{
	extern int errno;
	register struct _iobuf *iop;
	extern struct _iobuf *_lastbuf;

	for (iop = _iob; iop->_flag&(_IOREAD|_IOWRT); iop++)
		if (iop >= _lastbuf)
			return(NULL);
	iop->_cnt = 0;
	iop->_file = fd;
	if (*mode != 'r') {
		iop->_flag |= _IOWRT;
		if (*mode == 'a')
			lseek(fd, 0L, 2);
	} else
		iop->_flag |= _IOREAD;
	return(iop);
}
The mode has to be repeated because you can't query its
 * status
 */

#include	<stdio.h>
#include	<errno.h>

struct _iobuf *
fdopen(fd, mode)
register char *mode;
{
	extern int errno;
	register struct _iobuf *iop;
	extern struct _iobuf *_lastbuf;

	for (iop = _iob; iop->_flag&(_IOREAD|_IOWRT); iop++)
		if (iop >= _lastbuf)
			return(NULL);
	iop->_cnt = 0;
	iop->_file = fd;
	if (*mode != 'r') {
		iop->_flag |= _IOWRT;
		if (*mode == 'a')
			lseek(fd,lib86/stdio/fgetc.c                                                                                    444     140      12           77  3347424524   7350                                                                                                                                                                                                                                                                                                                                                                      #include <stdio.h>

fgetc(fp)
FILE *fp;
{
	return(getc(fp));
}
ode has to be repeated because you can't query its
 * status
 */

#include	<stdio.h>
#include	<errno.h>

struct _iobuf *
fdopen(fd, mode)
register char *mode;
{
	extern int errno;
	register struct _iobuf *iop;
	extern struct _iobuf *_lastbuf;

	for (iop = _iob; iop->_flag&(_IOREAD|_IOWRT); iop++)
		if (iop >= _lastbuf)
			return(NULL);
	iop->_cnt = 0;
	iop->_file = fd;
	if (*mode != 'r') {
		iop->_fla/usr/src/local/Machines/8086/lib86/stdio     lib86/stdio/fgets.c                                                                                    444     140      12          406  3347424524   7404                                                                                                                                                                                                                                                                                                                                                                      #include	<stdio.h>

char *
fgets(s, n, iop)
char *s;
register FILE *iop;
{
	register c;
	register char *cs;

	cs = s;
	while (--n>0 && (c = getc(iop))>=0) {
		*cs++ = c;
		if (c=='\n')
			break;
	}
	if (c<0 && cs==s)
		return(NULL);
	*cs++ = '\0';
	return(s);
}
obuf *iop;
	extern struct _iobuf *_lastbuf;

	for (iop = _iob; iop->_flag&(_IOREAD|_IOWRT); iop++)
		if (iop >= _lastbuf)
			return(NULL);
	iop->_cnt = 0;
	iop->_file = fd;
	if (*mode != 'r') {
		iop->_fla/usr/src/local/Machines/8086/lib86/stdio     lib86/stdio/filbuf.c                                                                                   444     140      12         1275  3347424525   7571                                                                                                                                                                                                                                                                                                                                                                      #include	<stdio.h>
char	*malloc();

_filbuf(iop)
register FILE *iop;
{
	static char smallbuf[_NFILE];

	if ((iop->_flag&_IOREAD) == 0)
		return(EOF);
	if (iop->_flag&_IOSTRG)
		return(EOF);
tryagain:
	if (iop->_base==NULL) {
		if (iop->_flag&_IONBF) {
			iop->_base = &smallbuf[fileno(iop)];
			goto tryagain;
		}
		if ((iop->_base = malloc(BUFSIZ)) == NULL) {
			iop->_flag |= _IONBF;
			goto tryagain;
		}
		iop->_flag |= _IOMYBUF;
	}
	iop->_ptr = iop->_base;
	iop->_cnt = read(fileno(iop), iop->_ptr, iop->_flag&_IONBF?1:BUFSIZ);
	if (--iop->_cnt < 0) {
		if (iop->_cnt == -1)
			iop->_flag |= _IOEOF;
		else
			iop->_flag |= _IOERR;
		iop->_cnt = 0;
		return(-1);
	}
	return(*iop->_ptr++&0377);
}

tryagain:
	if (iop->_base==NULL) {
		if (iop->_flag&_IONBF) {
			iop->_base = &smallbuf[fileno(iop)];
			goto tryagain;
		}
		if ((iop->_base = malloc(BUFSIZ)) == NULL) {
			iop->_flag |= _IONBF;
			goto tryagain;
		}
		iop->_flag |= _IOMYBUF;
	}
	iop->_ptr = iop->_base;
	iop->_cnt = read(fileno(iop), iop->_ptr, iop->_fllib86/stdio/flsbuf.c                                                                                   444     140      12         3415  3347424525   7601                                                                                                                                                                                                                                                                                                                                                                      #include	<stdio.h>

char	*malloc();

_flsbuf(c, iop)
register FILE *iop;
{
	register char *base;
	register n, rn;
	char c1;
	extern char _sobuf[];

	if ((iop->_flag&_IOWRT)==0)
		return(EOF);
tryagain:
	if (iop->_flag&_IONBF) {
		c1 = c;
		rn = 1;
		n = write(fileno(iop), &c1, rn);
		iop->_cnt = 0;
	} else {
		if ((base=iop->_base)==NULL) {
			if (iop==stdout) {
				if (isatty(fileno(stdout))) {
					iop->_flag |= _IONBF;
					goto tryagain;
				}
				iop->_base = _sobuf;
				iop->_ptr = _sobuf;
				goto tryagain;
			}
			if ((iop->_base=base=malloc(BUFSIZ)) == NULL) {
				iop->_flag |= _IONBF;
				goto tryagain;
			}
			iop->_flag |= _IOMYBUF;
			rn = n = 0;
		} else if ((rn = n = iop->_ptr - base) > 0) {
			iop->_ptr = base;
			n = write(fileno(iop), base, n);
		}
		iop->_cnt = BUFSIZ-1;
		*base++ = c;
		iop->_ptr = base;
	}
	if (rn != n) {
		iop->_flag |= _IOERR;
		return(EOF);
	}
	return(c);
}

fflush(iop)
register struct _iobuf *iop;
{
	register char *base;
	register n;

	if ((iop->_flag&(_IONBF|_IOWRT))==_IOWRT
	 && (base=iop->_base)!=NULL && (n=iop->_ptr-base)>0) {
		iop->_ptr = base;
		iop->_cnt = BUFSIZ;
		if (write(fileno(iop), base, n)!=n) {
			iop->_flag |= _IOERR;
			return(EOF);
		}
	}
	return(0);
}

/*
 * Flush buffers on exit
 */

_cleanup()
{
	register struct _iobuf *iop;
	extern struct _iobuf *_lastbuf;

	for (iop = _iob; iop < _lastbuf; iop++)
		fclose(iop);
}

fclose(iop)
register struct _iobuf *iop;
{
	register r;

	r = EOF;
	if (iop->_flag&(_IOREAD|_IOWRT) && (iop->_flag&_IOSTRG)==0) {
		r = fflush(iop);
		if (close(fileno(iop)) < 0)
			r = EOF;
		if (iop->_flag&_IOMYBUF)
			free(iop->_base);
		if (iop->_flag&(_IOMYBUF|_IONBF))
			iop->_base = NULL;
	}
	iop->_flag &= ~(_IOREAD|_IOWRT|_IONBF|_IOMYBUF|_IOERR|_IOEOF|_IOSTRG);
	iop->_cnt = 0;
	return(r);
}
uct _iobuf *iop;
	extern struct _iobuf *_lastbuf;

	for (iop = _iob; iop < _lastbuf; iop++)
		fclose(iop);
}

fclose(iop)
register struct _iobuf *iop;
{
	register r;

	r = EOF;
	if (iop->_flag&(_IOREAD|_IOWRT) && (iop->_flag&_IOSTRG)==0) {
		rlib86/stdio/fopen.c                                                                                    444     140      12         1604  3347424526   7426                                                                                                                                                                                                                                                                                                                                                                      #include	<stdio.h>
#include	<errno.h>

struct _iobuf *
fopen(file, mode)
char *file;
register char *mode;
{
	extern int errno;
	register f;
	register struct _iobuf *iop;
	extern struct _iobuf *_lastbuf;
	static char init=0;


	if (!init)
	 { register char *p = (char *) &(_iob[3]);
	   register int i, top;

	   _lastbuf = &_iob[_NFILE];	/* SAW: somehow, we need this too. */

	   for (i = (_NFILE-3)*(sizeof _iob[0]); i--;) *p++ = 0;
	   init = 1;
	 }

	for (iop = _iob; iop->_flag&(_IOREAD|_IOWRT); iop++)
		if (iop >= _lastbuf) return(NULL);


	if (*mode=='w')
		f = creat(file, 0666);
	else if (*mode=='a') {
		if ((f = open(file, 1)) < 0) {
			if (errno == ENOENT)
				f = creat(file, 0666);
		}
		lseek(f, 0L, 2);
	} else
		f = open(file, 0);
	if (f < 0)
		return(NULL);
	iop->_cnt = 0;
	iop->_file = f;
	if (*mode != 'r')
		iop->_flag |= _IOWRT;
	else
		iop->_flag |= _IOREAD;
	return(iop);
}
= (_NFILE-3)*(sizeof _iob[0]); i--;) *p++ = 0;
	   init = 1;
	 }

	for (iop = _iob; iop->_flag&(_IOREAD|_IOWRT); iop++)
		iflib86/stdio/fprintf.c                                                                                  444     140      12          177  3347424526   7753                                                                                                                                                                                                                                                                                                                                                                      #include	<stdio.h>

fprintf(iop, fmt, args)
FILE *iop;
char *fmt;
{
	_doprnt(fmt, &args, iop);
	return(ferror(iop)? EOF: 0);
}
< 0) {
			if (errno == ENOENT)
				f = creat(file, 0666);
		}
		lseek(f, 0L, 2);
	} else
		f = open(file, 0);
	if (f < 0)
		return(NULL);
	iop->_cnt = 0;
	iop->_file = f;
	if (*mode != 'r')
		iop->_flag |= _IOWRT;
	else
		iop->_flag |= _IOREAD;
	return(iop);
}
= (_NFILE-3)*(sizeof _iob[0]); i--;) *p++ = 0;
	   init = 1;
	 }

	for (iop = _/usr/src/local/Machines/8086/lib86/stdio     lib86/stdio/fputc.c                                                                                    444     140      12          105  3347424526   7413                                                                                                                                                                                                                                                                                                                                                                      #include <stdio.h>

fputc(c, fp)
FILE *fp;
{
	return(putc(c, fp));
}
_doprnt(fmt, &args, iop);
	return(ferror(iop)? EOF: 0);
}
< 0) {
			if (errno == ENOENT)
				f = creat(file, 0666);
		}
		lseek(f, 0L, 2);
	} else
		f = open(file, 0);
	if (f < 0)
		return(NULL);
	iop->_cnt = 0;
	iop->_file = f;
	if (*mode != 'r')
		iop->_flag |= _IOWRT;
	else
		iop->_flag |= _IOREAD;
	return(iop);
}
= (_NFILE-3)*(sizeof _iob[0]); i--;) *p++ = 0;
	   init = 1;
	 }

	for (iop = _/usr/src/local/Machines/8086/lib86/stdio     lib86/stdio/fputs.c                                                                                    444     140      12          231  3347424526   7433                                                                                                                                                                                                                                                                                                                                                                      #include	<stdio.h>

fputs(s, iop)
register char *s;
register FILE *iop;
{
	register r;
	register c;

	while (c = *s++)
		r = putc(c, iop);
	return(r);
}
ENT)
				f = creat(file, 0666);
		}
		lseek(f, 0L, 2);
	} else
		f = open(file, 0);
	if (f < 0)
		return(NULL);
	iop->_cnt = 0;
	iop->_file = f;
	if (*mode != 'r')
		iop->_flag |= _IOWRT;
	else
		iop->_flag |= _IOREAD;
	return(iop);
}
= (_NFILE-3)*(sizeof _iob[0]); i--;) *p++ = 0;
	   init = 1;
	 }

	for (iop = _/usr/src/local/Machines/8086/lib86/stdio     lib86/stdio/freopen.c                                                                                  444     140      12          671  3347424527   7741                                                                                                                                                                                                                                                                                                                                                                      #include <stdio.h>

FILE *
freopen(file, mode, iop)
char *file;
register char *mode;
register FILE *iop;
{
	register f;

	fclose(iop);
	if (*mode=='w')
		f = creat(file, 0666);
	else if (*mode=='a') {
		if ((f = open(file, 1)) < 0)
			f = creat(file, 0666);
		lseek(f, 0L, 2);
	} else
		f = open(file, 0);
	if (f < 0)
		return(NULL);
	iop->_file = f;
	if (*mode != 'r')
		iop->_flag |= _IOWRT;
	else
		iop->_flag |= _IOREAD;
	return(iop);
}
it = 1;
	 }

	for (iop = _/usr/src/local/Machines/8086/lib86/stdio     lib86/stdio/fseek.c                                                                                    444     140      12         1423  3347424527   7414                                                                                                                                                                                                                                                                                                                                                                      /*
 * Seek for standard library.  Coordinates with buffering.
 */

#include	<stdio.h>

long lseek();

fseek(iop, offset, ptrname)
FILE *iop;
long offset;
{
	register resync, c;
	long p;

	iop->_flag &= ~_IOEOF;
	if (iop->_flag&_IOREAD) {
		if (ptrname<2 && iop->_base &&
			!(iop->_flag&_IONBF)) {
			c = iop->_cnt;
			p = offset;
			if (ptrname==0)
				p += c - lseek(fileno(iop),0L,1);
			else
				offset -= c;
			if(c>0&&p<=c&&p>=iop->_base-iop->_ptr){
				iop->_ptr += (int)p;
				iop->_cnt -= (int)p;
				return(0);
			}
			resync = offset&01;
		} else 
			resync = 0;
		p = lseek(fileno(iop), offset-resync, ptrname);
		iop->_cnt = 0;
		if (resync)
			getc(iop);
	}
	else if (iop->_flag&_IOWRT) {
		fflush(iop);
		p = lseek(fileno(iop), offset, ptrname);
	}
	return(p==-1?-1:0);
}
(iop->_flag&_IONBF)) {
			c = iop->_cnt;
			p = offset;
			if (ptrname==0)
				p += c - lseek(fileno(iop),0L,1);
			else
				offset -= c;
			if(c>0&&p<=c&&p>=iop->_base-iop->_ptr){
				iop->_ptr += (int)p;
				iop->_cnt -= (int)p;
				relib86/stdio/ftell.c                                                                                    444     140      12          750  3347424527   7407                                                                                                                                                                                                                                                                                                                                                                      /*
 * Return file offset.
 * Coordinates with buffering.
 */

#include	<stdio.h>
long	lseek();


long ftell(iop)
FILE *iop;
{
	long tres;
	register adjust;

	if (iop->_cnt < 0)
		iop->_cnt = 0;
	if (iop->_flag&_IOREAD)
		adjust = - iop->_cnt;
	else if (iop->_flag&_IOWRT) {
		adjust = 0;
		if (iop->_base && (iop->_flag&_IONBF)==0)
			adjust = iop->_ptr - iop->_base;
	} else
		return(-1);
	tres = lseek(fileno(iop), 0L, 1);
	if (tres<0)
		return(tres);
	tres += adjust;
	return(tres);
}
es/8086/lib86/stdio     lib86/stdio/gcvt.c                                                                                     444     140      12         1762  3347424527   7270                                                                                                                                                                                                                                                                                                                                                                      /*
 * gcvt  - Floating output conversion to
 * minimal length string
 */

char	*ecvt();

char *
gcvt(number, ndigit, buf)
double number;
char *buf;
{
	int sign, decpt;
	register char *p1, *p2;
	register i;

	p1 = ecvt(number, ndigit, &decpt, &sign);
	p2 = buf;
	if (sign)
		*p2++ = '-';
	for (i=ndigit-1; i>0 && p1[i]=='0'; i--)
		ndigit--;
	if (decpt >= 0 && decpt-ndigit > 4
	 || decpt < 0 && decpt < -3) { /* use E-style */
		decpt--;
		*p2++ = *p1++;
		*p2++ = '.';
		for (i=1; i<ndigit; i++)
			*p2++ = *p1++;
		*p2++ = 'e';
		if (decpt<0) {
			decpt = -decpt;
			*p2++ = '-';
		} else
			*p2++ = '+';
		*p2++ = decpt/10 + '0';
		*p2++ = decpt%10 + '0';
	} else {
		if (decpt<=0) {
			if (*p1!='0')
				*p2++ = '.';
			while (decpt<0) {
				decpt++;
				*p2++ = '0';
			}
		}
		for (i=1; i<=ndigit; i++) {
			*p2++ = *p1++;
			if (i==decpt)
				*p2++ = '.';
		}
		if (ndigit<decpt) {
			while (ndigit++<decpt)
				*p2++ = '0';
			*p2++ = '.';
		}
	}
	if (p2[-1]=='.')
		p2--;
	*p2 = '\0';
	return(buf);
}
		*p2++ = *p1+lib86/stdio/getchar.c                                                                                  444     140      12          175  3347424530   7711                                                                                                                                                                                                                                                                                                                                                                      /*
 * A subroutine version of the macro getchar.
 */
#include <stdio.h>

#undef getchar

getchar()
{
	return(getc(stdin));
}
2++ = decpt%10 + '0';
	} else {
		if (decpt<=0) {
			if (*p1!='0')
				*p2++ = '.';
			while (decpt<0) {
				decpt++;
				*p2++ = '0';
			}
		}
		for (i=1; i<=ndigit; i++) {
			*p2++ = *p1++;
			if (i==decpt)
				*p2++ = '.';
		}
		if (ndigit<decpt) {
			while (ndigit++<decpt)
				*p2++ = '0';
			*p2++ = '.';
		}
	}
	if (p2[-1]=='.')
		p2--/usr/src/local/Machines/8086/lib86/stdio     lib86/stdio/gets.c                                                                                     444     140      12          321  3347424530   7227                                                                                                                                                                                                                                                                                                                                                                      #include	<stdio.h>

char *
gets(s)
char *s;
{
	register c;
	register char *cs;

	cs = s;
	while ((c = getchar()) != '\n' && c >= 0)
		*cs++ = c;
	if (c<0 && cs==s)
		return(NULL);
	*cs++ = '\0';
	return(s);
}
			while (decpt<0) {
				decpt++;
				*p2++ = '0';
			}
		}
		for (i=1; i<=ndigit; i++) {
			*p2++ = *p1++;
			if (i==decpt)
				*p2++ = '.';
		}
		if (ndigit<decpt) {
			while (ndigit++<decpt)
				*p2++ = '0';
			*p2++ = '.';
		}
	}
	if (p2[-1]=='.')
		p2--/usr/src/local/Machines/8086/lib86/stdio     lib86/stdio/getw.c                                                                                     444     140      12          240  3347424531   7234                                                                                                                                                                                                                                                                                                                                                                      #include	<stdio.h>

getw(iop)
register struct _iobuf *iop;
{
	register i;

	i = getc(iop);
	if (iop->_flag&_IOEOF)
		return(-1);
	return(i | (getc(iop)<<8));
}
=s)
		return(NULL);
	*cs++ = '\0';
	return(s);
}
			while (decpt<0) {
				decpt++;
				*p2++ = '0';
			}
		}
		for (i=1; i<=ndigit; i++) {
			*p2++ = *p1++;
			if (i==decpt)
				*p2++ = '.';
		}
		if (ndigit<decpt) {
			while (ndigit++<decpt)
				*p2++ = '0';
			*p2++ = '.';
		}
	}
	if (p2[-1]=='.')
		p2--/usr/src/local/Machines/8086/lib86/stdio     lib86/stdio/printf.c                                                                                   444     140      12          164  3347424531   7575                                                                                                                                                                                                                                                                                                                                                                      #include	<stdio.h>

printf(fmt, args)
char *fmt;
{
	_doprnt(fmt, &args, stdout);
	return(ferror(stdout)? EOF: 0);
}
	return(-1);
	return(i | (getc(iop)<<8));
}
=s)
		return(NULL);
	*cs++ = '\0';
	return(s);
}
			while (decpt<0) {
				decpt++;
				*p2++ = '0';
			}
		}
		for (i=1; i<=ndigit; i++) {
			*p2++ = *p1++;
			if (i==decpt)
				*p2++ = '.';
		}
		if (ndigit<decpt) {
			while (ndigit++<decpt)
				*p2++ = '0';
			*p2++ = '.';
		}
	}
	if (p2[-1]=='.')
		p2--/usr/src/local/Machines/8086/lib86/stdio     lib86/stdio/putchar.c                                                                                  444     140      12          205  3347424532   7736                                                                                                                                                                                                                                                                                                                                                                      /*
 * A subroutine version of the macro putchar
 */
#include <stdio.h>

#undef putchar

putchar(c)
register c;
{
	putc(c, stdout);
}
urn(i | (getc(iop)<<8));
}
=s)
		return(NULL);
	*cs++ = '\0';
	return(s);
}
			while (decpt<0) {
				decpt++;
				*p2++ = '0';
			}
		}
		for (i=1; i<=ndigit; i++) {
			*p2++ = *p1++;
			if (i==decpt)
				*p2++ = '.';
		}
		if (ndigit<decpt) {
			while (ndigit++<decpt)
				*p2++ = '0';
			*p2++ = '.';
		}
	}
	if (p2[-1]=='.')
		p2--/usr/src/local/Machines/8086/lib86/stdio     lib86/stdio/puts.c                                                                                     444     140      12          170  3347424532   7264                                                                                                                                                                                                                                                                                                                                                                      #include	<stdio.h>

puts(s)
register char *s;
{
	register c;

	while (c = *s++)
		putchar(c);
	return(putchar('\n'));
}
, stdout);
}
urn(i | (getc(iop)<<8));
}
=s)
		return(NULL);
	*cs++ = '\0';
	return(s);
}
			while (decpt<0) {
				decpt++;
				*p2++ = '0';
			}
		}
		for (i=1; i<=ndigit; i++) {
			*p2++ = *p1++;
			if (i==decpt)
				*p2++ = '.';
		}
		if (ndigit<decpt) {
			while (ndigit++<decpt)
				*p2++ = '0';
			*p2++ = '.';
		}
	}
	if (p2[-1]=='.')
		p2--/usr/src/local/Machines/8086/lib86/stdio     lib86/stdio/putw.c                                                                                     444     140      12          157  3347424533   7276                                                                                                                                                                                                                                                                                                                                                                      #include	<stdio.h>

putw(i, iop)
register i;
register struct _iobuf *iop;
{
	putc(i, iop);
	putc(i>>8, iop);
}
\n'));
}
, stdout);
}
urn(i | (getc(iop)<<8));
}
=s)
		return(NULL);
	*cs++ = '\0';
	return(s);
}
			while (decpt<0) {
				decpt++;
				*p2++ = '0';
			}
		}
		for (i=1; i<=ndigit; i++) {
			*p2++ = *p1++;
			if (i==decpt)
				*p2++ = '.';
		}
		if (ndigit<decpt) {
			while (ndigit++<decpt)
				*p2++ = '0';
			*p2++ = '.';
		}
	}
	if (p2[-1]=='.')
		p2--/usr/src/local/Machines/8086/lib86/stdio     lib86/stdio/rdwr.c                                                                                     444     140      12         1165  3347424533   7275                                                                                                                                                                                                                                                                                                                                                                      #include	<stdio.h>

fread(ptr, size, count, iop)
unsigned size, count;
register char *ptr;
register FILE *iop;
{
	register c;
	unsigned ndone, s;

	ndone = 0;
	if (size)
	for (; ndone<count; ndone++) {
		s = size;
		do {
			if ((c = getc(iop)) >= 0)
				*ptr++ = c;
			else
				return(ndone);
		} while (--s);
	}
	return(ndone);
}

fwrite(ptr, size, count, iop)
unsigned size, count;
register char *ptr;
register FILE *iop;
{
	register unsigned s;
	unsigned ndone;

	ndone = 0;
	if (size)
	for (; ndone<count; ndone++) {
		s = size;
		do {
			putc(*ptr++, iop);
		} while (--s);
		if (ferror(iop))
			break;
	}
	return(ndone);
}
ister c;
	unsigned ndone, s;

	ndone = 0;
	if (size)
	for (; ndone<count; ndone++) {
		s = size;
		do {
			if ((c = getc(iop)) >= 0)
				*ptr++ = c;
			else
				return(ndone);
		} while (--s);
	}
	return(ndone);
}

fwrite(ptr, size, count, iop)
unsigned size, count;
register char *ptr;
register FILE *iop;
{
	register unsigned s;
	unsigned ndone;

	ndone = 0;
	if (size)
	for (; ndone<count; ndlib86/stdio/rew.c                                                                                      444     140      12          265  3347424533   7074                                                                                                                                                                                                                                                                                                                                                                      #include	<stdio.h>

rewind(iop)
register struct _iobuf *iop;
{
	fflush(iop);
	lseek(fileno(iop), 0L, 0);
	iop->_cnt = 0;
	iop->_ptr = iop->_base;
	iop->_flag &= ~(_IOERR|_IOEOF);
}
ne<count; ndone++) {
		s = size;
		do {
			if ((c = getc(iop)) >= 0)
				*ptr++ = c;
			else
				return(ndone);
		} while (--s);
	}
	return(ndone);
}

fwrite(ptr, size, count, iop)
unsigned size, count;
register char *ptr;
register FILE *iop;
{
	register unsigned s;
	unsigned ndone;

	/usr/src/local/Machines/8086/lib86/stdio     lib86/stdio/scanf.c                                                                                    444     140      12          635  3347424534   7373                                                                                                                                                                                                                                                                                                                                                                      #include	<stdio.h>

scanf(fmt, args)
char *fmt;
{
	return(_doscan(stdin, fmt, &args));
}

fscanf(iop, fmt, args)
FILE *iop;
char *fmt;
{
	return(_doscan(iop, fmt, &args));
}

sscanf(str, fmt, args)
register char *str;
char *fmt;
{
	FILE _strbuf;

	_strbuf._flag = _IOREAD|_IOSTRG;
	_strbuf._ptr = _strbuf._base = str;
	_strbuf._cnt = 0;
	while (*str++)
		_strbuf._cnt++;
	return(_doscan(&_strbuf, fmt, &args));
}
FILE *iop;
{
	register unsigned s;
	unsigned ndone;

	/usr/src/local/Machines/8086/lib86/stdio     lib86/stdio/setbuf.c                                                                                   444     140      12          441  3347424534   7564                                                                                                                                                                                                                                                                                                                                                                      #include	<stdio.h>

setbuf(iop, buf)
register struct _iobuf *iop;
char *buf;
{
	if (iop->_base != NULL && iop->_flag&_IOMYBUF)
		free(iop->_base);
	iop->_flag &= ~(_IOMYBUF|_IONBF);
	if ((iop->_base = buf) == NULL)
		iop->_flag |= _IONBF;
	else
		iop->_ptr = iop->_base;
	iop->_cnt = 0;
}
._ptr = _strbuf._base = str;
	_strbuf._cnt = 0;
	while (*str++)
		_strbuf._cnt++;
	return(_doscan(&_strbuf, fmt, &args));
}
FILE *iop;
{
	register unsigned s;
	unsigned ndone;

	/usr/src/local/Machines/8086/lib86/stdio     lib86/stdio/sprintf.c                                                                                  444     140      12          362  3347424534   7763                                                                                                                                                                                                                                                                                                                                                                      #include	<stdio.h>

char *sprintf(str, fmt, args)
char *str, *fmt;
{
	struct _iobuf _strbuf;

	_strbuf._flag = _IOWRT+_IOSTRG;
	_strbuf._ptr = str;
	_strbuf._cnt = 32767;
	_doprnt(fmt, &args, &_strbuf);
	putc('\0', &_strbuf);
	return(str);
}
se
		iop->_ptr = iop->_base;
	iop->_cnt = 0;
}
._ptr = _strbuf._base = str;
	_strbuf._cnt = 0;
	while (*str++)
		_strbuf._cnt++;
	return(_doscan(&_strbuf, fmt, &args));
}
FILE *iop;
{
	register unsigned s;
	unsigned ndone;

	/usr/src/local/Machines/8086/lib86/stdio     lib86/stdio/strout.c                                                                                   444     140      12          604  3347424535   7636                                                                                                                                                                                                                                                                                                                                                                      #include	<stdio.h>

_strout(string, count, adjust, file, fillch)
register char *string;
register count;
int adjust;
register struct _iobuf *file;
{
	while (adjust < 0) {
		if (*string=='-' && fillch=='0') {
			putc(*string++, file);
			count--;
		}
		putc(fillch, file);
		adjust++;
	}
	while (--count>=0)
		putc(*string++, file);
	while (adjust) {
		putc(fillch, file);
		adjust--;
	}
}
_strbuf, fmt, &args));
}
FILE *iop;
{
	register unsigned s;
	unsigned ndone;

	/usr/src/local/Machines/8086/lib86/stdio     lib86/stdio/ungetc.c                                                                                   444     140      12          424  3347424535   7563                                                                                                                                                                                                                                                                                                                                                                      #include <stdio.h>

ungetc(c, iop)
register FILE *iop;
{
	if (c == EOF)
		return(-1);
	if ((iop->_flag&_IOREAD)==0 || iop->_ptr <= iop->_base)
		if (iop->_ptr == iop->_base && iop->_cnt==0)
			*iop->_ptr++;
		else
			return(-1);
	iop->_cnt++;
	*--iop->_ptr = c;
	return(0);
}
ust++;
	}
	while (--count>=0)
		putc(*string++, file);
	while (adjust) {
		putc(fillch, file);
		adjust--;
	}
}
_strbuf, fmt, &args));
}
FILE *iop;
{
	register unsigned s;
	unsigned ndone;

	/usr/src/local/Machines/8086/lib86/stdio     lib86/nstdio/Makefile                                                                                  444     140      12          154  3347424543   7747                                                                                                                                                                                                                                                                                                                                                                      all:
	cd ../stdio; make
	cp ../stdio/*.b .
	rm doscan.b doprnt.b gcvt.b
	cc86 -c doscan.c
	cc86 -c doprnt.c
AD)==0 || iop->_ptr <= iop->_base)
		if (iop->_ptr == iop->_base && iop->_cnt==0)
			*iop->_ptr++;
		else
			return(-1);
	iop->_cnt++;
	*--iop->_ptr = c;
	return(0);
}
ust++;
	}
	while (--count>=0)
		putc(*string++, file);
	while (adjust) {
		putc(fillch, file);
		adjust--;
	}
}
_strbuf, fmt, &args));
}
FILE *iop;
{
	register unsigned s;
	unsigned ndone;

/usr/src/local/Machines/8086/lib86/nstdio     lib86/nstdio/doprnt.c                                                                                  444     140      12         6070  3347424544  10005                                                                                                                                                                                                                                                                                                                                                                      # include <stdio.h>

_doprnt(fmt, argp, file)
register char *fmt;
register int *argp;
register FILE *file;
{	register char c, *p, *q;
	register int d, width, ndigit, radix;
	long n;
	int sign, decpt;
	char t[128], digits[10], zfill, rjust, ndfnd;
	char *ecvt(), *fcvt();
	struct {
		short unsigned length;
		char dtype;
		char class;
		char *ptr;
	} desc;
	p = &t[0];
	while (c = *fmt++)
		if (c != '%')
			*p++ = c;
		else {
			if (p != &t[0]) {
				_strout(t, p-t, 0, file);
				p = &t[0];
			}
			rjust = 0;
			ndigit = 0;
			zfill = ' ';
			if (*fmt == '-') {
				rjust++;
				fmt++;
			}
			if (*fmt == '0') {
				zfill = '0';
				fmt++;
			}
			if(*fmt != '*') { 
				width = 0;
				while ((d = *fmt++ - '0') >= 0 && d <= 9)
					width = width*10+d;
			}
			else {
				fmt++;
				d = *fmt++ - '0';
				width = *argp++;
			}
			ndfnd = 0;
			if ((d += '0') == '.') {
			    if(*fmt != '*') {
				ndigit = 0;
				while ((d = *fmt++ - '0') >= 0 && d <= 9) {
					ndfnd++;
					ndigit = ndigit*10+d;
				}
				d += '0';
			    }
			    else {
				fmt++;
				d = *fmt++;
				ndfnd++;
				ndigit = *argp++;
			    }
			}
			switch (d) {
			case 'l':
			case 'L':
				switch(*fmt++) {
				case 'o': goto loct;
				case 'x': goto lhex;
				case 'd': goto ldec;
				case 'u': goto luns;
				default:
					fmt--;
					goto uns;
				}
			case 'o':
			case 'O':
			loct:	radix = 8;
				n = *argp++;
				goto compute;
			case 'X':
			lhex:	radix = 16;
				n = *(long *)argp;
				argp + = 2;
				goto hexcomp;

			case 'x':
				radix = 16;
				n = *argp++;
			hexcomp:
				if (n == 0 && ndigit == 0)
					*p++ = '0';
				for (q = &digits[0]; n != 0;
						n = (n>>4) & 0x0fffffff)
				{
					d = n & 0xF;
					*q++ = d + (d<10?'0':'a'-10);
				}
				while (q > &digits[0])
					*p++ = *--q;
				goto prbuf;


			case 'D':
			ldec:	
				radix = 10;
				n = *(long *)argp;
				if(n < 0){
					n = -n;
					*p++ = '-';
				}
				argp += 2;
				goto compute;

			case 'd':
				radix = 10;
			signed:	if (*argp < 0) {
					*p++ = '-';
					n = -*argp++;
				} else
					n = *argp++;
				goto compute;

			case 'u':
			case 'U':
			luns:
			uns:	n = *argp++;
				radix = 10;
			compute:
				if (n == 0 && ndigit == 0)
					*p++ = '0';
				for (q = &digits[0]; n != 0; n = n/radix)
				{
					d = n%radix; 
/*					d = n - ((n/radix) * radix); */
/*					d = n;
					while(d >= radix) d -= radix;
*/					if(d<0) d += radix;
					*q++ = d + (d<10?'0':'a'-10);
				}
				while (q > &digits[0])
					*p++ = *--q;
				goto prbuf;

			case 'c':
				for (q = (char *)argp++, d = 0; d < sizeof(int); d++)
					if ((*p++ = *q++) == 0)
						p--;
			prbuf:	q = &t[0];
			prstr:	if ((d = width - (p - q)) < 0)
					d = 0;
				if (rjust == 0)
					d = -d;
				_strout(q, p-q, d, file, zfill);
				p = &t[0];
				break;

			case 's':
				if ((q = (char *)*argp++) == 0)
					q = "(null)";
				if ((d = ndigit) == 0)
					d = 32767;
				for (p=q; *p!=0 && --d>=0; p++);
				goto prstr;

			case 'r':
				argp = (int *)*argp;
				fmt = (char *)*argp++;
				break;

			case '%':
				*p++= '%';
				break;
			}
	}
	if (p != &t[0])
		_strout(t, p-t, 0, file);
}
p--;
			prbuf:	q = &t[0];
			prstr:	if ((d = width - (p - q)) < 0)
					d = 0;
				if (rjust == 0)
					d = -d;
				_strout(q, p-q, d, file, zfill);
				p = &t[0];
				break;

			case 's':
				if ((q = (char *)*argp++) == 0)
					q = "(null)";
				if ((d = ndigit) == 0)
					d = 32767;
				for (p=q; *p!=0 && --d>=0; p++);
				goto prstr;

			case 'r':
				argp = (int *)*argp;
				fmt = (char *)*argp++;
				break;

			case '%':
				*p++= '%';
				break;lib86/nstdio/doscan.c                                                                                  444     140      12        10362  3347424544   7765                                                                                                                                                                                                                                                                                                                                                                      #include <stdio.h>
#include	<ctype.h>

#define	SPC	01
#define	STP	02

#define	SHORT	0
#define	REGULAR	1
#define	LONG	2
#define	INT	0
#define	FLOAT	1

char	*_getccl();

char	_sctab[128] = {
	0,0,0,0,0,0,0,0,
	0,SPC,SPC,0,0,0,0,0,
	0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,
	SPC,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,
};

_doscan(iop, fmt, argp)
FILE *iop;
register char *fmt;
register int **argp;
{
	register int ch;
	int nmatch, len, ch1;
	int **ptr, fileended, size;

	nmatch = 0;
	fileended = 0;
	for (;;) switch (ch = *fmt++) {
	case '\0': 
		return (nmatch);
	case '%': 
		if ((ch = *fmt++) == '%')
			goto def;
		ptr = 0;
		if (ch != '*')
			ptr = argp++;
		else
			ch = *fmt++;
		len = 0;
		size = REGULAR;
		while (ch>='0' && ch <='9') {
			len = len*10 + ch - '0';
			ch = *fmt++;
		}
		if (len == 0)
			len = 30000;
		if (ch=='l') {
			ch = *fmt++;
			size = LONG;
		} else if (ch=='h') {
			size = SHORT;
			ch = *fmt++;
		} else if (ch=='[')
			fmt = _getccl(fmt);
		if (isupper(ch)) {
			ch = tolower(ch);
			size = LONG;
		}
		if (ch == '\0')
			return(-1);
		if (_innum(ptr, ch, len, size, iop, &fileended) && ptr)
			nmatch++;
		if (fileended)
			return(nmatch? nmatch: -1);
		break;

	case ' ':
	case '\r':
	case '\n':
	case '\t': 
	while ((ch1 = getc(iop))==' ' || ch1=='\t' || ch1=='\n'|| ch1 =='\r')
			;
		if (ch1 != EOF)
			ungetc(ch1, iop);
		break;

	default: 
	def:
		ch1 = getc(iop);
		if (ch1 != ch) {
			if (ch1==EOF)
				return(-1);
			ungetc(ch1, iop);
			return(nmatch);
		}
	}
}

_innum(ptr, type, len, size, iop, eofptr)
int **ptr, *eofptr;
struct _iobuf *iop;
{
	register char *np;
	char numbuf[64];
int c, base;
	int expseen, scale, negflg, c1, ndigit;
	long lcval;

	if (type=='c' || type=='s' || type=='[')
		return(_instr(ptr? *(char **)ptr: (char *)NULL, type, len, iop, eofptr));
	lcval = 0;
	ndigit = 0;
	scale = INT;
	base = 10;
	if (type=='o')
		base = 8;
	else if (type=='x')
		base = 16;
	np = numbuf;
	expseen = 0;
	negflg = 0;
	while ((c = getc(iop))==' ' || c=='\t' || c=='\n'|| c=='\r');
	if (c=='-') {
		negflg++;
		*np++ = c;
		c = getc(iop);
		len--;
	} else if (c=='+') {
		len--;
		c = getc(iop);
	}
	for ( ; --len>=0; *np++ = c, c = getc(iop)) {


		if ('0'<=c && c<='9'
		 || base==16 && ('a'<=c && c<='f' || 'A'<=c && c<='F')) {
			ndigit++;
			if (base==8)
				lcval <<=3;
			else if (base==10)
			lcval = ((lcval<<2) + lcval)<<1;

			else
				lcval <<= 4;
			c1 = c;
			if ('0'<=c && c<='9')
				c -= '0';
			else if ('a'<=c && c<='f')
				c -= 'a'-10;
			else
				c -= 'A'-10;
			lcval += c;
			c = c1;
			continue;
		} else if (c=='.') {
			if (base!=10 || scale==INT)
				break;
			ndigit++;
			continue;
		} else if ((c=='e'||c=='E') && expseen==0) {
			if (base!=10 || scale==INT || ndigit==0)
				break;
			expseen++;
			*np++ = c;
			c = getc(iop);
			if (c!='+'&&c!='-'&&('0'>c||c>'9'))
				break;
		} else
			break;
	}
	if (negflg)
		lcval = -lcval;
	if (c != EOF) {
		ungetc(c, iop);
		*eofptr = 0;
	} else
		*eofptr = 1;
	if (ptr==NULL || np==numbuf)
		return(0);
	*np++ = 0;
	switch((scale<<4) | size) {

	case (INT<<4) | SHORT:
		**(short **)ptr = lcval;
		break;

	case (INT<<4) | REGULAR:
		**(int **)ptr = lcval;
		break;

	case (INT<<4) | LONG:
		**(long **)ptr = lcval;
		break;
	}
	return(1);
}

_instr(ptr, type, len, iop, eofptr)
register char *ptr;
register struct _iobuf *iop;
int *eofptr;
{
	register ch;
	register char *optr;
	int ignstp;

	*eofptr = 0;
	optr = ptr;
	if (type=='c' && len==30000)
		len = 1;
	ignstp = 0;
	if (type=='s')
		ignstp = SPC;
	while (_sctab[ch = getc(iop)] & ignstp)
		if (ch==EOF)
			break;
	ignstp = SPC;
	if (type=='c')
		ignstp = 0;
	else if (type=='[')
		ignstp = STP;
	while (ch!=EOF && (_sctab[ch]&ignstp)==0) {
		if (ptr)
			*ptr++ = ch;
		if (--len <= 0)
			break;
		ch = getc(iop);
	}
	if (ch != EOF) {
		if (len > 0)
			ungetc(ch, iop);
		*eofptr = 0;
	} else
		*eofptr = 1;
	if (ptr && ptr!=optr) {
		if (type!='c')
			*ptr++ = '\0';
		return(1);
	}
	return(0);
}

char *
_getccl(s)
register char *s;
{
	register c, t;

	t = 0;
	if (*s == '^') {
		t++;
		s++;
	}
	for (c = 0; c < 128; c++)
		if (t)
			_sctab[c] &= ~STP;
		else
			_sctab[c] |= STP;
	while (((c = *s++)&0177) != ']') {
		if (t)
			_sctab[c++] |= STP;
		else
			_sctab[c++] &= ~STP;
		if (c==0)
			return(--s);
	}
	return(s);
}
}
	if (ch != EOF) {
		if (len > 0)
			ungetc(ch, iop);
		*eofptr = 0;
	} else
		*eofptr = 1;
	if (ptr && ptr!=optr) {
		if (type!='c')
			*ptr++ = '\0';
		return(1);
	}
	return(0);
}

char *
_getccl(s)
register char *s;
{
	register c, t;

	t = 0;
	if (*s == '^') {
		t++lib86/sys/Makefile                                                                                     444      30      12          461  3365230305   7233                                                                                                                                                                                                                                                                                                                                                                      .SUFFIXES: .b
.c.b: ; cc86 -c $<

OBJECTS=	handler.b io.b msd2dot0.b sys2.b dos.b rwbyte.b

all:		$(OBJECTS)

msd2dot0.b:	msd2dot0.a86
		a86 msd2dot0

sys2.b:		sys2.c
		cc86 -c sys2.c

dos.b:		dos.a86
		a86 dos

handler.b: handler.a86
	a86 handler

io.b: io.a86
	a86 io

rwbyte.b:	rwbyte.a86
		a86 rwbyte
r = 0;
	} else
		*eofptr = 1;
	if (ptr && ptr!=optr) {
		if (type!='c')
			*ptr++ = '\0';
		return(1);
	}
	return(0);
}

char *
_getccl(s)
register char *s;
{
	regi/usr/src/local/Machines/8086/lib86/sys     lib86/sys/sys2.c                                                                                       644      30      12         4624  3512337372   6674                                                                                                                                                                                                                                                                                                                                                                      #include <sgtty.h>
#include <stdio.h>

/* system call writearounds for MSDOS 2.0
 * Modified March 85 by JSP [see getenv() and system()]
 */

#define	SHORT(XX) (*((short *) XX))
#define	LONG(XX)  (*((long  *) XX))

/* output messsage to console */
prints(p)
 register char *p;
 {	while (*p) write(2, p++, 1);
 }

extern long lseek();

/* UNIX-style getenv:
 * Modified March 85 by JSP to include correct '=' and ' ' detection
 */

char *getenv(name)
 char *name;
 {	static char buf[64];			/* Sigh.		*/
	int i;
	register char *aa, *bb;

	for (i = 0; ; i++) {
	    _genv(i, buf);
	    if (!buf[0]) return 0;
	    for (aa = name, bb = buf; ; aa++, bb++) {
		if (!*aa && (*bb == '=' || *bb == ' ')) {
		   while (*bb == '=' || *bb == ' ') bb++;
		   /* return pos of first non-space char after the '=' */
		   return bb;
		   }
		if (*aa != *bb) break;
		}
	    }
 }

/* Call shell to execute cmd.  If cmd == 0, simply calls an
 * interactive shell.
 * Modified March 85 by JSP to include SWITCHAR sensing
 * Modified July 85 by SAW to do switchar sensing properly.
 */

system(cmd)
 char *cmd;
 {	char cmdbuf[100];
	register char *aa, *bb;
	char *shell, switchar;
	int i;

	if (!(switchar = _swtch()))
	   switchar = '/';			/* default dos switchar */

	aa = cmdbuf + 1; *cmdbuf = 0;

	if (cmd) {
	   *aa++ = switchar;		/* forms -C or /C as necessary */
	   *aa++ = 'C';
	   cmdbuf[0] += 2;
	   for (bb = cmd; *aa = *bb++; aa++) (*cmdbuf)++;
	   }
	*aa++ = '\r'; *aa++ = '\n'; *aa++ = 0;

	if (!(shell = getenv("COMSPEC"))) shell = "COMMAND.COM";

	i = _system(cmdbuf, shell);
	return i;
 }


/* return length of an open file descriptor:
 */

long flength(fid)
 {	long dot, size;
	dot = lseek(fid, 0L, 1);
	size = lseek(fid, 0L, 2);
	lseek(fid, dot, 0);
	return size;
 }

dos_ini()
 {
 }

/* Close all open files.  Called by _exit.
 */

_dos_cl()
 {
 }

int isatty(fid)
 {
	return(-1);
 }

char *sbrk(incr)
  {	char a[1];
	extern char *_memtop;	/* current top of user data */
	register char *p,*q;

	q = _memtop;		/* answer if we succeed */
	if (((int) q) & 1) q++;	/* SAW: malloc seems to want int align	*/

	p = &q[(incr+1)&~1];	/* new top of user data */

	/* allocation succeeds if we didn't wrap around, and if we
	 * are still below stack.
	 */
	if (p >= _memtop && p < &a[-64])
	 { _memtop = p;
	   return(q);
	 }

	return ((char *) -1);
 }

ioctl(fid,request,argp)
 {	register struct _fcb *f;

	prints("***ioctl call ignored\r\n");
	return(-1);
 }
	/* current top of user data */
	register char *p,*q;

	q = _memtop;		/* answer if we succeed */
	if (((int)lib86/sys/dos.a86                                                                                      444     140      12          644  3347424503   6732                                                                                                                                                                                                                                                                                                                                                                      || IBM DOS interface (1/82)

|| int dos(index,arg) -- make DOS call specified by index with argument arg.

	.globl	_dos

	.text
_dos:	push	bp		| entry sequence
	mov	bp,sp
	push	di
	push	si

	movb	ah,*4(bp)	| get index into AH
	mov	dx,*6(bp)	| argument pointer into DX
	int	0x21		| let operating system do what it will
	movb	ah,*0		| zero extend answer to make an int result

	lea	sp,*-4(bp)
	pop	si
	pop	di
	pop	bp
	ret
of user data */
	register char *p,*q;

	q = _memt/usr/src/local/Machines/8086/lib86/sys     lib86/sys/handler.a86                                                                                  444      30      12         7473  3357574135   7577                                                                                                                                                                                                                                                                                                                                                                      || set up C routine as interrupt handler.

|| the following should correspond to <int.h>
||   struct Int {
||	int intnumber;	/* which interrupt we're handling */
||	int oldip,oldcs;  /* what used to be the vector */
||	int ip;		/* points to user's interrupt routine */
||	int arg;	/* argument to user's interrupt routine */
||	int istack[100];  /* interrupt stack and handler routine */
||   }

|| handler(inumber,&foo,f,arg)
||   int inumber;	/* what interrupt we want to handle */
||   struct Int *foo;	/* user-supplied structure that we fill in */
||   int (*f)();	/* interrupt routine */
||   int arg;		/* what interrupt routine should be called with */

inumber = 0		| offsets...
oldip = inumber+2
oldcs = oldip+2
iip = oldcs+2
arg = iip+2
istack = arg+2
estack = istack+198	| could be 200 but who can be sure...

	.text
	.globl	_handler
_handler:
	push	bp		| standard entry sequence
	mov	bp,sp
	push	si
	push	di
	push	es

	mov	bx,*6(bp)	| this is our structure

	lea	di,*istack(bx)	| where interrupt handler will go
	mov	si,#proto	| prototype used for initialization
	mov	cx,#psize+1	| how many words to move
	shr	cx,*1
	repz
	movw			| copy the routine (es = ds by default)
	mov	*istack+proto1(bx),bx	| save away address of structure
	lea	ax,estack(bx)
	mov	*istack+proto2(bx),ax	| save away start of interrupt stack
	mov	*istack+proto3(bx),cs	| save away current cs

	mov	ax,*4(bp)	| get interrupt number
	sal	ax,*1		| convert into byte offset
	sal	ax,*1
	mov	*inumber(bx),ax	| save for later reference
	mov	si,ax		| save as index

	mov	ax,*8(bp)	| save address of user's interrupt routine
	mov	*iip(bx),ax
	mov	ax,*10(bp)	| also save argument
	mov	*arg(bx),ax

	xor	ax,ax		| make es point to interrupt area
	mov	es,ax
	cli			| no interrupts while installing handler!
	seg	es		| get current interrupt ip
	mov	ax,(si)	
	mov	*oldip(bx),ax
	seg	es
	mov	ax,*2(si)
	mov	*oldcs(bx),ax
	lea	ax,*istack(bx)	| offset of our handler stub
	seg	es
	mov	(si),ax
	mov	ax,ds		| structure is in data seg...
	seg	es
	mov	*2(si),ax
	sti

	pop	es
	pop	di
	pop	si
	pop	bp
	ret

|| nohandler(foo)
||   struct Int *foo;	/* previous prepared interrupt structure */

	.globl	_nohandler
	.globl	_nohandl	| C-compiler truncates names
_nohandler:
_nohandl:
	push	bp
	mov	bp,sp
	push	si
	push	di
	push	es

	mov	bx,*4(bp)	| this is our structure
	xor	ax,ax		| make es point to interrupt area
	mov	es,ax
	mov	si,*inumber(bx)

	cli
	mov	ax,*oldip(bx)	| restore old interrupt handler
	seg	es
	mov	(si),ax
	mov	ax,*oldcs(bx)
	seg	es
	mov	*2(si),ax
	sti

	pop	es
	pop	di
	pop	si
	pop	bp
	ret

|| this general-purpose stub is called by tailored interrupt routines
|| so that cs gets set up correctly for c environment.
||	bx -> interrupt structure

stub:	push	ax		| save rest of registers
	push	dx
	push	cx
	push	ds
	push	es

	mov	ax,ss		| set up remainder of segment registers
	mov	ds,ax
	mov	es,ax

	push	*arg(bx)	| get ready to call user's routine
	call	@*iip(bx)	| let user do his thing
	add	sp,*2

	pop	es
	pop	ds
	pop	cx
	pop	dx
	pop	ax
	reti			| back to interrupt routine

	.data
|| prototype interrupt handler...  copied into interrupt structure where it
|| will be able to find the info it needs to call user's interrupt routine.

proto:	push	bx		| save what we need to get started
	push	di
	push	si
	mov	di,ss		| di and si will be used to save old stack info
	mov	si,sp

	mov	bx,cs		| set up stack for c environment
	mov	ss,bx
proto1 = . - proto + 1		| where we should stick address of interrupt struct
	mov	bx,#0		| get address of interrupt struct
proto2 = . - proto + 1
	mov	sp,#0		| and set up to use interrupt stack

proto3 = . - proto + 3		| where c-environments cs will go
	calli	stub,0		| make interseg call to do the rest

	mov	sp,si		| get back the old stack
	mov	ss,di
	pop	si		| restore saved regs
	pop	di
	pop	bx
	iret			| return from interrupt

psize = . - proto		| size of user-specific interrupt code

nvironment
	mov	ss,bx
proto1 = . - proto + 1		| where we should stick address of interrupt struct
	mov	bx,#0		| get address of interrupt struct
proto2 = . - proto + 1
	mov	sp,#0		| and set up to uslib86/sys/io.a86                                                                                       444     140      12          354  3347424504   6553                                                                                                                                                                                                                                                                                                                                                                      || input from port: int inp(port) int port;

	.globl _inp
_inp:	mov	bx,sp
	mov	dx,*2(bx)
	in
	xorb	ah,ah
	ret

|| output to port: outp(port,value) int port,value;

	.globl _outp
_outp:	mov	bx,sp
	mov	dx,*2(bx)
	mov	ax,*4(bx)
	out
	ret

urn from interrupt

psize = . - proto		| size of user-specific interrupt code

nvironment
	mov	ss,bx
proto1 = . - proto + 1		| where we should stick address of interrupt struct
	mov	bx,#0		| get address of interrupt struct
proto2 = ./usr/src/local/Machines/8086/lib86/sys     lib86/sys/msd2dot0.a86                                                                                 666      30      12        14770  3512335505   7627                                                                                                                                                                                                                                                                                                                                                                      | Some global data locations:

	.data
	.globl	__dosax,__dosbx,__doscx,__dosdx
__dosax:	.byte	0,0
__dosbx:	.byte	0,0
__doscx:	.byte	0,0
__dosdx:	.byte	0,0

		.even
		.globl	__pblk
__pblk:		.word	0		| env string seg ptr
pbcmd:		.word	0,0		| cmdbuf ptr
pbfcb1:		.word	0,0		| 1st FCB ptr
pbfcb2:		.word	0,0

	.text
| _exec("path", *paramblk, fnval)

	.globl	__exec
__exec:	push	bp
	mov	bp,sp
	push	di
	push	si

	mov	dx,4(bp)
	mov	bx,6(bp)
	mov	al,8(bp)
	mov	ah,#0x4b
cdos:	int	0x21

| Fall thru to...

| Common error handling code: returns >= 0 in AX iff no err, else returns
|   -(error code):

cyerr:	jb	cyerr1		| An error happened.
	or	ax,ax		| Make sure AX is non-negative
	jge	cyerr2
cyerr1:	neg	ax		| if neg, negate it.
cyerr2:	mov	__dosax,ax
	mov	__dosbx,bx
	mov	__doscx,cx
	mov	__dosdx,dx

	pop	si
	pop	di
	pop	bp
	ret			| return to caller.

| _system(cmdbuf, shell)
	.globl	__system
__system:
	push	bp
	mov	bp,sp
	push	di
	push	si
	push	ds
	push	es
	seg	cs
	mov	sssave,ss
	seg	cs
	mov	spsave,sp

	mov	ax,ds			| Fill in __pblk.
	mov	pbcmd+2,ax
	mov	ax,4(bp)
	mov	pbcmd,ax
	seg	cs
	mov	ax,0x2C			| Use same old env ptr.
	mov	__pblk,ax
	mov	dx,6(bp)		| name of shell.
	mov	bx,#__pblk
	mov	ax,*0
	mov	ah,#0x4B
	int	0x21
	jb	syst5

	mov	ah,#0x4D		| find exit code.
	int	0x21
	jmp	syst6

syst5:	mov	ax,#-1			| error return.
syst6:	cli
	seg	cs
	mov	sp,spsave
	seg	cs
	mov	ss,sssave
	pop	es
	pop	ds
	sti
	pop	si
	pop	di
	pop	bp
	ret

| internal saved stack pointer:
sssave:	.word	0
spsave:	.word	0


| Copy the nth environment variable into *cc++:
| _genv(n, cc)

	.globl	__genv
__genv:	push	bp
	mov	bp,sp
	push	di
	push	es

	seg	cs
	mov	bx,0x2c			| pp ptr to environment.
	mov	es,bx
	mov	di,6(bp)		| target location.
	mov	cx,4(bp)		| count.
	mov	bx,*0
	mov	(di),bl			| default: null string.

genv1:	or	cx,cx			| n = 0?
	je	genv8			| yup, found it.
	dec	cx
	seg	es
	mov	al,(bx)
	or	al,al			| end of env?
	je	genv8			| yup, copy in null string.
genv3:	seg	es
	mov	al,(bx)
	inc	bx			| look for end of string.
	or	al,al
	jne	genv3
	jmp	genv1			| on to next string.

genv8:	seg	es			| copy in string.
	mov	al,(bx)
	inc	bx
	mov	(di),al
	inc	di
	or	al,al
	jne	genv8

	pop	es
	pop	di
	pop	bp
	ret

| _fdate(fid, &dtime, code); short dtime[2]; 
| sets if code = 1, gets if code0.

	.globl	__fdate

__fdate:
	push	bp
	mov	bp,sp
	push	di
	push	si

	mov	bx,4(bp)
	mov	al,8(bp)
	mov	bp,6(bp)
	mov	ah,#0x57
	mov	dx,(bp)
	mov	cx,2(bp)
	int	0x21
	mov	(bp),dx
	mov	2(bp),cx
	jmp	cyerr

| rename(from, to)
	.globl	_rename
_rename:
	push	bp
	mov	bp,sp
	push	di
	push	si

	mov	dx,4(bp)
	mov	di,6(bp)
	mov	ah,0x56
	int	0x21
	jmp	cyerr

| code = _wait()
	.globl	__wait
__wait:	mov	ah,0x4D
	int	0x21
	ret

| _exit(code)
	.globl	__exit
__exit:
	mov	bp,sp
	mov	al,2(bp)
	mov	ah,*0x4C
	int	0x21

| _dir1st("path", attr)
	.globl	__dir1st
__dir1st:
	push	bp
	mov	bp,sp
	push	di
	push	si

	mov	dx,4(bp)
	mov	cx,6(bp)
	mov	ah,#0x4E
	int	0x21
	jmp	cyerr

| _dirnxt()
	.globl	__dirnxt
__dirnxt:
	push	bp
	mov	bp,sp
	push	di
	push	si

	mov	ah,#0x4F
	int	0x21
	jmp	cyerr

| err = _adjblk(seg, newsize); _dosbx = max size on error.
	.globl	__adjblk
__adjblk:
	push	bp
	mov	bp,sp
	push	di
	push	si

	push	es
	mov	ax,4(bp)
	mov	es,ax
	mov	bx,6(bp)
	mov	ah,#0x4A
	int	0x21
	pop	es
	jmp	cyerr

| err = _freblk(seg);
	.globl	__freblk
__freblk:
	push	bp
	mov	bp,sp
	push	di
	push	si

	push	es
	mov	ax,4(bp)
	mov	es,ax
	mov	ah,#0x49
	int	0x21
	pop	es
	jmp	cyerr

| seg = _allblk(size); returns 0 on error (whence see _dosbx for largest
|   available block).

	.globl	__allblk
__allblk:
	push	bp
	mov	bp,sp

	push	es
	mov	bx,4(bp)
	mov	ah,#0x48
	int	0x21
	mov	__dosbx,bx
	jnb	allbl1		| no error.
	mov	ax,#0
allbl1:	pop	es
	pop	bp
	ret

| _getcd(drive, buf); char buf[64];
	.globl	__getcd
__getcd:
	push	bp
	mov	bp,sp
	push	di
	push	si

	mov	dl,4(bp)
	mov	si,6(bp)
	mov	ah,#0x47
	jmp	cdos

| _fdup(fid, newfid)
	.globl	__fdup
__fdup:	push	bp
	mov	bp,sp
	push	di
	push	si

	mov	ah,#0x46
	mov	bx,4(bp)
	mov	cx,6(bp)
	jmp	cdos

| newfid = dup(fid)
	.globl	_dup
_dup:	push	bp
	mov	bp,sp
	push	di
	push	si

	mov	ah,#0x45
	mov	bx,4(bp)
	jmp	cdos

| _ioctl(al, bx, cx, dx)
	.globl	__ioctl
__ioctl:
	push	bp
	mov	bp,sp
	push	di
	push	si

	mov	al,4(bp)
	mov	ah,#0x44
	mov	bx,6(bp)
	mov	cx,8(bp)
	mov	dx,10(bp)
	jmp	cdos

| _fattr(code, "path", mode) - get (code=0) or set (code=1) file attribute
|  If code=0, attr returned in _doscx.
	.globl	__fattr
__fattr:
	push	bp
	mov	bp,sp
	push	di
	push	si

	mov	al,4(bp)
	mov	dx,6(bp)
	mov	cx,8(bp)
	mov	ah,#0x43
	jmp	cdos

| (long) err = lseek(fid, offset, whence); long offset;
	.globl	_lseek
_lseek:
	push	bp
	mov	bp,sp
	push	di
	push	si

	mov	bx,4(bp)
	mov	dx,6(bp)
	mov	cx,8(bp)		| most sig part
	mov	al,10(bp)
	mov	ah,#0x42
	int	0x21
	jnb	lseek2
	mov	dx,#-1			| Make a long negative return.
lseek1:	jmp	cyerr
lseek2:	jmp	cyerr2			| Return file offset in dx, ax.

| unlink("path")
	.globl	_unlink
_unlink:
	push	bp
	mov	bp,sp
	push	di
	push	si

	mov	dx,4(bp)
	mov	ah,#0x41
	jmp	cdos

| write(fid, buf, nbytes)
	.globl	_write
_write:
	push	bp
	mov	bp,sp
	push	di
	push	si

	mov	bx,4(bp)
	mov	dx,6(bp)
	mov	cx,8(bp)
	mov	ah,#0x40
	jmp	cdos

| read(fid, buf, nbytes)
	.globl	_read
_read:
	push	bp
	mov	bp,sp
	push	di
	push	si

	mov	bx,4(bp)
	mov	dx,6(bp)
	mov	cx,8(bp)
	mov	ah,#0x3F
	jmp	cdos

| close(fid)
	.globl	_close
_close:
	push	bp
	mov	bp,sp
	push	di
	push	si

	mov	bx,4(bp)
	mov	ah,#0x3E
	jmp	cdos

| open("path", how)
	.globl	_open
_open:
	push	bp
	mov	bp,sp
	push	di
	push	si

	mov	dx,4(bp)
	mov	al,6(bp)
	mov	ah,#0x3D
	jmp	cdos

| creat("path", attr)
	.globl	_creat
_creat:
	push	bp
	mov	bp,sp
	push	di
	push	si

	mov	dx,4(bp)
|	mov	cx,6(bp)
	mov	cx,#0		| Make things work, for now...
	mov	ah,#0x3C
	jmp	cdos

| chdir("path")
	.globl	_chdir
_chdir:	push	bp
	mov	bp,sp
	push	di
	push	si

	mov	dx,4(bp)
	mov	ah,#0x3B
	jmp	cdos

| rmdir("path")
	.globl	_rmdir
_rmdir:	push	bp
	mov	bp,sp
	push	di
	push	si

	mov	dx,4(bp)
	mov	ah,#0x3A
	jmp	cdos

| mkdir("path")
	.globl	_mkdir
_mkdir:	push	bp
	mov	bp,sp
	push	di
	push	si

	mov	dx,4(bp)
	mov	ah,#0x39
	jmp	cdos

| _resid(code) -- terminate, stay resident.

	.globl	__resid
__resid:
	push	bp
	mov	bp,sp
	push	di
	push	si

	mov	ax,__memtop		| Compute current size, in parags.
	add	ax,#0xF			| Round up.
	mov	cl,*4
	shr	ax,cl
	jne	resid1
	mov	ax,#0x1000		| Full data segment.
resid1:	mov	bx,ax			| size of data seg, in pp.
	mov	dx,ds
	mov	cx,cs			| Add size of code seg.
	sub	ax,cx
	add	dx,ax			| Total memory size.

	mov	al,4(bp)		| exit code
	mov	ah,#0x31
	jmp	cdos

| _swtch() -- fetch & return switch character.

	.globl	__swtch
__swtch:
	mov	ah,#0x37
	mov	al,#0
	int	0x21
	mov	ah,#0
	mov	al,dl
	ret
p
	mov	blib86/sys/rwbyte.a86                                                                                   664      30      12          565  3365230017   7440                                                                                                                                                                                                                                                                                                                                                                      | value = rbyte(seg, offset)

	.globl	_rbyte
_rbyte:	mov	bx,sp
	push	es
	mov	ax,*2(bx)		| segment
	mov	es,ax
	mov	bx,*4(bx)		| offset
	seg	es
	mov	al,(bx)
	pop	es
	mov	ah,#0
	ret

| wbyte(value, seg, offset)

	.globl	_wbyte
_wbyte:	mov	bx,sp
	push	es
	mov	ax,*4(bx)		| seg
	push	ax
	mov	ax,*2(bx)		| value
	mov	bx,*6(bx)		| offset
	pop	es
	seg	es
	mov	(bx),al
	pop	es
	ret
wtch() -- fetch & return switch character.

	.globl	__swtch
__swtch:
	mov	ah,#0x37
	mov	al,#0
	i/usr/src/local/Machines/8086/lib86/sys                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     lib86/sys/io.a86                                                                                       444     140      12          354  3347424504   6553                                                                                                                                                                                                                                                                                                                                                                      || input from port: int inp(port) int port;

	.globl _inp
_inp:	mov	bx,sp
	mov	dx,*2(bx)
	in
	xorb	ah,ah
	ret

|| output to port: outp(port,value) int port,value;

	.globl _outp
_outp:	mov	bx,sp
	mov	dx,*2(bx)
	mov	ax,*4(bx)
	out
	ret

urn from interrupt

psize = . - proto		| size of user-specific interrupt code

nvironment
	mov	ss,bx
proto1 = . - proto + 1		| where we should stick address of interrupt struct
	mov	bx,#0		| get address of interrupt struct
proto2 = ./usr/src/local/Machines/8086/lib86/sys     lib86/sys/msd2dot0.a86                                                                                 666      30      12        14770  3512335505   7627                                                                                                                                                                                                                                                                                                                                                                      | Some global data locations:

	.data
	.globl	__dosax,__dosbx,__doscx,__dosdx
__dosax:	.byte	0,0
__dosbx:	.byte	0,0
__doscx:	.byte	0,0
__dosdx:	.byte	0,0

		.even
		.globl	__pblk
__pblk:		.word	0		| env string seg ptr
pbcmd:		.word	0,0		| cmdbuf ptr
pbfcb1:		.word	0,0		| 1st FCB ptr
pbfcb2:		.word	0,0

	.text
| _exec("path", *paramblk, fnval)

	.globl	__exec
__exec:	push	bp
	mov	bp,sp
	push	di
	push	si

	mov	dx,4(bp)
	mov	bx,6(bp)
	mov	al,8(bp)
	mov	ah,#0x4b
cdos:	int	0x21

| Fall thru to...

| Common error handling code: returns >= 0 in AX iff no err, else returns
|   -(error code):

cyerr:	jb	cyerr1		| An error happened.
	or	ax,ax		| Make sure AX is non-negative
	jge	cyerr2
cyerr1:	neg	ax		| if neg, negate it.
cyerr2:	mov	__dosax,ax
	mov	__dosbx,bx
	mov	__doscx,cx
	mov	__dosdx,dx

	pop	si
	pop	di
	pop	bp
	ret			| return to caller.

| _system(cmdbuf, shell)
	.globl	__system
__system:
	push	bp
	mov	bp,sp
	push	di
	push	si
	push	ds
	push	es
	seg	cs
	mov	sssave,ss
	seg	cs
	mov	spsave,sp

	mov	ax,ds			| Fill in __pblk.
	mov	pbcmd+2,ax
	mov	ax,4(bp)
	mov	pbcmd,ax
	seg	cs
	mov	ax,0x2C			| Use same old env ptr.
	mov	__pblk,ax
	mov	dx,6(bp)		| name of shell.
	mov	bx,#__pblk
	mov	ax,*0
	mov	ah,#0x4B
	int	0x21
	jb	syst5

	mov	ah,#0x4D		| find exit code.
	int	0x21
	jmp	syst6

syst5:	mov	ax,#-1			| error return.
syst6:	cli
	seg	cs
	mov	sp,spsave
	seg	cs
	mov	ss,sssave
	pop	es
	pop	ds
	sti
	pop	si
	pop	di
	pop	bp
	ret

| internal saved stack pointer:
sssave:	.word	0
spsave:	.word	0


| Copy the nth environment variable int