[comp.sources.atari.st] v02i096: sozobon1.2 -- Update to Sozobon C compiler part05/09

koreth@panarthea.ebay.sun.com (Steven Grimm) (10/25/89)

Submitted-by: ncar.ucar.edu!dunike!onecom!wldrdg!hans (Johann Ruegg)
Posting-number: Volume 2, Issue 96
Archive-name: sozobon1.2/part05

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 5 (of 9)."
# Contents:  hcc/FUN.C hcc/G2.C hcc/GEN.C
# Wrapped by koreth@panarthea on Tue Oct 24 18:40:46 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'hcc/FUN.C' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'hcc/FUN.C'\"
else
echo shar: Extracting \"'hcc/FUN.C'\" \(11588 characters\)
sed "s/^X//" >'hcc/FUN.C' <<'END_OF_FILE'
X/* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
X *
X * Permission is granted to anyone to use this software for any purpose
X * on any computer system, and to redistribute it freely, with the
X * following restrictions:
X * 1) No charge may be made other than reasonable charges for reproduction.
X * 2) Modified versions must be clearly marked as such.
X * 3) The authors are not responsible for any harmful consequences
X *    of using this software, even if they result from defects in it.
X *
X *	fun.c
X *
X *	Handle function entry, exit, etc.
X *	Parse statements.
X *	Also, general syntax error recovery strategy.
X */
X
X#include <stdio.h>
X#include "param.h"
X#include "tok.h"
X#include "nodes.h"
X#include "cookie.h"
X
X#if MMCC
Xoverlay "pass2"
X#endif
X
Xextern NODE *cur;
X
Xint level;
XNODE *blktab;
XNODE *labels;
X
Xstruct swittbl {
X	NODEP	caselist;
X	int	deflbl;
X} *curswit;
X
Xint curbrk, curcont;
Xint funtopl, funbotl, funretl, funstrl;
XNODEP funtyp;
Xint maxregs;
Xlong maxlocs;
X
Xint skipon;
X
XNODEP glb_decls();
X
Xextern int oflags[];
X#define debugl oflags['l'-'a']
X#define debugs oflags['s'-'a']
X#define debugv oflags['v'-'a']
X
Xfindtok(x)
X{
X	while (cur->e_token != EOFTOK && cur->e_token != x)
X		fadvnode();
X	if (cur->e_token == EOFTOK)
X		exit(1);
X}
X
Xprogram()
X{
X	extern NODEP symtab[];
X	NODEP last;
X
X	skipon = 0;
Xmore:
X	last = glb_decls();
X	if (cur->e_token == EOFTOK)
X		return;
X	if (last) skipon = 0;	/* saw something valid */
X	if (last && last->n_tptr && last->n_tptr->t_token == '(') {
X	/* possible function definition */
X		if (debugs) {
X			printf("FUN ");
X			put_nnm(last);
X		}
X		out_fstart(last);
X#ifdef OUT_AZ
X		last->e_sc = HERE_SC;
X#else
X		last->e_sc = K_EXTERN;
X#endif
X		fun_start(last->n_tptr);
X		args_blk(last->n_tptr->n_right);
X		sub_block();
X		fun_end();
X		clr_lvl(); /* for args block */
X		goto more;
X	}
X	/* error if get to here */
X	if (last) {
X		error("missing ;");
X		goto more;
X	} else {
X		skip();
X		goto more;
X	}
X}
X
Xfun_start(np)
XNODEP np;
X{
X	NODEP functy();
X
X	funtyp = functy(np);
X	curbrk = curcont = -1;
X	funtopl = new_lbl();
X	funbotl = new_lbl();
X	funretl = new_lbl();
X	switch (funtyp->t_token) {
X	case K_STRUCT:
X	case K_UNION:
X		funstrl = new_lbl();
X		break;
X	default:
X		funstrl = 0;
X	}
X	maxregs = 0;
X	maxlocs = 0;
X	out_br(funbotl);
X	def_lbl(funtopl);
X}
X
Xfun_end()
X{
X	NODEP np;
X
X	if (labels) {
X		for (np = labels; np; np = np->n_next)
X			if (np->c_defined == 0)
X				errorn("undefined label", np);
X		freenode(labels);
X		labels = NULL;
X	}
X	def_lbl(funretl);
X	out_fret(maxregs, funstrl);
X	def_lbl(funbotl);
X	out_fend(maxregs, maxlocs);
X	out_br(funtopl);
X	if (funstrl)
X		out_fs(funstrl, funtyp->t_size);
X}
X
Xskip()
X{
X	if (skipon == 0) {
X		error("syntax (try skipping...)");
X		skipon = 1;
X	}
X	fadvnode();
X}
X
Xblock()
X{
X	int some;
X	int sawsome;
X
X	some = loc_decls();
X	if (cur->e_token == EOFTOK)
X		return;
X	if (some) skipon = 0;
Xmore:
X	sawsome = stmts(); 
X	if (sawsome) skipon = 0;
X	if (cur->e_token == '}') {
X		if (blktab->b_regs > maxregs)
X			maxregs = blktab->b_regs;
X		if (blktab->b_size + blktab->b_tsize > maxlocs)
X			maxlocs = blktab->b_size + blktab->b_tsize;
X		return;
X	}
X
X	/* error if get to here */
X	if (cur->e_token == EOFTOK || is_tykw(cur->e_token))
X		/* get out of block */
X		return;
X	else {
X		skip();
X		goto more;
X	}
X}
X
Xclr_lvl()
X{
X	NODE *bp;
X
X	level--;
X	bp = blktab;
X	blktab = bp->n_next;
X	bp->n_next = NULL;
X	if (debugl && bp->b_syms) {
X		printf("local syms %d", level);
X		printlist(bp->b_syms);
X	}
X#ifdef OUT_AZ
X	xrefl(bp->b_syms);
X#endif
X	freenode(bp->b_syms);
X	if (debugl && bp->b_tags) {
X		printf("local tags %d", level);
X		printlist(bp->b_tags);
X	}
X	freenode(bp->b_tags);
X	freenode(bp);
X}
X
Xeat(c)
X{
X	char *p = "assume X";
X
X	if (cur->e_token == c)
X		fadvnode();
X	else {
X		p[strlen(p) - 1] = c;
X		error(p);
X	}
X}
X
Xsub_block()
X{
X	register NODE *new;
X
X	if (debugs)
X		printf("{ ");
X	eat('{');
X	level++;
X	new = allocnode();
X	new->n_next = blktab;
X	sprintf(new->n_name, "sub{");
X	blktab = new;
X	block();
X	clr_lvl();
X	eat('}');
X	if (debugs)
X		printf("}\n");
X}
X
Xargs_blk(np)
XNODEP np;
X{
X	register NODE *p;
X	register NODE *new;
X	NODE *tp;
X	NODEP llook();
X	long size;
X	int rmask;
X
X	size = 0;
X	rmask = 0;
X	new = allocnode();
X	new->n_next = blktab;
X	sprintf(new->n_name, "arg{");
X	blktab = new;
X	level++;
X	loc_decls();
X	/* make sure all decls were in arg list */
X	for (p=new->b_syms; p != NULL; p = p->n_next)
X		if (llook(np, p) == NULL)
X			errorn("ID not param", p);
X	/* now make any names not mentioned INT */
X	/* and generate offsets and alloc regs */
X	for (p=np; p != NULL; p = p->n_next) {
X		if ((tp=llook(new->b_syms, p)) == NULL) {
X			def_arg(&new->b_syms, p);
X			tp = new->b_syms;
X		}
X		lc_size(&size, &rmask, tp);
X		if (tp->e_sc == K_REGISTER)
X			reg_arg(&rmask, tp);
X		if (debugv) {
X			printf("final o%ld r%d ", tp->e_offs, tp->e_rno);
X			put_nnm(tp);
X			putchar('\n');
X		}
X		out_advice(tp);
X	}
X	new->b_regs = rmask;
X}
X
Xreg_arg(rp, xp)
Xint *rp;
XNODEP xp;
X{
X	if (lc_reg(rp, xp) == 0) {	/* out of regs? */
X		xp->e_sc = K_AUTO;
X		return;
X	}
X	out_argreg(xp);
X}
X
X
Xstmts()
X{
X	int didsome;
X
X	didsome = 0;
X	while (stmt())
X		didsome++;
X	return didsome;
X}
X
Xstmt_bc(brk,cont)
X{
X	int svb, svc;
X
X	svb = curbrk;
X	svc = curcont;
X	curbrk = brk;
X	curcont = cont;
X
X	stmt();
X
X	curbrk = svb;
X	curcont = svc;
X}
X
Xstmt_b(brk)
X{
X	int svb;
X
X	svb = curbrk;
X	curbrk = brk;
X
X	stmt();
X
X	curbrk = svb;
X}
X
X/* do a single statement */
Xstmt()
X{
X	register tok;
X	NODEP np;
X	NODEP getexpr();
X	int i;
X
Xmore:
X	tok = cur->e_token;
X	if (is_stkw(tok)) {
X		if (is_blkst(tok)) {
X			i = blk_stmt();
X		} else if (is_brast(tok)) {
X			i = bra_stmt();
X		} else if (is_lblst(tok)) {
X			i = lbl_stmt();
X		} else {
X			asm_stmt();
X			return 1;
X		}
X		if (i == 0)
X			goto more;
X		return 1;
X	}
X	else if (tok == '{') {
X		sub_block();
X		return 1;
X	} else if (tok == ';') {
X		fadvnode();
X		return 1;
X	}
X	np = getexpr();
X	if (np) {
X		if (cur->e_token == ':') {
X			fadvnode();
X			label(np);
X			goto more;
X		}
X		expr_stmt(np);
X		if (cur->e_token != ';')
X			error("missing ;");
X		else
X			fadvnode();
X		return 1;
X	}
X	return 0;
X}
X
Xexpr_stmt(np)
XNODEP np;
X{
X	if (debugs) {
X		printf("E_STMT ");
X		if (debugs > 1)
X			printnode(np);
X	}
X	do_expr(np, FORSIDE);
X}
X
Xlabel(np)
XNODEP np;
X{
X	register NODEP tp;
X	NODEP llook();
X
X	if (debugs) {
X		printf("LABEL ");
X		if (debugs > 1)
X			printnode(np);
X	}
X	if (np->e_token != ID) {
X		error("weird label");
X		return;
X	}
X	tp = llook(labels, np);
X	if (tp) {
X		freenode(np);
X		if (tp->c_defined) {
X			error("duplicate label");
X			return;
X		}
X	} else {
X		putlist(&labels, np);
X		tp = np;
X		tp->c_casel = new_lbl();
X	}
X	tp->c_defined = 1;
X	def_lbl(tp->c_casel);
X}
X
Xblk_stmt()
X{
X	register tok;
X	int l1, l2, l3;
X	NODEP e1, e2, e3;
X	NODEP opt_expr(), paren_expr(), def_type();
X	struct swittbl locswit, *oldp;
X	extern int lineno;
X	int svline, svline2;
X
X	tok = cur->e_token;
X	fadvnode();
X	switch (tok) {
X	case K_IF:
X		if (debugs)
X			printf("IF ");
X		l1 = new_lbl();
X		e1 = paren_expr();
X		gen_brf(e1, l1);
X		eat(')');
X		stmt();
X		opt_else(l1);
X		return 1;
X	case K_WHILE:
X		if (debugs)
X			printf("WHILE ");
X		e1 = paren_expr();
X		l1 = new_lbl();
X		l2 = new_lbl();
X
X		def_lbl(l1);
X		gen_brf(e1,l2);
X		eat(')');
X
X		stmt_bc(l2,l1);
X
X		out_br(l1);
X		def_lbl(l2);
X		return 1;
X	case K_DO:
X		if (debugs)
X			printf("DO ");
X		l1 = new_lbl();
X		l2 = new_lbl();
X		l3 = new_lbl();
X		def_lbl(l1);
X
X		stmt_bc(l3,l2);
X
X		def_lbl(l2);
X		eat(K_WHILE);
X		e1 = paren_expr();
X		gen_brt(e1, l1);
X		eat(')');
X		eat(';');
X		def_lbl(l3);
X		return 1;
X	case K_FOR:
X		if (debugs)
X			printf("FOR ");
X		l1 = new_lbl();
X		l2 = new_lbl();
X		l3 = new_lbl();
X		eat('(');
X		e1 = opt_expr();
X		expr_stmt(e1);
X		eat(';');
X		def_lbl(l1);
X		e2 = opt_expr();
X		if (e2)
X			gen_brf(e2,l3);
X		eat(';');
X		e3 = opt_expr();	/* save for later */
X		svline = lineno;
X		eat(')');
X
X		stmt_bc(l3,l2);
X
X		def_lbl(l2);
X
X		svline2 = lineno;
X		lineno = svline;
X		expr_stmt(e3);
X		lineno = svline2;
X
X		out_br(l1);
X		def_lbl(l3);
X		return 1;
X	case K_SWITCH:
X		if (debugs)
X			printf("SWITCH ");
X		e1 = paren_expr();
X		l1 = new_lbl();
X		l2 = new_lbl();
X		to_d0(e1, def_type());
X		eat(')');
X
X		out_br(l2);
X		oldp = curswit;
X		curswit = &locswit;
X		locswit.caselist = NULL;
X		locswit.deflbl = -1;
X
X		stmt_b(l1);
X
X		out_br(l1);
X		def_lbl(l2);
X		gen_switch(locswit.caselist, locswit.deflbl);
X		curswit = oldp;
X		def_lbl(l1);
X		return 1;
X	case K_ELSE:
X		error("unexpected 'else'");
X		fadvnode();
X		return 0;
X	}
X}
X
XNODEP
Xparen_expr()
X{
X	NODEP np;
X	NODEP need_expr();
X
X	eat('(');
X	np = need_expr();
X	return np;
X}
X
Xbra_stmt()
X{
X	register tok;
X	NODEP np, tp;
X	NODEP opt_expr(), llook();
X
X	tok = cur->e_token;
X	fadvnode();
X	switch (tok) {
X	case K_BREAK:
X		if (debugs)
X			printf("BRK");
X		eat(';');
X		out_br(curbrk);
X		return 1;
X	case K_CONTINUE:
X		if (debugs)
X			printf("CONT ");
X		eat(';');
X		out_br(curcont);
X		return 1;
X	case K_RETURN:
X		if (debugs)
X			printf("RETURN ");
X		np = opt_expr();
X		if (np) {
X			if (funstrl)
X				ret_stru(np);
X			else
X				to_d0(np, funtyp);
X		}
X		out_br(funretl);
X		eat(';');
X		return 1;
X	case K_GOTO:
X		if (debugs)
X			printf("GOTO ");
X		np = cur;  advnode();
X		if (np->e_token != ID)
X			error("bad goto");
X		else {
X			tp = llook(labels, np);
X			if (tp) {
X				freenode(np);	
X			} else {
X				tp = np;
X				putlist(&labels, tp);
X				tp->c_casel = new_lbl();
X			}
X			out_br(tp->c_casel);
X		}
X		eat(';');
X		return 1;
X	}
X}
X
Xlbl_stmt()
X{
X	register tok;
X	NODEP need_expr(), np;
X	int l1, i;
X
X	l1 = new_lbl();
X	tok = cur->e_token;
Xagain:
X	fadvnode();
X	switch (tok) {
X	case K_CASE:
X		if (debugs)
X			printf("CASE ");
X		np = need_expr();
X		i = conxval(np);
X		if (curswit)
X			add_case(i,l1);
X		else
X			error("'case' outside switch");
X		eat(':');
X		break;
X	case K_DEFAULT:
X		if (debugs)
X			printf("DEFAULT ");
X		if (curswit) {
X			if (curswit->deflbl >= 0)
X				error("multiple 'default'");
X			curswit->deflbl = l1;
X		} else
X			error("'default' outside switch");
X		eat(':');
X	}
X	tok = cur->e_token;	/* lookahead for more cases */
X	if (tok == K_CASE || tok == K_DEFAULT)
X		goto again;
X	def_lbl(l1);
X	return 0;
X}
X
Xasm_stmt()
X{
X	NODEP np, getexpr();
X
X	fadvnode();
X	np = getexpr();
X	if (np == NULL || np->e_token != SCON) {
X		error("bad asm() func");
X	} else {
X		out_asm(np);
X		freenode(np);
X	}
X	eat(';');
X}
X
XNODEP
Xopt_expr()
X{
X	NODE *np, *getexpr();
X
X	np = getexpr();
X	if (np) {
X		if (debugs) {
X			printf("OXPR ");
X			if (debugs > 1)
X				printnode(np);
X		}
X	}
X	return np;
X}
X
XNODEP
Xneed_expr()
X{
X	NODE *np, *getexpr();
X
X	np = getexpr();
X	if (np) {
X		if (debugs) {
X			printf("NXPR ");
X			if (debugs > 1)
X				printnode(np);
X		}
X	} else
X		error("need expr");
X	return np;
X}
X
Xopt_else(l1)
X{
X	int l2;
X
X	if (cur->e_token == K_ELSE) {
X		if (debugs)
X			printf("ELSE ");
X		fadvnode();
X		l2 = new_lbl();
X		out_br(l2);
X		def_lbl(l1);
X		stmt();
X		def_lbl(l2);
X	} else
X		def_lbl(l1);
X}
X
Xadd_case(val, lbl)
X{
X	NODEP np, last, p;
X
X	np = allocnode();
X	np->c_casev = val;
X	np->c_casel = lbl;
X	sprintf(np->n_name, "%d:%d", val, lbl);
X
X	last = NULL;
X	for (p = curswit->caselist; p; last=p, p=p->n_next)
X		if (p->c_casev == val) {
X			error("duplicate case");
X			return;
X		} else if (p->c_casev > val)
X			break;
X	if (last) {
X		last->n_next = np;
X		np->n_next = p;
X	} else {
X		curswit->caselist = np;
X		np->n_next = p;
X	}
X	if (debugs) {
X		printf("CASELIST\n");
X		printnode(curswit->caselist);
X	}
X}
X
Xto_d0(np, typ)
XNODEP np, typ;
X{
X	NODEP tp;
X
X	tp = allocnode();
X	tp->e_token = TCONV;
X	tp->n_tptr = typ;
X	tp->n_flags |= N_COPYT;
X	tp->n_left = np;
X	tp->e_type = E_UNARY;
X	strcpy(tp->n_name, "r cast");
X
X	do_expr(tp, IND0);
X}
X
Xret_stru(np)
XNODEP np;
X{
X	p2_expr(&np);
X	if (same_type(np->n_tptr, funtyp) == 0) {
X		error("bad struct return type");
X		return;
X	}
X	genx(np, RETSTRU);	
X}
END_OF_FILE
if test 11588 -ne `wc -c <'hcc/FUN.C'`; then
    echo shar: \"'hcc/FUN.C'\" unpacked with wrong size!
fi
# end of 'hcc/FUN.C'
fi
if test -f 'hcc/G2.C' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'hcc/G2.C'\"
else
echo shar: Extracting \"'hcc/G2.C'\" \(11766 characters\)
sed "s/^X//" >'hcc/G2.C' <<'END_OF_FILE'
X/* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
X *
X * Permission is granted to anyone to use this software for any purpose
X * on any computer system, and to redistribute it freely, with the
X * following restrictions:
X * 1) No charge may be made other than reasonable charges for reproduction.
X * 2) Modified versions must be clearly marked as such.
X * 3) The authors are not responsible for any harmful consequences
X *    of using this software, even if they result from defects in it.
X *
X *	g2.c
X *
X *	Generate code for binary nodes.
X */
X
X#include <stdio.h>
X#include "param.h"
X#include "nodes.h"
X#include "flags.h"
X#include "bstok.h"
X#include "gen.h"
X#include "ops.h"
X
X#define FAIL	0
X#define OKAY	1
X
Xextern int cookflags[];
X
X#define isimmed(np)	((np)->g_flags & IMMEDID)
X#define isareg(np)	((np)->g_token == REGVAR && (np)->g_rno >= AREG)
X
Xstruct bop {
X	char *s_op, *u_op;
X	int opflags;
X} bops[] = {
X	{"muls",	"mulu",	EOPD |ASSOC},
X	{"divs",	"divu",	EOPD},
X	{"divs",	"divu", EOPD},
X	{"and",		"and",	EOPD|DOPE|IOPE |ASSOC},
X	{"or",		"or",	EOPD|DOPE|IOPE |ASSOC},
X	{"eor",		"eor",	DOPE|IOPE |ASSOC},
X	{"add",		"add",	EOPD|DOPE|EOPA|IOPE|AOPA|AOPD |ASSOC},
X	{"sub",		"sub",	EOPD|DOPE|EOPA|IOPE|AOPA|AOPD},
X	{"asl",		"lsl",	DOPD|QOPD|ONEOPM},
X	{"asr",		"lsr",	DOPD|QOPD|ONEOPM},
X};
X
Xchar *tstnm[] = {
X	"lt",		/* < */
X	"gt",		/* > */
X	"le",		/* <= */
X	"ge",		/* >= */
X	"eq",		/* == */
X	"ne",		/* != */
X};
X
Xint tstx[] = {
X	B_LT, B_GT, B_LE, B_GE, B_EQ, B_NE
X};
X
Xchar *utstnm[] = {
X	"cs",		/* < */
X	"hi",		/* > */
X	"ls",		/* <= */
X	"cc",		/* >= */
X	"eq",		/* == */
X	"ne",		/* != */
X};
X
Xint utstx[] = {
X	B_ULT, B_UGT, B_ULE, B_UGE, B_EQ, B_NE
X};
X
Xb_eval(np, cookie)
Xregister NODEP np;
X{
X	NODEP lp = np->n_left, rp = np->n_right;
X	NODEP tp;
X	int lcook = FORADR, rcook = FORADR;
X
X	switch (np->g_token) {		/* special cookies */
X	case DOUBLE '&':
X	case DOUBLE '|':
X		lcook = rcook = FORCC;
X		break;
X	case '?':
X		lcook = FORCC;
X		break;
X	case '(':
X		rcook = FORPUSH;
X		break;
X	case ',':
X		if (np->g_offs)	/* function args */
X			lcook = rcook = FORPUSH;
X		else {
X			lcook = FORSIDE;
X			rcook = cookie;
X		}
X		break;
X	case '=':
X		rcook = FORIMA;
X		break;
X	case '+':
X	case '-':
X		tp = rp;
X		while (tp->g_token == TCONV && tp->g_ty != ET_F)
X			tp = tp->n_left;
X		if (tp->g_token == ICON)
X			lcook = FORIMA;
X		break;		
X	}
X
X	if (np->g_type == EV_LR) {
X		if (eval(lp,lcook) == FAIL)
X			return FAIL;
X		freetmps(lp);
X		if (eval(rp,rcook) == FAIL)
X			return FAIL;
X		freetmps(rp);
X	} else if (np->g_type == EV_RL) {
X		if (eval(rp,rcook) == FAIL)
X			return FAIL;
X		freetmps(rp);
X		if (eval(lp,lcook) == FAIL)
X			return FAIL;
X		freetmps(lp);
X	} else {	/* EV_LRSEP */
X		if (eval(lp,lcook) == FAIL)
X			return FAIL;
X		freetmps(lp);
X		free1(NULL, lp);
X		if (eval(rp,rcook) == FAIL)
X			return FAIL;
X		freetmps(rp);
X	}
X	return b_sube(np, cookflags[cookie]);
X}
X
Xb_sube(np, flags)
Xregister NODEP np;
X{
X	NODEP lp = np->n_left, rp = np->n_right;
X	register int i, r;
X	int argsize;
X	char buf[40];
X	
X	if (isassign(np->g_token))
X		return as_eval(np);
X
X	switch (np->g_token) {
X	case '=':
X		if (specasn(np, flags) || strasn(np))
X			return OKAY;
X		inherit(np);
X		addcode(np, "\tmove.S\t>A,<A\n");
X		return OKAY;
X
X	case '(':
X		argsize = argmod(rp);
X		free1(NULL,rp);
X		if (np->g_ty == ET_A) {		/* struct returned */
X			frc_ral(AREG);
X			indir(np, AREG);
X		} else {
X			frc_ral(0);
X			retreg(np, 0);
X		}
X		sprintf(buf, "\tjsr\t<A\n\tadd.w\t#%d,sp\n", argsize);
X		addcode(np, buf);
X		return OKAY;
X
X	case ',':
X		if (np->g_offs == 0)	/* normal ',' */
X			rinherit(np);
X		return OKAY;
X
X	case DOUBLE '&':
X		free1(NULL, rp);
X		r = ralloc(0);
X		retreg(np, r);
X		holdlbls(np);
X		np->g_betw = iscc(lp) ? "<FL1\n" :
X			"<Q\tbeq\tL1\n";
X		addcode(np, iscc(rp) ? ">FL1\n" :
X			">Q\tbeq\tL1\n");
X		addcode(np, "\tmoveq\t#1,A\n");
X		addcode(np, "\tbra\tL2\nL1:\tclr\tA\nL2:\n");
X		return OKAY;
X
X	case DOUBLE '|':
X		free1(NULL, rp);
X		r = ralloc(0);
X		retreg(np, r);
X		holdlbls(np);
X		np->g_betw = iscc(lp) ? "<TL1\n" :
X			"<Q\tbne\tL1\n";
X		addcode(np, iscc(rp) ? ">TL1\n" :
X			">Q\tbne\tL1\n");
X		addcode(np, "\tclr\tA\n");
X		addcode(np, "\tbra\tL2\nL1:\tmoveq\t#1,A\nL2:\n");
X		return OKAY;
X
X	case '?':
X		rinherit(np);
X		rinhlbls(np);
X		np->g_betw = iscc(lp) ? "<FL1\n" : "<Q\tbeq\tL1\n";
X		return OKAY;
X
X	case ':':
X		free1(NULL, rp);
X		r = ralloc(0);
X		retreg(np, r);
X		holdlbls(np);
X		np->g_betw = same_a(np, lp) ?
X			"\tbra\tL2\nL1:\n"  :
X			"\tmove.S\t<A,A\n\tbra\tL2\nL1:\n";
X		if (!same_a(np, rp))
X			addcode(np, "\tmove.S\t>A,A\n");
X		addcode(np, "L2:\n");
X		return OKAY;
X
X	case '<':
X		i = 0;  goto dotst;
X	case '>':
X		i = 1;  goto dotst;
X	case LTEQ:
X		i = 2;  goto dotst;
X	case GTEQ:
X		i = 3;  goto dotst;
X	case DOUBLE '=':
X		i = 4;  goto dotst;
X	case NOTEQ:
X		i = 5;
Xdotst:
X		fix_cmp(np, EOPD|EOPA|IOPE|AOPA|AOPD);
X		if (flags & CC_OK) {
X			np->g_token = (lp->g_ty == ET_U ?
X			utstx[i] : tstx[i]) + BR_TOK;
X		} else {
X			strcpy(np->n_name, lp->g_ty == ET_U ?
X			utstnm[i] : tstnm[i]);
X			r = ralloc(0);
X			retreg(np, r);
X			addcode(np, "\tsN\tA\n\tand.w\t#1,A\n");
X		}
X		return OKAY;
X
X	case '*':
X		return fixmul(np, bops[0].opflags);
X	case '/':
X		return fixdiv(np, bops[1].opflags);
X	case '%':
X		return fixmod(np, bops[2].opflags);
X	case '&':	i = 3;  goto doop;
X	case '|':	i = 4;  goto doop;
X	case '^':	i = 5;	goto doop;
X	case '+':
X		if (optadd(np, flags, 1))
X			return OKAY;
X			i = 6;  goto doop;
X	case '-':
X		if (optadd(np, flags, -1))
X			return OKAY;
X			i = 7;  goto doop;
X	case DOUBLE '<':i = 8;  goto doop;
X	case DOUBLE '>':i = 9;
Xdoop:
X		strcpy(np->n_name, np->g_ty == ET_U ?
X			bops[i].u_op : bops[i].s_op);
X		r = fix2ops(np, bops[i].opflags);
X		cc_hack(np);
X		return r;
X	case FIELDAS:
X		return fldasn(np, flags);
X	default:
X		printf("Weird b_eval %s ", np->n_name);
X		return FAIL;
X	}
X}
X
Xas_eval(np)
Xregister NODEP np;
X{
X	NODEP rp = np->n_right;
X	register int op, i, r;
X
X	rp = np->n_right;
X
X	op = np->g_token;
X	op -= ASSIGN 0;
X	switch (op) {
X
X	/* these get unfolded now */
X	case '*':
X			return fixamul(np, bops[0].opflags);
X	case '/':
X			return fixadiv(np, bops[1].opflags);
X	case '%':
X			return fixamod(np, bops[2].opflags);
X	case '&':	i = 3;  goto doop;
X	case '|':	i = 4;  goto doop;
X	case '^':	i = 5;	goto doop;
X	case '+':	i = 6;  goto doop;
X	case '-':	i = 7;  goto doop;
X	case DOUBLE '<':i = 8;  goto doop;
X	case DOUBLE '>':i = 9;
Xdoop:
X		strcpy(np->n_name, np->g_ty == ET_U ?
X			bops[i].u_op : bops[i].s_op);
X		r = fix_asn(np, bops[i].opflags);
X		cc_hack(np);
X		return r;
X
X	default:
X		printf("Weird as_eval %s ", np->n_name);
X		return FAIL;
X	}
X}
X
Xrinherit(np)
Xregister NODEP np;
X{
X	register NODEP rp = np->n_right;
X
X	np->g_token = rp->g_token;
X	np->g_offs = rp->g_offs;
X	np->g_rno = rp->g_rno;
X	np->g_flags |= RCHILDNM | (rp->g_flags & IMMEDID);
X}
X
Xargmod(np)
Xregister NODEP np;
X{
X	int size = 0;
X
X	if (np->g_token == ',') {
X		np->g_type = EV_RL;
X		size += argmod(np->n_right);
X		size += argmod(np->n_left);
X		return size;
X	}
X	size += onearg(np);
X	return size;
X}
X
Xonearg(np)
Xregister NODEP np;
X{
X	int rv;
X
X	/* hack small ICON */
X	if (np->g_sz == 1 && np->g_token == ICON)
X		np->g_sz = 2;
X	/* hack push of 0 */
X	if (np->g_token == ICON && np->g_offs == 0 && isimmed(np)) {
X		addcode(np, "\tclr.S\t-(sp)\n");
X		return (int)np->g_sz;
X	}
X	/* hack push of #OREG */
X	if (np->g_token == OREG && isimmed(np)) {
X		np->g_flags &= ~IMMEDID;
X		addcode(np, "\tpea\tA\n");
X		return 4;
X	}
X
X	if (np->g_ty == ET_A) {
X		rv = strpush(np);
X		freetmps(np);
X		free1(NULL,np);
X		return rv;
X	}
X
X	switch (np->g_sz) {
X	case 1:
X		addcode(np, (np->g_ty == ET_U) ?
X		   "\tclr.w\td0\n\tmove.b\tA,d0\n\tmove.w\td0,-(sp)\n" :
X		   "\tmove.b\tA,d0\n\text.w\td0\n\tmove.w\td0,-(sp)\n" );
X		return 2;
X	case 2:
X		addcode(np,
X		   "\tmove.w\tA,-(sp)\n");
X		return 2;
X	default:
X		addcode(np,
X		   "\tmove.l\tA,-(sp)\n");
X		return 4;
X	}
X}
X
X#define MAXD DRV_START
X#define MAXA (ARV_START-AREG)
X#define NEEDALL	(MAXA*AREG + MAXD)
X
Xorder(np)
Xregister NODEP np;
X{
X	int l, r;
X
X	switch (np->g_type) {
X	case E_BIN:
X		order(np->n_right);
X		r = np->n_right->g_needs;
X	case E_UNARY:
X		order(np->n_left);
X		l = np->n_left->g_needs;
X		break;
X	default:	/* leaf */
X		np->g_type = EV_NONE;
X		np->g_needs = 0;
X		return;
X	}
X
X	if (np->g_type == E_UNARY) {
X		switch (np->g_token) {
X		case STAR:
X		case UNARY '&':
X			np->g_needs = merge(l,AREG);
X			break;
X		case '(':
X			np->g_needs = NEEDALL;
X			break;
X		case POSTINC:
X		case POSTDEC:
X		case '!':
X		case TCONV:
X			np->g_needs = merge(l,1);
X			break;
X		case '.':
X			if (np->g_fldw) {
X				np->g_needs = merge(l,1);
X				break;
X			}
X			/* else fall through */
X		default:
X			np->g_needs = l;
X		}
X		np->g_type = EV_LEFT;
X		return;
X	}
X
X/* at this point, have binary node */
X
X	switch (np->g_token) {
X	case DOUBLE '&':
X	case DOUBLE '|':
X	case '?':
X	case ':':
X		/* always left-right, no extra regs */
X		np->g_type = EV_LRSEP;
X		np->g_needs = merge(1, merge(l,r));
X		return;
X	case ',':
X		np->g_needs = merge(l, r);
X		np->g_type = EV_LRSEP;
X		return;
X	case '(':
X		np->g_needs = NEEDALL;
X		break;
X	case '^':
X	case DOUBLE '<':
X	case DOUBLE '>':
X	case ASSIGN '/':
X	case ASSIGN DOUBLE '<':
X	case ASSIGN DOUBLE '>':
X		np->g_needs = merge(bin(l,r), 2);
X		break;
X	default:
X		if (isassign(np->g_token) || np->g_token == '=')
X			np->g_needs = merge(rbin(l,r), 1);
X		else
X			np->g_needs = merge(bin(l,r), 1);
X	}
X
X	if (isassign(np->g_token) || np->g_token == '=')
X		np->g_type = EV_RL;	/* NO PUSHER's on L */
X	else
X		np->g_type = worst_1st(l, r);
X	flag_saves(np, l, r);
X}
X
Xflag_saves(np, l, r)
XNODEP np;
X{
X	NODEP *cpp;
X	register int other;
X
X	if (np->g_type == EV_LR) {
X		cpp = &np->n_left;
X		other = r;
X	} else {
X		cpp = &np->n_right;
X		other = l;
X	}
X	if ((other & 7) >= MAXD || (other/AREG) >= MAXA)
X		addtmp(np, cpp);
X}
X
Xaddtmp(np, cpp)
XNODEP np, *cpp;
X{
X	NODEP cp, tp;
X	NODEP copyone();
X
X	cp = *cpp;
X	tp = copyone(cp);
X	tp->n_left = cp;
X	*cpp = tp;
X	tp->g_token = PUSHER;
X	strcpy(tp->n_name, "pusher");
X	tp->g_type = EV_LEFT;
X}
X	
Xworst_1st(l,r)
X{
X	int ld, rd;
X
X	ld = l & 7;
X	rd = r & 7;
X	if (rd > ld)
X		return EV_RL;
X	if (r > l)
X		return EV_RL;
X	return EV_LR;
X}
X
Xbin(l,r)
X{
X	int la, ra, na;
X	int ld, rd, nd;
X	int rfirst;
X
X	la = l/AREG;
X	ra = r/AREG;
X	ld = l & 7;
X	rd = r & 7;
X	rfirst = (ra > la) || (rd > ld);
X	return rfirst ? rbin(l,r) : rbin(r,l);
X}
X
Xrbin(last,first)
X{
X	int la, fa, na;
X	int ld, fd, nd;
X
X	la = last/AREG;
X	fa = first/AREG;
X	ld = last & 7;
X	fd = first & 7;
X	na = fa > la ? fa : la + (fa ? 1 : 0);
X	if (na > MAXA)
X		na = MAXA;
X	nd = fd > ld ? fd : ld + (fd ? 1 : 0);
X	if (nd > MAXD)
X		nd = MAXD;
X	return na*AREG + nd;
X}
X
Xmerge(need, have)
X{
X	int na, nd, ha, hd, xa, xd;
X
X	na = need/AREG;
X	ha = have/AREG;
X	nd = need & 7;
X	hd = have & 7;
X	xa = na > ha ? na : ha;
X	xd = nd > hd ? nd : hd;
X	return xa*AREG + xd;
X}
X
Xholdlbls(np)
XNODEP np;
X{
X	np->g_bsize = new_lbl();
X	new_lbl();
X}
X
Xrinhlbls(np)
XNODEP np;
X{
X	np->g_bsize = np->n_right->g_bsize;
X}
X
X/* limited version of same address check
X	assume one of these is a temp register */
Xsame_a(p1, p2)
XNODEP p1, p2;
X{
X	if (p1->g_token != p2->g_token)
X		return 0;
X	if (p1->g_rno != p2->g_rno)
X		return 0;
X	return 1;
X}
X
Xoptadd(np, flags, sign)
Xregister NODEP np;
X{
X	NODEP lp = np->n_left, rp = np->n_right;
X
X	if (rp->g_token != ICON)
X		return 0;
X	if (isimmed(lp) && isimmed(rp)) {
X		switch (lp->g_token) {
X		case OREG:
X		case ONAME:
X			inherit(np);
X			if (sign == -1)
X				rp->g_offs = -rp->g_offs;
X			np->g_offs += rp->g_offs;
X
X			if ((flags & IMMA_OK) == 0)
X				imm_oreg(np);
X			return 1;
X		default:
X			return 0;
X		}
X	}
X	return 0;
X}
X
Xiscc(np)
XNODEP np;
X{
X	return (np->g_token >= BR_TOK) || (np->g_flags & SIDE_CC);
X}
X
Xcc_hack(np)
XNODEP np;
X{
X	if (isareg(np))
X		return;
X	np->g_flags |= SIDE_CC;
X}
X
Xcctok(np)
XNODEP np;
X{
X	if (np->g_token >= BR_TOK)
X		return np->g_token - BR_TOK;
X	if (np->g_flags & SIDE_CC)
X		return B_NE;
X	printf("cctok error ");
X	return 0;
X}
END_OF_FILE
if test 11766 -ne `wc -c <'hcc/G2.C'`; then
    echo shar: \"'hcc/G2.C'\" unpacked with wrong size!
fi
# end of 'hcc/G2.C'
fi
if test -f 'hcc/GEN.C' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'hcc/GEN.C'\"
else
echo shar: Extracting \"'hcc/GEN.C'\" \(11959 characters\)
sed "s/^X//" >'hcc/GEN.C' <<'END_OF_FILE'
X/* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
X *
X * Permission is granted to anyone to use this software for any purpose
X * on any computer system, and to redistribute it freely, with the
X * following restrictions:
X * 1) No charge may be made other than reasonable charges for reproduction.
X * 2) Modified versions must be clearly marked as such.
X * 3) The authors are not responsible for any harmful consequences
X *    of using this software, even if they result from defects in it.
X *
X *	gen.c
X *
X *	Generate code.
X *	Includes main routine and code generation for unary nodes
X *	and leafs.
X */
X
X#include <stdio.h>
X#include "param.h"
X#include "bstok.h"
X#include "tytok.h"
X#include "flags.h"
X#include "nodes.h"
X#include "gen.h"
X
XNODEP strsave;
Xint cctest;
Xstatic int reserve;
Xstatic int tmpused;
X
Xextern xflags[];
X#define debug xflags['g'-'a']
X
X#define FAIL	0
X#define OKAY	1
X
X#define isimmed(np)	((np)->g_flags & IMMEDID)
X#define isareg(np)	((np)->g_token == REGVAR && (np)->g_rno >= AREG)
X#define isdreg(np)	((np)->g_token == REGVAR && (np)->g_rno < AREG)
X#define istdreg(np)	((np)->g_token == REGVAR && (np)->g_rno < DRV_START)
X
Xint cookflags[] = {
X	0,
X	NOVAL_OK|CC_OK|IMMA_OK,		/* FORSIDE */
X	IMMA_OK,			/* FORPUSH */
X	CC_OK,				/* FORCC */
X	IMMA_OK,			/* FORIMA */
X	0,				/* FORADR */
X	IMMA_OK,			/* FORINIT */
X	0,				/* IND0 */
X	0,				/* RETSTRU */
X};
X
Xgenx(np, cookie)
Xregister NODEP np;
X{
X	extern nmerrors;
X	int rv;
X	extern NODE *blktab;
X
X	if (np == NULL) return;
X	if (nmerrors)
X		goto bad;
X	if (debug) {
X		printf("GEN enter");
X		printnode(np);
X	}
X
X	untype(np);
X	if (debug>1) {
X		printf("after UNTYPE");
X		printnode(np);
X	}
X
X	tmpused = 0;
X	gunk(np);
X	if (tmpused && tmpused > blktab->b_tsize)
X		blktab->b_tsize = tmpused;
X	if (debug > 1) {
X		printf("after gunk");
X		printnode(np);
X	}
X	order(np);
X
X	reserve = 0;
X	rv = eval(np, cookie);
X	if (rv == OKAY && debug) {
X		printf("GEN exit");
X		codeprint(np);
X	}
X	if (rv == OKAY)
X		rv = cookmon(np, cookie);
X	else
X		error("couldnt eval node");
X	freenode(np);
X	return rv;
Xbad:
X	freenode(np);
X	return FAIL;
X}
X
Xeval(np, cookie)
Xregister NODEP np;
X{
X	int rv;
X
X	np->g_r1 = np->g_r2 = -1;
X
X	if (np == NULL) return FAIL;
X
X	switch (np->g_type) {
X
X	default:
X		rv = b_eval(np, cookie);
X		/* already did freetmps */
X		free1(np, np->n_left);
X		free1(np, np->n_right);
X		break;
X
X	case EV_LEFT:
X		rv = u_eval(np, cookie);
X		freetmps(np);
X		free1(np, np->n_left);
X		break;
X
X	case EV_NONE:
X		rv = l_eval(np);
X		break;
X	}
X	return rv;
X}
X
Xu_eval(np, cookie)
Xregister NODEP np;
X{
X	int subcook = FORADR;
X
X	switch (np->g_token) {
X	case STAR:
X		subcook = FORIMA;
X		break;
X	case '!':
X		subcook = FORCC;
X		break;
X	}
X
X	if (eval(np->n_left, subcook) == FAIL)
X		return FAIL;
X	return u_sube(np, cookflags[cookie]);
X}
X
Xu_sube(np, flags)
Xregister NODEP np;
X{
X	register NODEP lp = np->n_left;
X	long offs;
X	int i;
X
X	switch (np->g_token) {
X	case '.':
X		if (np->g_fldw)
X			return fldget(np, flags);
X		offs = np->g_offs;
X		inherit(np);
X		np->g_offs += offs;
X		return OKAY;
X	case STAR:
X		if (isimmed(lp)) {
X			inherit(np);
X			np->g_flags &= ~IMMEDID;
X		} else if (isareg(lp)) {
X			indir(np, lp->g_rno);
X		} else {	/* NEED A temp */
X			if (lp->g_token == OREG && istemp(lp->g_rno))
X				i = lp->g_rno;
X			else
X				i = ralloc(AREG);
X			addcode(np, "\tmove.l\t<A,R0\n");
X			indir(np, i);
X		}
X		return OKAY;
X	case UNARY '&':
X		if (isimmed(lp))
X			warn("& ignored");
X		else if (lp->g_token == REGVAR)
X			return FAIL;
X		inherit(np);
X		np->g_flags |= IMMEDID;
X		if ((flags & IMMA_OK) == 0)
X			imm_oreg(np);
X		return OKAY;
X	case '~':
X		utemp(np);
X		addcode(np, "\tnot.S\tA\n");
X		cc_hack(np);
X		return OKAY;
X	case UNARY '-':
X		utemp(np);
X		addcode(np, "\tneg.S\tA\n");
X		cc_hack(np);
X		return OKAY;
X	case TCONV:
X		castgen(np);
X		return OKAY;
X	case PUSHER:	/* must not be on left of assign or asn-op */
X		if ((lp->g_token != OREG && lp->g_token != REGVAR) ||
X			istemp(lp->g_rno) == 0) {
X			inherit(np);
X			return OKAY;
X		}
X		if (lp->g_ty == ET_A)
X			strxpush(np);
X		else
X			addcode(np, "\tmove.S\t<A,-(sp)\n");
X		return OKAY;
X	case '(':
X		if (np->g_ty == ET_A) {		/* struct returned */
X			frc_ral(AREG);
X			indir(np, AREG);
X		} else {
X			frc_ral(0);
X			retreg(np, 0);
X		}
X		addcode(np, "\tjsr\t<A\n");
X		return OKAY;
X	case DOUBLE '+':
X		holdcon(np);
X		inherit(np);
X		addcode(np, "\tadd.S\t#K,A\n");
X		cc_hack(np);
X		return OKAY;
X	case DOUBLE '-':
X		holdcon(np);
X		inherit(np);
X		addcode(np, "\tsub.S\t#K,A\n");
X		cc_hack(np);
X		return OKAY;
X	case POSTINC:
X		if ((flags & NOVAL_OK) == 0) {
X			i = ralloc(0);
X			retreg(np, i);
X			addcode(np, "\tmove.S\t<A,A\n");
X		}
X		addcode(np, "\tadd.S\t#O,<A\n");
X		return OKAY;
X	case POSTDEC:
X		if ((flags & NOVAL_OK) == 0) {
X			i = ralloc(0);
X			retreg(np, i);
X			addcode(np, "\tmove.S\t<A,A\n");
X		}
X		addcode(np, "\tsub.S\t#O,<A\n");
X		return OKAY;
X	case CMPBR:
X		i = ralloc(0);
X		retreg(np, i);
X		addcode(np, "\tsN\tA\n\tand.w\t#1,A\n");
X		cc_hack(np);
X		return OKAY;
X	case '!':
X		if (flags & CC_OK) {
X			if (iscc(lp)) {
X				i = cctok(lp);
X				i = (i&1) ? i+1 : i-1;	/* reverse truth */
X			} else {
X				i = B_EQ;
X				addcode(np, "<Q");
X			}
X			np->g_token = i + BR_TOK;
X		} else {
X			if (istdreg(lp))
X				i = lp->g_rno;
X			else
X				i = ralloc(0);
X			retreg(np, i);
X			if (iscc(lp)) {
X				addcode(np, "<EA\n\tand.w\t#1,A\n");
X			} else {
X				addcode(np, "<Q");
X				addcode(np, "\tseq\tA\n\tand.w\t#1,A\n");
X			}
X		}
X		return OKAY;
X	default:
X		printf("Weird u_eval %s ", np->n_name);
X		return FAIL;
X	}
X}
X
Xholdcon(np)
XNODEP np;
X{
X	np->g_bsize = np->g_offs;
X}
X
Xretreg(np, rno)
XNODEP np;
X{
X	np->g_token = REGVAR;
X	np->g_rno = rno;
X}
X
Xindir(np, rno)
Xregister NODEP np;
X{
X	np->g_token = OREG;
X	np->g_offs = 0;
X	np->g_rno = rno;
X}
X
Xinherit(np)
Xregister NODEP np;
X{
X	NODEP lp = np->n_left;
X
X	np->g_token = lp->g_token;
X	np->g_offs = lp->g_offs;
X	np->g_rno = lp->g_rno;
X	np->g_flags |= CHILDNM | (lp->g_flags & IMMEDID);
X}
X
Xcookmon(np, cookie)
Xregister NODEP np;
X{
X	extern FILE *output;
X
X	if (np == NULL) return FAIL;
X
X	switch (cookie) {
X	case FORCC:
X		if (iscc(np)) {
X			outcode(np);
X			cctest = cctok(np);
X		} else {
X			if (np->g_token == ICON && isimmed(np)) {
X				cctest = np->g_offs ? B_YES : B_NO;
X				return OKAY;
X			}
X			outcode(np);
X			outsub("Q", np);
X			cctest = B_NE;
X		}
X		return OKAY;
X	case FORINIT:
X		if (anycode(np) == 0 && (np->g_flags & IMMEDID)) {
X			out_a(np, output);
X			return OKAY;
X		}
X		error("bad INIT expr");
X		return FAIL;
X	case IND0:
X		outcode(np);
X		if (np->g_token != REGVAR ||
X			np->g_rno != 0)
X			if (np->g_token == ICON && np->g_offs == 0 &&
X				isimmed(np))
X				outsub("\tclr.S\td0\n", np);
X			else
X				outsub("\tmove.S\tA,d0\n", np);
X		return OKAY;
X	case RETSTRU:
X		freetmps(np);
X		strret(np);
X		outcode(np);
X		return OKAY;
X	}
X	outcode(np);
X	return OKAY;
X}
X
Xanycode(np)
Xregister NODEP np;
X{
X	if (np->g_code)
X		return 1;
X	switch (np->g_type) {
X	case EV_NONE:
X		return 0;
X	case EV_LEFT:
X		return anycode(np->n_left);
X	case EV_RIGHT:
X		return anycode(np->n_right);
X	case EV_LR:
X	case EV_RL:
X		return anycode(np->n_left) || anycode(np->n_right);
X	}
X}
X
Xl_eval(np)
Xregister NODEP np;
X{
X	int l1;
X
X	switch (np->g_token) {
X	case ID:
X		switch (np->g_sc) {
X		default:	/* EXTERN or HERE */
X			np->g_token = ONAME;
X			np->g_offs = 0;
X			if (np->n_name[0] != '%')
X				nnmins(np, "_");
X			else	/* hack for inline name */
X				strcpy(np->n_name, &np->n_name[1]);
X			return OKAY;		/* dont free n_nmx */
X		case K_STATIC:
X			sprintf(np->n_name, "L%d", (int)np->g_offs);
X			np->g_offs = 0;
X			np->g_token = ONAME;
X			break;
X		case K_AUTO:
X			np->g_rno = FRAMEP;
X			np->g_token = OREG;
X			break;
X		case K_REGISTER:
X			np->g_token = REGVAR;
X			break;
X		}
X		if (np->n_nmx) {
X			freenode(np->n_nmx);
X			np->n_nmx = NULL;
X		}
X		return OKAY;
X	case ICON:
X		np->g_flags |= IMMEDID;
X		return OKAY;
X	case FCON:
X		np->g_flags |= IMMEDID;
X		return OKAY;
X	case SCON:
X		np->g_flags |= IMMEDID;
X		np->g_token = ONAME;
X		l1 = new_lbl();
X		save_scon(np, l1);
X		sprintf(np->n_name, "L%d", l1);
X		return OKAY;
X	case OREG:
X		return OKAY;
X	}
X	return FAIL;
X}
X
Xsave_scon(np, lbl)
XNODEP np;
X{
X	NODEP tp, copyone();
X
X	tp = copyone(np);
X	tp->g_offs = lbl;
X	if (np->n_nmx) {
X		freenode(np->n_nmx);
X		np->n_nmx = NULL;
X	}
X	putlist(&strsave, tp);
X}
X
Xutemp(np)
XNODEP np;
X{
X	NODEP lp = np->n_left;
X	int i;
X
X	if (lp->g_token == REGVAR && 
X	    istemp(lp->g_rno)) {
X		inherit(np);
X		return;
X	}
X	i = ralloc(0);
X	retreg(np, i);
X	addcode(np, "\tmove.S\t<A,A\n");
X}
X
Xfreetmps(np)
Xregister NODEP np;
X{
X	if (np->g_r1 != -1)
X		rfree(np->g_r1);
X	if (np->g_r2 != -1)
X		rfree(np->g_r2);
X}
X
Xfree1(np, cp)
XNODEP np, cp;
X{
X	int cr;
X
X	if (cp->g_token != OREG && cp->g_token != REGVAR)
X		return;
X	cr = cp->g_rno;
X	if (np && cr == np->g_rno &&
X		(np->g_token == OREG || np->g_token == REGVAR))
X		return;
X	if (istemp(cr))
X		rfree(cr);
X}
X
Xistemp(rno)
X{
X	return (rno < DRV_START || 
X		(rno >= AREG && rno < ARV_START));
X}
X
Xrfree(rno)
X{
X	reserve &= ~(1<<rno);
X}
X
Xfrc_ral(rno)
X{
X	int i;
X
X	i = (1<<rno);
X	if (reserve & i)
X		error("rno reserved! ");
X	reserve |= i;
X}
X
Xtempr(np, type)
XNODEP np;
X{
X	int i;
X
X	i = ralloc(type);
X	if (np->g_r1 == -1)
X		np->g_r1 = i;
X	else
X		np->g_r2 = i;
X	return i;
X}
X
Xralloc(type)
X{
X	int starti, endi;
X	register int i;
X
X	if (type == AREG) {
X		starti = AREG;
X		endi = ARV_START;
X	} else {
X		starti = 0;
X		endi = DRV_START;
X	}
X	for (i=starti; i<endi; i++)
X		if ((reserve & (1<<i)) == 0) {
X			reserve |= (1<<i);
X			return i;
X		}
X	error("Compiler failure - rallo");
X	return -1;
X}
X
Xtmp_alloc(sz)
X{
X	extern NODE *blktab;
X
X	tmpused += sz;
X	return blktab->b_size + tmpused;
X}
X
X/* fixes nodes with no code or aX is temp that are #d(aX) */
Ximm_oreg(np)
XNODEP np;
X{
X	char *regnm(), buf[30];
X	int i;
X
X	if (np->g_token != OREG)
X		return;
X	if ((np->g_flags & IMMEDID) == 0)
X		return;
X	np->g_flags &= ~IMMEDID;
X	if (np->g_offs == 0) {		/* #(a0) -> a0 */
X		np->g_token = REGVAR;
X		return;
X	}
X	if (istemp(np->g_rno)) {
X		holdcon(np);
X		addcode(np, "\tadd\t#K,A\n");
X		np->g_token = REGVAR;
X		return;
X	}
X	sprintf(buf, "\tlea\t%d(%s),A\n", (int)np->g_offs, regnm(np->g_rno));
X	addcode(np, buf);
X	i = ralloc(AREG);
X	retreg(np, i);
X}
X
Xcastgen(tp)
Xregister NODEP tp;
X{
X	register NODEP np = tp->n_left;
X	int sz = tp->g_sz;
X	int i;
X
X	if (np->g_token == ICON && isimmed(np)) {
X		if (tp->g_ty == ET_F) {
X			tp->g_token = FCON;
X			*(float *)&tp->g_offs = (float)np->g_offs;
X			tp->g_flags |= IMMEDID;
X		} else {
X			inherit(tp);
X			i_exp(tp, np->g_sz, np->g_ty);
X			squish(tp);
X		}
X	} else if (np->g_token == FCON && isimmed(np)) {
X		if (tp->g_ty != ET_F) {
X			tp->g_token = ICON;
X			tp->g_offs = (long)*(float *)&np->g_offs;
X			tp->g_flags |= IMMEDID;
X			squish(tp);
X		} else {
X			inherit(tp);
X		}
X	} else if (sz > np->g_sz) {
X		if (np->g_ty == ET_U) {
X			i = ralloc(0);
X			retreg(tp, i);
X			addcode(tp, "\tclr.S\tA\n\tmove.<S\t<A,A\n");
X		} else {
X			if (isdreg(np)) {
X				inherit(tp);
X			} else {
X				i = ralloc(0);
X				retreg(tp, i);
X				addcode(tp, "\tmove.<S\t<A,A\n");
X			}
X			if (sz == 4 && np->g_sz == 1)
X				addcode(tp, "\text.w\tA\n\text.l\tA\n");
X			else
X				addcode(tp, "\text.S\tA\n");
X		}
X		return;
X	}
X	else if (sz < np->g_sz) {
X		switch (np->g_token) {
X		case ONAME:
X		case OREG:
X			if (isimmed(np)) {
Xsmfudge:
X				i = ralloc(0);
X				retreg(tp, i);
X				addcode(tp, "\tmove.<S\t<A,A\n");
X				return;
X			}
X			inherit(tp);
X			tp->g_offs = np->g_offs + (np->g_sz - sz);
X			break;
X		case REGVAR:
X			if (sz == 1 && np->g_rno >= AREG)
X				goto smfudge;
X			/* fall through */
X		default:
X			inherit(tp);
X		}
X	} else
X		inherit(tp);
X}
X
Xsquish(np)
XNODEP np;
X{
X	int neg;
X
X	neg = (np->g_ty == ET_S && np->g_offs < 0);
X
X	switch (np->g_sz) {
X	case 1:
X		if (neg)
X			np->g_offs |= 0xffffff00L;
X		else
X			np->g_offs &= 0xff;
X		break;
X	case 2:
X		if (neg)
X			np->g_offs |= 0xffff0000L;
X		else
X			np->g_offs &= 0xffffL;
X		break;
X	}
X}
X
Xi_exp(np, osz, oty)
XNODEP np;
X{
X	long l;
X
X	if (oty == ET_S && osz < np->g_sz) {
X		l = np->g_offs;
X		switch (osz) {
X		case 1:
X			l = (char) l;
X			break;
X		case 2:
X			l = (short) l;
X			break;
X		}
X		np->g_offs = l;
X	}
X}
END_OF_FILE
if test 11959 -ne `wc -c <'hcc/GEN.C'`; then
    echo shar: \"'hcc/GEN.C'\" unpacked with wrong size!
fi
# end of 'hcc/GEN.C'
fi
echo shar: End of archive 5 \(of 9\).
cp /dev/null ark5isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 9 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0