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

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

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

#! /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 7 (of 9)."
# Contents:  hcc/GUNK.C hcc/P2.C hcc/PRE.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/GUNK.C' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'hcc/GUNK.C'\"
else
echo shar: Extracting \"'hcc/GUNK.C'\" \(15002 characters\)
sed "s/^X//" >'hcc/GUNK.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 *	gunk.c
X *
X *	Transformations on expression trees
X *	Most of this stuff is because we cant handle
X *	floats, long mul/div, or fields directly.
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 copyone();
X
X#define gwiden(x)	((x)==1 ? 2 : (x))
X#define isfield(np)	((np)->g_token == '.' && (np)->g_fldw)
X
XNODEP npar1, npar2, npar3;
Xchar *spar1, *spar2, *spar3;
Xint ipar1, ipar2, ipar3;
X
Xstruct rule {
X	int (*match)();		/* test for transformation needed */
X	int (*rewri)();		/* rewrite function */
X};
X
Xint m_unfold(), unfold(), m_cast(), cast(), m_inline(), inline();
Xint m_hardas(), hardas(), m_fcmp(), fcmp(), m_md_shf(), md_shf();
Xint m_eident(), eident(), m_incdec(), incdec(), m_fldas(), fldas();
X
Xstruct rule gunktbl[] = {
X	{m_unfold, unfold},
X	{m_cast, cast},
X	{m_md_shf, md_shf},
X	{m_eident, eident},
X	{m_incdec, incdec},
X	{m_hardas, hardas},
X	{m_inline, inline}, /* must cast before inline */
X	{m_fcmp, fcmp},
X	{m_fldas, fldas},
X	{0}
X};
X
Xint anygunk;
X
Xgunk(np)
XNODEP np;
X{
X	do {
X		anygunk = 0;
X		gunks(np);
X	} while (anygunk);
X}
X
Xgunks(np)
Xregister NODEP np;
X{
X	switch (np->g_type) {
X	case E_BIN:
X		gunks(np->n_right);
X	case E_UNARY:
X		gunks(np->n_left);
X	}
X	gunk1(np);
X}
X
Xgunk1(np)
XNODEP np;
X{
X	register struct rule *p;
X
X	for (p=gunktbl; p->match; p++)
X		if ((*p->match)(np)) {
X			anygunk++;
X			(*p->rewri)(np);
X			return;
X		}
X}
X
X/*
X *	Change pointer arithmetic to equivalent trees
X *		(main thing is to mult or div by object size)
X */
Xm_unfold(np)
XNODEP np;
X{
X	switch (np->g_token) {
X	case PTRADD:
X		ipar1 = '+';
X		return 1;
X	case PTRSUB:
X		ipar1 = '-';
X		return 1;
X	case PTRDIFF:
X		ipar1 = 0;
X		return 1;
X	case ASSIGN PTRADD:
X		ipar1 = ASSIGN '+';
X		return 1;
X	case ASSIGN PTRSUB:
X		ipar1 = ASSIGN '-';
X		return 1;
X	}
X	return 0;
X}
X
Xunfold(np)
XNODEP np;
X{
X	if (ipar1) {
X		ins_mul(np, np->g_offs);
X		np->g_token = ipar1;
X	} else {
X		ins_div(np, np->g_offs);
X	}
X}
X
XNODEP
Xnewgcon(kon, ty, sz)
Xlong kon;
X{
X	register NODEP kp;
X
X	kp = allocnode();
X	kp->g_token = ICON;
X	sprintf(kp->n_name, "%ld", kon);
X	kp->g_offs = kon;
X	kp->g_type = E_LEAF;
X	kp->g_ty = ty;
X	kp->g_sz = sz;
X	return kp;
X}
X
Xins_mul(np, kon)
XNODEP np;
Xlong kon;
X{
X	NODEP rp = np->n_right;
X	register NODEP mp, kp;
X
X	if (kon == 1)
X		return;
X	if (rp->g_token == ICON) {
X		rp->g_offs *= kon;
X		rp->g_sz = gwiden(rp->g_sz);
X		return;
X	}
X
X	mp = allocnode();
X	mp->g_token = '*';
X	sprintf(mp->n_name, "p*");
X	mp->g_type = E_BIN;
X	mp->g_ty = rp->g_ty;
X	mp->g_sz = gwiden(rp->g_sz);
X
X	kp = newgcon(kon, mp->g_ty, mp->g_sz);
X
X	mp->n_right = kp;
X	mp->n_left = np->n_right;
X	np->n_right = mp;
X}
X
Xins_div(np, kon)
Xregister NODEP np;
Xlong kon;
X{
X	register NODEP tp, kp;
X
X	kp = newgcon(kon, np->g_ty, np->g_sz);
X
X	tp = copyone(np);
X	tp->g_token = '-';
X	tp->n_left = np->n_left;
X	tp->n_right = np->n_right;
X	tp->g_sz = SIZE_P;
X	tp->g_ty = ET_U;
X
X	np->n_left = tp;
X	np->n_right = kp;
X	np->g_type = E_BIN;
X	np->g_token = '/';
X	sprintf(np->n_name, "p/");
X}
X
X#define CAST_LN	1
X#define CAST_RN 2
X#define CAST_LLONG	3
X
X/*
X *	Insert needed (implied) casts
X */
Xm_cast(np)
XNODEP np;
X{
X	NODEP lp = np->n_left;
X
X	switch (np->g_type) {
X	case E_LEAF:
X		return 0;
X	case E_BIN:
X		return bm_cast(np);
X	}
X	/* must be unary */
X	switch (np->g_token) {
X	case UNARY '-':
X	case '~':
X		return castup(lp, np, CAST_LN);
X	case TCONV:
X		return fcastlong(np);
X	}
X	return 0;
X}
X
Xbm_cast(np)
Xregister NODEP np;
X{
X	NODEP lp = np->n_left, rp = np->n_right;
X
X	if (isassign(np->g_token)) {
X		if (castup(rp, lp, CAST_RN))
X			return 1;
X		if (castmagic(rp, lp, CAST_RN, np->g_token - (ASSIGN 0)))
X			return 1;
X		return 0;
X	}
X
X	switch (np->g_token) {
X	case '=':
X		if (np->g_ty == ET_A)
X			return 0;
X		return castany(rp, lp, CAST_RN);
X
X	case '<':
X	case '>':
X	case DOUBLE '=':
X	case NOTEQ:
X	case LTEQ:
X	case GTEQ:
X		if (castup(lp, rp, CAST_LN))
X			return 1;
X		return castup(rp, lp, CAST_RN);
X
X	case '(':
X	case ',':
X	case '?':
X	case DOUBLE '&':
X	case DOUBLE '|':
X		return 0;
X
X	case DOUBLE '<':
X	case DOUBLE '>':
X		if (castup(lp, np, CAST_LN))
X			return 1;
X		return castany(rp, np, CAST_RN);
X
X	default:
X		if (castup(lp, np, CAST_LN))
X			return 1;
X		return castup(rp, np, CAST_RN);
X	}
X	return 0;
X}
X
Xfcastlong(np)
XNODEP np;
X{
X	NODEP lp = np->n_left;
X
X	if (red_con(lp))
X		return 0;
X	if (np->g_ty == ET_F && lp->g_ty != ET_F && lp->g_sz != SIZE_L) {
X		ipar1 = CAST_LLONG;
X		return 1;
X	}
X	if (lp->g_ty == ET_F && np->g_ty != ET_F && np->g_sz != SIZE_L) {
X		ipar1 = CAST_LLONG;
X		return 1;
X	}
X	return 0;
X}
X
Xcastup(lowp, hip, par)
XNODEP lowp, hip;
X{
X	if (stronger(hip, lowp)) {
X		ipar1 = par;
X		npar1 = hip;
X		return 1;
X	}
X	return 0;
X}
X
Xcastmagic(p1, p2, par, tok)
XNODEP p1, p2;
X{
X	if (xstronger(p1,p2) && magicop(tok)) {
X		ipar1 = par;
X		npar1 = p2;
X		return 1;
X	}
X	return 0;
X}
X
Xcastany(p1, p2, par)
XNODEP p1, p2;
X{
X	if (p1->g_sz != p2->g_sz ||
X		((p1->g_ty == ET_F) != (p2->g_ty == ET_F))) {
X		ipar1 = par;
X		npar1 = p2;
X		return 1;
X	}
X	return 0;
X}
X
Xcast(np)
XNODEP np;
X{
X	switch (ipar1) {
X	case CAST_LN:
X		castsub(npar1->g_ty, npar1->g_sz, &np->n_left, np->n_left);
X		break;
X	case CAST_RN:
X		castsub(npar1->g_ty, npar1->g_sz, &np->n_right, np->n_right);
X		break;
X	case CAST_LLONG:
X		castsub(ET_S, SIZE_L, &np->n_left, np->n_left);
X		break;
X	}
X}
X
Xcastsub(ty, sz, npp, np)
XNODEP *npp, np;
X{
X	register NODEP tp;
X
X	/* ICON cast optimization */
X	if (np->g_token == ICON &&
X	    np->g_ty == ty &&
X	    np->g_sz < sz) {
X		np->g_sz = sz;
X		return;
X	}
X
X	tp = allocnode();
X	tp->g_token = TCONV;
X	strcpy(tp->n_name, "cast up");
X	tp->n_left = np;
X	*npp = tp;
X	tp->g_sz = sz;
X	tp->g_ty = ty;
X	tp->g_type = E_UNARY;
X}
X
X/*
X *	Change stuff computer cant do to calls to inline functions
X *	(in this case, all floats and long *%/)
X */
Xm_inline(np)
XNODEP np;
X{
X	int isfloat, isuns;
X
X	if (np->g_type == E_LEAF)
X		return 0;
X
X	if (np->g_ty == ET_A)
X		return 0;
X	isfloat = (np->g_ty == ET_F);
X	isuns = (np->g_ty == ET_U);
X
X	if (np->g_type == E_UNARY) {
X		switch (np->g_token) {
X		case UNARY '-':
X			if (!isfloat) return 0;
X			spar1 = "%fpneg";
X			return 1;
X		case TCONV:
X			if ((np->n_left->g_ty == ET_F) == isfloat)
X				return 0;
X			if (red_con(np->n_left))
X				return 0;
X			spar1 = isfloat ? "fpltof" : "fpftol";
X			return 1;
X		}
X		return 0;
X	}
X
X	if (np->g_sz != 4)	/* longs or floats only */
X		return 0;
X
X	switch (np->g_token) {
X	case '*':
X		spar1 = isfloat ? "%fpmul" : (isuns ? "%lmulu" : "%lmul");
X		return 1;
X	case '/':
X		spar1 = isfloat ? "%fpdiv" : (isuns ? "%ldivu" : "%ldiv");
X		return 1;
X	case '+':
X		if (!isfloat) return 0;
X		spar1 = "%fpadd";
X		return 1;
X	case '-':
X		if (!isfloat) return 0;
X		spar1 = "%fpsub";
X		return 1;
X	case '%':
X		spar1 = isuns ? "%lremu" : "%lrem";
X		return 1;
X	}
X	return 0;
X}
X
Xinline(np)
XNODEP np;
X{
X	register NODEP nmp, cmap;
X	int isunary;
X
X	isunary = (np->g_type == E_UNARY);
X
X	if (isunary) {
X		np->n_right = np->n_left;
X		np->g_type = E_BIN;
X	} else {
X		cmap = copyone(np);
X		cmap->n_left = np->n_left;
X		cmap->n_right = np->n_right;
X		np->n_right = cmap;
X
X		cmap->g_token = ',';
X		cmap->g_offs = 2;
X		strcpy(cmap->n_name, ",inl");
X	}
X
X	nmp = allocnode();
X	np->n_left = nmp;
X
X	np->g_token = '(';
X	strcpy(np->n_name, "inline");
X
X	nmp->g_token = ID;
X	strcpy(nmp->n_name, spar1);
X#ifdef OUT_AZ
X	strcat(nmp->n_name, "#");
X#endif
X}
X
X/*
X *	Transform hard ++,-- to equivalent trees
X *	(for us, floats or fields)
X */
Xm_incdec(np)
XNODEP np;
X{
X	if (np->g_type != E_UNARY)
X		return 0;
X	if (np->g_ty != ET_F && !isfield(np->n_left))
X		return 0;
X
X	ipar2 = 0;
X	switch (np->g_token) {
X	case DOUBLE '+':
X		ipar1 = ASSIGN '+';
X		spar1 = "+=";
X		break;
X	case DOUBLE '-':
X		ipar1 = ASSIGN '-';
X		spar1 = "-=";
X		break;
X	case POSTINC:
X		ipar1 = DOUBLE '+';
X		spar1 = "++";
X		ipar2 = '-';
X		spar2 = "-";
X		break;
X	case POSTDEC:
X		ipar1 = DOUBLE '-';
X		spar1 = "--";
X		ipar2 = '+';
X		spar2 = "+";
X		break;
X	default:
X		return 0;
X	}
X	return 1;
X}
X
Xincdec(np)
Xregister NODEP np;
X{
X	NODEP t1;
X	NODEP onep;
X
X	onep = newgcon(1L, ET_S, SIZE_I);
X
X	if (ipar2 == 0) {		/* easy case, ++X becomes X+=1 */
X		np->g_token = ipar1;
X		np->g_type = E_BIN;
X		np->n_right = onep;
X		strcpy(np->n_name, spar1);
X		return;
X	}
X
X	/* hard case, X++ becomes (++X - 1) */
X	t1 = copyone(np);
X	t1->n_left = np->n_left;
X	np->n_left = t1;
X	np->n_right = onep;
X	np->g_type = E_BIN;
X	np->g_token = ipar2;
X	strcpy(np->n_name, spar2);
X
X	t1->g_token = ipar1;
X	strcpy(t1->n_name, spar1);
X}
X
X/*
X *	Transform hard op= trees to equivalent '=' trees
X *	(in this case, all floats, long or char *%/, fields)
X */
Xm_hardas(np)
XNODEP np;
X{
X	int op;
X
X	if (np->g_type != E_BIN)
X		return 0;
X	op = np->g_token;
X	if (isassign(op))
X		op -= ASSIGN 0;
X	else
X		return 0;
X	if (xstronger(np->n_right, np->n_left) &&
X		magicop(op) == 0)
X		return 1;
X	if (np->g_ty == ET_F || isfield(np->n_left))
X		return 1;
X	if (np->g_sz == 4 || np->g_sz == 1)
X		switch (op) {
X		case '*':
X		case '/':
X		case '%':
X			return 1;
X		}
X	return 0;
X}
X
Xhardas(np)
XNODEP np;
X{
X	NODEP opp, newl;
X	NODEP copynode();
X
X	if (m_vhard(np)) {
X		vhard(np);
X		return;
X	}
X
X	opp = copyone(np);
X	newl = copynode(np->n_left);
X	opp->n_right = np->n_right;
X	np->n_right = opp;
X	opp->n_left = newl;
X
X	np->g_token = '=';
X	strcpy(np->n_name, "unfold");
X
X	opp->g_token -= (ASSIGN 0);
X	bmaxty(opp);
X}
X
X/*
X *	Check for lhs of op= that have side effects or are complex
X */
Xm_vhard(np)
XNODEP np;
X{
X	NODEP lp = np->n_left;
X
X	while (lp->g_token == '.')
X		lp = lp->n_left;
X	if (lp->g_token != STAR)
X		return 0;
X	return isvhard(lp->n_left);
X}
X
Xisvhard(np)
XNODEP np;
X{
X	NODEP rp;
X
Xdescend:
X	switch (np->g_type) {
X	case E_LEAF:
X		return 0;
X	case E_UNARY:
X		switch (np->g_token) {
X		case '(':
X		case DOUBLE '+':
X		case DOUBLE '-':
X		case POSTINC:
X		case POSTDEC:
X			return 1;
X		default:
X			np = np->n_left;
X			goto descend;
X		}
X	case E_BIN:
X		switch (np->g_token) {
X		case '+':
X		case '-':
X			rp = np->n_right;
X			if (rp->g_token == ICON && np->g_ty != ET_F) {
X				np = np->n_left;
X				goto descend;
X			}
X			/* fall through */
X		default:
X			return 1;
X		}
X	}
X}
X
Xvhard(np)
XNODEP np;
X{
X	NODEP starp;
X	NODEP atree, btree;
X	NODEP t1, t2;
X	register NODEP opp;
X	NODEP tmp_var();
X
X	starp = np->n_left;
X	while (starp->g_token == '.')
X		starp = starp->n_left;
X	atree = starp->n_left;
X	btree = np->n_right;
X	t1 = tmp_var(ET_U, SIZE_P);
X	t2 = copyone(t1);
X	starp->n_left = t2;
X
X	opp = copyone(t1);
X	opp->g_type = E_BIN;
X	opp->g_token = '=';
X	strcpy(opp->n_name, "=");
X	opp->n_right = atree;
X	opp->n_left = t1;
X
X	comma_r(np, opp);
X}
X
Xcomma_r(topp, lp)
XNODEP topp, lp;
X{
X	register NODEP newp;
X
X	newp = copyone(topp);
X	topp->g_token = ',';
X	strcpy(topp->n_name, ",");
X	newp->n_left = topp->n_left;
X	newp->n_right = topp->n_right;
X	topp->n_left = lp;
X	topp->n_right = newp;
X}
X
XNODEP
Xtmp_var(ty, sz)
X{
X	register NODEP t1;
X
X	t1 = allocnode();
X	t1->g_token = OREG;
X	t1->g_type = E_LEAF;
X	t1->g_rno = AREG+6;
X	t1->g_ty = ty;
X	t1->g_sz = sz;
X	t1->g_offs = - tmp_alloc(sz);
X	strcpy(t1->n_name, "tmp_v");
X	return t1;
X}
X
X/* X op= Y where Y's type is stronger than X's
X	either unfold it or (default)
X	cast Y to weaker type (+ or -)
X*/
X
Xmagicop(op)
X{
X	switch (op) {
X	case '+':
X	case '-':
X	case DOUBLE '<':
X	case DOUBLE '>':
X	case '&':
X	case '|':
X	case '^':
X		return 1;
X	}
X	return 0;
X}
X
Xstronger(xp, yp)
XNODEP xp, yp;
X{
X	if (xp->g_sz > yp->g_sz || 
X		(xp->g_sz == yp->g_sz && xp->g_ty > yp->g_ty))
X		return 1;
X	return 0;
X}
X
X/* stronger with ET_S and ET_U considered equal */
Xxstronger(xp, yp)
XNODEP xp, yp;
X{
X	if (xp->g_sz > yp->g_sz ||
X		(xp->g_ty == ET_F && yp->g_ty != ET_F))
X		return 1;
X	return 0;
X}
X
X/* give np the type of the stronger child */
Xbmaxty(np)
XNODEP np;
X{
X	NODEP lp = np->n_left, rp = np->n_right;
X
X	if (stronger(lp, rp))
X		rp = lp;
X	np->g_ty = rp->g_ty;
X	np->g_sz = gwiden(rp->g_sz);
X}
X
X/*
X *	Change floating compares to inline call 
X */
Xm_fcmp(np)
XNODEP np;
X{
X		/* already made L and R same with casts */
X	if (np->g_type != E_BIN || np->n_left->g_ty != ET_F)
X		return 0;
X	switch (np->g_token) {
X	case '<':
X		spar2 = "lt";
X		return 1;
X	case '>':
X		spar2 = "gt";
X		return 1;
X	case DOUBLE '=':
X		spar2 = "eq";
X		return 1;
X	case NOTEQ:
X		spar2 = "ne";
X		return 1;
X	case GTEQ:
X		spar2 = "ge";
X		return 1;
X	case LTEQ:
X		spar2 = "le";
X		return 1;
X	}
X	return 0;
X}
X
Xfcmp(np)
Xregister NODEP np;
X{
X	register NODEP tp;
X
X	spar1 = "%fpcmp";
X	inline(np);
X
X	tp = copyone(np);
X	tp->n_left = np->n_left;
X	tp->n_right = np->n_right;
X	np->n_left = tp;
X
X	np->n_right = NULL;
X	np->g_type = E_UNARY;
X	np->g_token = CMPBR;
X	sprintf(np->n_name, spar2);
X}
X
X/*
X *	Remove useless binary operations with identity constant
X */
Xm_eident(np)
XNODEP np;
X{
X	NODEP rp = np->n_right;
X	long l;
X	int i, op;
X
X	if (np->g_type != E_BIN)
X		return 0;
X	if (np->g_ty == ET_F)
X		return 0;
X	while (rp->g_token == TCONV && rp->g_ty != ET_F)
X		rp = rp->n_left;
X	if (rp->g_token != ICON)
X		return 0;
X	l = rp->g_offs;
X	if (l < 0 || l > 1)
X		return 0;
X
X	op = np->g_token;
X	if (isassign(op))
X		op -= ASSIGN 0;
X	switch (op) {
X	case '+':
X	case '-':
X	case DOUBLE '<':
X	case DOUBLE '>':
X	case '|':
X	case '^':
X		i = 0;	break;
X	case '*':
X	case '/':
X		i = 1;  break;
X	default:
X		return 0;
X	}
X	if (l != i)
X		return 0;
X	return 1;	
X}
X
Xeident(np)
XNODEP np;
X{
X	NODEP lp = np->n_left, rp = np->n_right;
X
X	freenode(rp);
X	
X	lcpy(np, lp, sizeof(NODE)/4);
X
X	freeunit(lp);
X}
X
X#define MAXLOOK	8
X
X/*
X *	Change certain mult or div to equivalent shift
X */
Xm_md_shf(np)
XNODEP np;
X{
X	NODEP rp = np->n_right;
X	long l;
X	register i, j;
X
X	if (np->g_type != E_BIN)
X		return 0;
X	if (np->g_ty == ET_F)
X		return 0;
X	while (rp->g_token == TCONV && rp->g_ty != ET_F)
X		rp = rp->n_left;
X	if (rp->g_token != ICON)
X		return 0;
X
X	switch (np->g_token) {
X	case '*':
X		ipar1 = DOUBLE '<';  break;
X	case '/':
X		ipar1 = DOUBLE '>';  break;
X	case ASSIGN '*':
X		ipar1 = ASSIGN DOUBLE '<';  break;
X	case ASSIGN '/':
X		ipar1 = ASSIGN DOUBLE '>';  break;
X	default:
X		return 0;
X	}
X
X	l = rp->g_offs;
X	if (l < 2 || l > (1<<MAXLOOK))
X		return 0;
X	i = l;
X	for (j=1; j<=MAXLOOK; j++)
X		if (i == 1<<j) {
X			ipar2 = j;
X			return 1;
X		}
X	return 0;
X}
X
Xmd_shf(np)
XNODEP np;
X{
X	NODEP rp = np->n_right;
X
X	np->g_token = ipar1;
X	while (rp->g_token == TCONV)
X		rp = rp->n_left;
X	rp->g_offs = ipar2;
X}
X
Xm_fldas(np)
XNODEP np;
X{
X	if (np->g_type != E_BIN)
X		return 0;
X	if (np->g_token == '=' && isfield(np->n_left))
X		return 1;
X	return 0;
X}
X
Xfldas(np)
Xregister NODEP np;
X{
X	NODEP lp = np->n_left;
X
X	np->g_fldw = lp->g_fldw;
X	np->g_fldo = lp->g_fldo;
X	np->g_token = FIELDAS;
X
X	lp->g_fldw = 0;
X}
X
Xred_con(np)
Xregister NODEP np;
X{
X	while (np->g_token == TCONV)
X		np = np->n_left;
X	if (np->g_token == ICON || np->g_token == FCON)
X		return 1;
X	return 0;
X}
END_OF_FILE
if test 15002 -ne `wc -c <'hcc/GUNK.C'`; then
    echo shar: \"'hcc/GUNK.C'\" unpacked with wrong size!
fi
# end of 'hcc/GUNK.C'
fi
if test -f 'hcc/P2.C' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'hcc/P2.C'\"
else
echo shar: Extracting \"'hcc/P2.C'\" \(14397 characters\)
sed "s/^X//" >'hcc/P2.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 *	p2.c
X *
X *	Expression tree routines.
X *
X *	Constant folding, typing of nodes, simple transformations.
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 int xflags[];
X#define debug xflags['t'-'a']
X
Xextern nmerrors;
XNODEP bas_type();
X
Xdo_expr(np, cookie)
XNODE *np;
X{
X	if (np == NULL)
X		return;
X/*	include if want only one error at a time
X	if (nmerrors) {
X		freenode(np);
X		return;
X	}
X*/
X	p2_expr(&np);
X	genx(np, cookie);
X}
X
Xp2_expr(npp)
XNODEP *npp;
X{
X	NODEP np = *npp;
X
X	if (np == NULL) return;
X	if (debug > 1) {
X		printf("P2 enter");
X		printnode(np);
X	}
X	confold(npp,0);
X	np = *npp;
X	form_types(np);
X	if (debug) {
X		printf("p2_expr");
X		printnode(np);
X	}
X	return;
X}
X
Xform_types(np)
XNODEP np;
X{
X
X	if (np == NULL) return;
X	switch (np->e_type) {
X	case E_SPEC:
X		switch (np->e_token) {	/* special cases */
X		case '.':
X		case ARROW:
X			form_types(np->n_left);
X			sel_type(np);
X			return;
X		case '(':
X			if (np->n_right) {
X				form_types(np->n_right);	/* args */
X				np->e_type = E_BIN;
X			} else
X				np->e_type = E_UNARY;
X			fun_type(np);
X			return;
X		}
X		/* fall through */
X	case E_BIN:
X		form_types(np->n_left);
X		form_types(np->n_right);
X		b_types(np);
X		break;
X
X	case E_UNARY:
X		form_types(np->n_left);
X		u_types(np);
X		break;
X
X	case E_LEAF:
X		l_types(np);
X		break;
X	}
X}
X
X/* (fun) (args) */
Xfun_type(np)
XNODEP np;
X{
X	NODEP lp, typ;
X	NODEP allsyms(), new_fun();
X
X	lp = np->n_left;
X	if (lp->e_token == ID) { /* may be new ID */
X		typ = allsyms(lp);
X		if (typ == NULL)
X			typ = new_fun(lp);
X		typ = typ->n_tptr;
X		lp->n_tptr = typ;
X		lp->n_flags |= N_COPYT;
X	} else {
X		form_types(lp);
X		typ = lp->n_tptr;
X	}
X	if (typ->t_token != '(') {	/* fun ret ? */
X		error("call non-fun");
X		goto bad;
X	}
X	typ = typ->n_tptr;
X	goto good;
Xbad:
X	typ = bas_type(K_INT);
Xgood:
X	np->n_tptr = typ;
X	np->n_flags |= N_COPYT;
X}
X
X/* (struct|union) (. or ->) ID */
Xsel_type(xp)
XNODEP xp;
X{
X	NODEP np, sup;
X	int tok;
X	NODEP rv;
X	NODEP llook();
X
X	np = xp->n_right;
X	sup = xp->n_left->n_tptr;
X	tok = xp->e_token;
X
X/* already checked that np->e_token == ID */
X	if (tok == ARROW) {
X		if (sup->t_token != STAR) {
X			error("(non pointer)->");
X			goto bad;
X		}
X		sup = sup->n_tptr;
X	}
X	if (sup->t_token != K_STRUCT && sup->t_token != K_UNION) {
X		error("select non-struct");
X		goto bad;
X	}
X	rv = llook(sup->n_right, np);
X	if (rv == NULL) {
X		error("? member ID");
X		goto bad;
X	}
X	xp->e_offs = rv->e_offs;
X	if (rv->e_fldw) {
X		xp->e_fldw = rv->e_fldw;
X		xp->e_fldo = rv->e_fldo;
X	}
X	rv = rv->n_tptr;
X	goto good;
Xbad:
X	rv = bas_type(K_INT);
Xgood:
X	xp->n_tptr = rv;
X	xp->n_flags |= N_COPYT;
X
X	/* change to UNARY op */
X	xp->e_type = E_UNARY;
X	freenode(np);
X	xp->n_right = NULL;
X
X	/* change ARY OF to PTR TO */
X	if (rv->t_token == '[')
X		see_array(xp);
X}
X
Xl_types(np)
Xregister NODE *np;
X{
X	NODEP allsyms();
X	register NODE *tp;
X
X	switch (np->e_token) {
X	case ID:	/* already did see_id */
X		if (np->n_tptr->t_token == '[')	/* change to &ID */
X			see_array(np);
X		return;
X	case ICON:
X		tp = bas_type(icon_ty(np));
X		break;
X	case FCON:
X		tp = bas_type(K_DOUBLE);
X		break;
X	case SCON:
X		tp = bas_type(SCON);
X		break;
X	default:
X		errors("Weird leaf",np->n_name);
X	bad:
X		tp = bas_type(K_INT);
X	}
X	np->n_tptr = tp;
X	np->n_flags |= N_COPYT;
X}
X
Xu_types(np)
XNODEP np;
X{
X	NODEP tp;
X	NODEP lp = np->n_left;
X	NODEP normalty();
X
X	tp = lp->n_tptr;	/* default */
X
X	switch (np->e_token) {
X	case DOUBLE '+':
X	case DOUBLE '-':
X	case POSTINC:
X	case POSTDEC:
X		mustlval(lp);
X		mustty(lp, R_SCALAR);
X		if (tp->t_token == STAR)
X			np->e_offs = tp->n_tptr->t_size;
X		else
X			np->e_offs = 1;
X		break;
X	case STAR:
X		if (mustty(lp, R_POINTER)) goto bad;
X		tp = tp->n_tptr;
X		np->n_tptr = tp;
X		np->n_flags |= N_COPYT;
X
X		/* Ary of to Ptr to */
X		if (tp->t_token == '[')
X			see_array(np);
X		return;
X	case UNARY '&':
X		mustlval(lp);
X		tp = allocnode();
X		tp->n_tptr = lp->n_tptr;
X		tp->n_flags |= N_COPYT;
X		tp->t_token = STAR;
X		sprintf(tp->n_name, "Ptr to");
X		tp->t_size = SIZE_P;
X		np->n_tptr = tp;
X		return;		/* no COPYT */
X	case UNARY '-':
X		mustty(lp, R_ARITH);
X		tp = normalty(lp, NULL);
X		break;
X	case TCONV:
X		mustty(lp, R_SCALAR);
X		if (np->n_tptr->t_token != K_VOID)
X			mustty(np, R_SCALAR);
X		return;		/* type already specified */
X	case '!':
X		mustty(lp, R_SCALAR);
X		tp = bas_type(K_INT);
X		break;
X	case '~':
X		mustty(lp, R_INTEGRAL);
X		tp = normalty(lp, NULL);
X		break;
X	default:
X		error("bad unary type");
X	bad:
X		tp = bas_type(K_INT);
X	}
X	np->n_tptr = tp;
X	np->n_flags |= N_COPYT;
X}
X
Xb_types(np)
XNODEP np;
X{
X	NODEP tp;
X	NODEP lp, rp;
X	NODEP normalty(), addty(), colonty();
X	int op;
X
X	op = np->e_token;
X	if (isassign(op)) {
X		mustlval(np->n_left);
X		op -= (ASSIGN 0);
X	}
X
X	lp = np->n_left;
X	rp = np->n_right;
X	tp = bas_type(K_INT);
X	switch (op) {
X	case '*':
X	case '/':
X		mustty(lp, R_ARITH);
X		mustty(rp, R_ARITH);
X		tp = normalty(lp,rp);
X		break;
X	case '%':
X	case '&':
X	case '|':
X	case '^':
X		mustty(lp, R_INTEGRAL);
X		mustty(rp, R_INTEGRAL);
X		tp = normalty(lp,rp);
X		break;
X	case '+':
X	case '-':
X		mustty(lp, R_SCALAR);
X		mustty(rp, R_SCALAR);
X		tp = addty(np);
X		break;
X	case DOUBLE '<':
X	case DOUBLE '>':
X		mustty(lp, R_INTEGRAL);
X		mustty(rp, R_INTEGRAL);
X		tp = normalty(lp, NULL);
X		break;
X	case '<':
X	case '>':
X	case LTEQ:
X	case GTEQ:
X	case DOUBLE '=':
X	case NOTEQ:
X		mustty(lp, R_SCALAR);
X		mustty(rp, R_SCALAR);
X		chkcmp(np);
X		break;		/* INT */
X	case DOUBLE '&':
X	case DOUBLE '|':
X		mustty(lp, R_SCALAR);
X		mustty(rp, R_SCALAR);
X		break;		/* INT */
X	case '?':
X		mustty(lp, R_SCALAR);
X		tp = rp->n_tptr;
X		break;
X	case ':':
X		if (same_type(lp->n_tptr, rp->n_tptr)) {
X			tp = lp->n_tptr;
X			break;
X		}
X		mustty(lp, R_SCALAR);
X		mustty(rp, R_SCALAR);
X		tp = colonty(np);
X		break;
X	case '=':
X		mustlval(lp);
X		mustty(lp, R_ASSN);
X		asn_chk(lp->n_tptr, rp);
X		tp = lp->n_tptr;
X		break;
X	case ',':
X		tp = rp->n_tptr;
X		break;
X	default:
X		error("bad binary type");
X	bad:
X		tp = bas_type(K_INT);
X	}
X	if (isassign(np->e_token)) {
X		/* ignore normal result -- result is left type */
X		tp = lp->n_tptr;
X	}
X	np->n_tptr = tp;
X	np->n_flags |= N_COPYT;
X}
X
Xlong
Xconlval(np)
XNODEP np;
X{
X	long i;
X
X	confold(&np,0);
X	if (np->e_token == ICON) {
X		i = np->e_ival;
X		freenode(np);
X		return i;
X	}
X	error("need const expr");
X	return 0;
X}
X
Xconxval(np)
XNODEP np;
X{
X	return (int)conlval(np);
X}
X
Xconfold(npp,spec)
XNODEP *npp;
X{
X	NODEP np;
X	NODEP tp, onp;
X	int tok,spl,spr;
X	long l;
X
X	np = *npp;
X	if (np == NULL) return;
X	switch (np->e_type) {
X	case E_LEAF:
X			lcanon(np,spec);
X			return;
X	case E_UNARY:
X			confold(&np->n_left,0);
X			ucanon(np);
X			return;
X	case E_BIN:
X			confold(&np->n_left,0);
X	/* delay confold on the right tree */
X			switch (np->e_token) {
X			case DOUBLE '|':
X				l = np->n_left->e_ival;
X				tp = np;
X				goto l_or_r;
X			case DOUBLE '&':
X				l = ! np->n_left->e_ival;
X				tp = np;
X				goto l_or_r;
X			case '?':
X				l = np->n_left->e_ival;
X				tp = np->n_right;	/* ':' node */
X		l_or_r:
X				tok = np->n_left->e_token;
X				if (tok != ICON) {
X					confold(&np->n_right,0);
X					return;
X				}
X				onp = np;
X				if (l) {	/* take true side */
X					np = tp->n_left;
X					tp->n_left = NULL;
X				} else {	/* take false side */
X					np = tp->n_right;
X					tp->n_right = NULL;
X				}
X				freenode(onp);
X				confold(&np,0);
X				*npp = np;
X				return;
X			}
X			confold(&np->n_right,0);
X			bcanon(np);
X			if (np->e_flags & C_AND_A)
X				b_assoc(np);
X			return;
X	case E_SPEC:
X		tok = np->e_token;
X		spl = spr = 0;
X		switch (tok) {
X		case '(':
X			spl = tok;	/* new name allowed */
X			break;
X		case '.':
X		case ARROW:
X			spr = tok;	/* look in struct sym.tab. */
X			break;
X		}
X		confold(&np->n_left,spl);
X		confold(&np->n_right,spr);
X		return;
X	}
X}
X
Xnewicon(np,x,nf)
XNODE *np;
Xlong x;
X{
X	np->e_token = ICON;
X	np->e_ival = x;
X	np->e_flags = nf;
X	sprintf(np->n_name, "%ld", x);
X	np->e_type = E_LEAF;
X	if (np->n_left) {
X		freenode(np->n_left);
X		np->n_left = NULL;
X	}
X	if (np->n_right) {
X		freenode(np->n_right);
X		np->n_right = NULL;
X	}
X}
X
Xnewfcon(np,x,nf)
XNODE *np;
Xdouble x;
X{
X	np->e_token = FCON;
X	np->e_fval = x;
X	np->e_flags = nf;
X	sprintf(np->n_name, FLTFORM, x);
X	np->e_type = E_LEAF;
X	if (np->n_left) {
X		freenode(np->n_left);
X		np->n_left = NULL;
X	}
X	if (np->n_right) {
X		freenode(np->n_right);
X		np->n_right = NULL;
X	}
X}
X
X/* LEAF */
X/* sptok is token if E_SPEC node is parent
X   and dont want to look at ID yet */
Xlcanon(np,sptok)
XNODE *np;
X{
X	NODE *tp;
X	NODEP allsyms();
X	long x;
X
X	if (np->e_token == ID) {
X		if (sptok)
X			return;
X		see_id(np);
X		return;
X	}
X	if (np->e_token == TSIZEOF) {
X		tp = np->n_tptr;
X		x = tp->t_size;
X		np->n_tptr = NULL;
X		if ((np->n_flags & N_COPYT) == 0)
X			freenode(tp);
X		newicon(np, x, 0);
X	}
X}
X
X/* UNARY */
Xucanon(np)
XNODE *np;
X{
X	NODE *tp;
X	long x,l;
X	int lflags = 0;
X
X	if (np->e_token == K_SIZEOF) {
X		tp = np->n_left;
X		confold(&tp,0);
X		form_types(tp);
X		tp = tp->n_tptr;
X		x = tp->t_size;
X		goto out;
X	}
X
X	if (np->n_left->e_token == FCON) {
X		if (np->e_token == UNARY '-')
X			newfcon(np, -(np->n_left->e_fval));
X		return;
X	}
X	if (np->n_left->e_token != ICON)
X		return;
X	l = np->n_left->e_ival;
X	lflags = np->n_left->e_flags;
X	switch (np->e_token) {
X	case UNARY '-':
X			x = -l;		break;
X	case '~':
X			x = ~l;		break;
X	case '!':
X			x = !l;		break;
X	default:
X		return;
X	}
Xout:
X	newicon(np, x, lflags);
X}
X
Xbcanon(np)
Xregister NODE *np;
X{
X	int ltok, rtok;
X	double l,r;
X	NODEP tp;
X
X	ltok = np->n_left->e_token;
X	rtok = np->n_right->e_token;
X	if (ltok != ICON && ltok != FCON)
X		return;
X	if (rtok != ICON && rtok != FCON) {
X	/* left is ?CON, right is not */
X		if (np->e_flags & (C_AND_A|C_NOT_A)) {
X		/* reverse sides  - put CON on right */
X			tp = np->n_left;
X			np->n_left = np->n_right;
X			np->n_right = tp;
X			if (np->e_flags & C_NOT_A)
X				swt_op(np);
X		}
X		return;
X	}
X	if (ltok == ICON && rtok == ICON) {
X		b2i(np);
X		return;
X	}
X	if (ltok == FCON)
X		l = np->n_left->e_fval;
X	else
X		l = (double)np->n_left->e_ival;
X	if (rtok == FCON)
X		r = np->n_right->e_fval;
X	else
X		r = (double)np->n_right->e_ival;
X	b2f(np,l,r);
X}
X
X/* canon for assoc. & comm. op */
X/* this code will almost never be executed, but it was fun. */
Xb_assoc(np)
XNODEP np;
X{
X	NODEP lp, rp;
X	int tok;
X
X	lp = np->n_left;
X	if (lp->e_token != np->e_token)
X		return;
X	/* left is same op as np */
X	rp = np->n_right;
X	tok = lp->n_right->e_token;
X	if (tok != ICON && tok != FCON)
X		return;
X	/* left.right is ?CON */
X	tok = rp->e_token;
X	if (tok == ICON || tok == FCON) {
X		/* have 2 CONS l.r and r -- put together on r */
X		NODEP	ep;
X		ep = lp->n_left;
X		np->n_left = ep;
X		np->n_right = lp;
X		lp->n_left = rp;
X		/* can now fold 2 CONS */
X		bcanon(lp);
X	} else {
X		/* have 1 CON at l.r -- move to top right */
X		NODEP	kp;
X		kp = lp->n_right;
X		lp->n_right = rp;
X		np->n_right = kp;
X	}
X}
X
X/* switch pseudo-commutative op */
Xswt_op(np)
XNODEP np;
X{
X	int newtok;
X	char *newnm;
X
X	switch (np->e_token) {
X	case '<':	newtok = '>';	newnm = ">";	break;
X	case '>':	newtok = '<';	newnm = "<";	break;
X	case LTEQ:	newtok = GTEQ;	newnm = ">=";	break;
X	case GTEQ:	newtok = LTEQ;	newnm = "<=";	break;
X	default:
X		return;
X	}
X	np->e_token = newtok;
X	strcpy(np->n_name, newnm);
X}
X
X/* BINARY 2 ICON's */
Xb2i(np)
Xregister NODE *np;
X{
X	register long l,r,x;
X	int newflags,lflags;
X
X	newflags = 0;
X
X	r = np->n_right->e_ival;
X	newflags = np->n_right->e_flags;
X
X	l = np->n_left->e_ival;
X	lflags = np->n_left->e_flags;
X	newflags = newflags>lflags ? newflags : lflags;
X
X	switch (np->e_token) {
X	case '+':
X			x = l+r;	break;
X	case '-':
X			x = l-r;	break;
X	case '*':
X			x = l*r;	break;
X	case '/':
X			x = l/r;	break;
X	case '%':
X			x = l%r;	break;
X	case '>':
X			x = l>r;	break;
X	case '<':
X			x = l<r;	break;
X	case LTEQ:
X			x = l<=r;	break;
X	case GTEQ:
X			x = l>=r;	break;
X	case DOUBLE '=':
X			x = l==r;	break;
X	case NOTEQ:
X			x = l!=r;	break;
X	case '&':
X			x = l&r;	break;
X	case '|':
X			x = l|r;	break;
X	case '^':
X			x = l^r;	break;
X	case DOUBLE '<':
X			x = l<<r;	break;
X	case DOUBLE '>':
X			x = l>>r;	break;
X	default:
X		return;
X	}
X	newicon(np, x, newflags);
X}
X
X/* BINARY 2 FCON's */
Xb2f(np,l,r)
Xregister NODE *np;
Xdouble l,r;
X{
X	register double x;
X	int ix, isint;
X
X	isint = 0;
X
X	switch (np->e_token) {
X	case '+':
X			x = l+r;	break;
X	case '-':
X			x = l-r;	break;
X	case '*':
X			x = l*r;	break;
X	case '/':
X			x = l/r;	break;
X	case '>':
X			ix = l>r;	isint++;	break;
X	case '<':
X			ix = l<r;	isint++;	break;
X	case LTEQ:
X			ix = l>=r;	isint++;	break;
X	case GTEQ:
X			ix = l<=r;	isint++;	break;
X	case DOUBLE '=':
X			ix = l==r;	isint++;	break;
X	case NOTEQ:
X			ix = l!=r;	isint++;	break;
X	default:
X		return;
X	}
X	if (isint)
X		newicon(np, (long)ix, 0);
X	else
X		newfcon(np, x);
X}
X
Xsame_type(a,b)
Xregister NODE *a, *b;
X{
Xmore:
X	if (a == b)
X		return 1;
X	if (a == NULL || b == NULL)
X		return 0;
X	if (a->t_token != b->t_token)
X		return 0;
X	if (a->t_token != STAR && a->t_size != b->t_size)
X		return 0;
X	a = a->n_tptr;
X	b = b->n_tptr;
X	goto more;
X}
X
Xsee_id(np)
XNODEP np;
X{
X	NODEP tp;
X	NODEP allsyms(), def_type();
X
X	tp = allsyms(np);
X	if (tp == NULL) {
X		errorn("undefined:", np);
X		tp = def_type();
X		goto out;
X	}
X	switch (tp->e_sc) {
X	case ENUM_SC:
X		newicon(np, tp->e_ival, 0);
X		return;
X	case K_REGISTER:
X		np->e_rno = tp->e_rno;
X		/* fall through */
X	default:
X		np->e_sc = tp->e_sc;
X		np->e_offs = tp->e_offs;
X		tp = tp->n_tptr;
X	}
Xout:
X	np->n_tptr = tp;
X	np->n_flags |= N_COPYT;
X
X	/* special conversions */
X	if (tp->t_token == '(')
X		insptrto(np);
X}
X
Xinsptrto(np)
XNODEP np;
X{
X	NODEP op, copyone();
X
X	op = copyone(np);
X
X	np->n_left = op;
X	np->e_token = UNARY '&';
X	np->e_type = E_UNARY;
X	strcpy(np->n_name, "&fun");
X	np->n_flags &= ~N_COPYT;
X}
X
X/* np points to ID or STAR or '.' node
X	tptr is a COPY
X	tptr token is '[' */
X
Xsee_array(np)
XNODEP np;
X{
X	NODEP tp, copyone();
X
X	tp = copyone(np);
X	tp->n_left = np->n_left;
X	tp->n_tptr = tp->n_tptr->n_tptr;
X
X	np->n_left = tp;
X	np->e_token = UNARY '&';
X	np->e_type = E_UNARY;
X	strcpy(np->n_name, "&ary");
X	arytoptr(np);
X/* leave old size
X	np->n_tptr->t_size = SIZE_P;
X*/
X}
END_OF_FILE
if test 14397 -ne `wc -c <'hcc/P2.C'`; then
    echo shar: \"'hcc/P2.C'\" unpacked with wrong size!
fi
# end of 'hcc/P2.C'
fi
if test -f 'hcc/PRE.C' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'hcc/PRE.C'\"
else
echo shar: Extracting \"'hcc/PRE.C'\" \(14315 characters\)
sed "s/^X//" >'hcc/PRE.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 *	pre.c
X *
X *	preprocessor for the compiler
X *
X *	Handles all preprocessor (#) commands and
X *	  looks up keywords
X *
X *	Interface:
X *		getnode()	returns next "token node"
X */
X
X#include <stdio.h>
X#include "param.h"
X#include "tok.h"
X#include "nodes.h"
X
X#if CC68
XFILE *fopenb();
X#define fopen fopenb
X#endif
X
Xextern struct tok curtok;
Xextern char curstr[];
X
X#define TK_SEENL	1	/* want to see NL token */
X#define TK_SEEWS	2	/* want to see WS token */
X#define TK_ONLY1	4	/* only want 1st token on line */
X#define TK_LTSTR	8	/* '<' starts a string */
X#define TK_NOESC	16	/* dont do '\' escapes in string */
X
Xextern int tk_flags, sawnl;
X
X#ifndef ACK_HOST
XNODE *deflist[NHASH];
XNODE *holdtok;
Xint iflevel, iftruth, ifnest, in_if_x, skip_id;
X#else
X#if PART_1
XNODE *deflist[NHASH];
XNODE *holdtok;
Xextern int iflevel, iftruth, ifnest, in_if_x, skip_id;
X#else
Xextern NODE *deflist[NHASH];
Xextern NODE *holdtok;
Xint iflevel, iftruth, ifnest, in_if_x, skip_id;
X#endif
X#endif
X
Xextern lineno;
Xextern char *inname;
Xextern FILE *input;
X
XNODE *hlook(), *llook();
XNODEP tok_to_node();
XNODE *copylist();
X
X#ifdef DEBUG
Xextern int oflags[];
X#define debugd	oflags['d'-'a']
X#define debugt	oflags['t'-'a']
X#endif
X
X#ifndef ACK_HOST
X#define PART_1	1
X#define PART_2	1
X#endif
X
X#if PART_1
X
XNODEP
Xhi_node()
X{
X	register NODEP rv;
X
X	/* node from hold queue ? */
X	if (holdtok) {
X#ifdef DEBUG
X		if (debugd > 2) {
X			printf("Holdqueue");
X			printnode(holdtok);
X		}
X#endif
X		rv = holdtok;
X		holdtok = rv->n_next;
X		rv->n_next = NULL;
X		return rv;
X	}
X	/* node from input */
Xagain:
X	while (iflevel && !iftruth)
X		skiplines();
X	if (nxttok()==0)
X		return NULL;
X	if (curtok.tnum == '#') {
X		dopound(0);
X		goto again;
X	}
X	rv = tok_to_node();
X	return rv;
X}
X
XNODEP
Xgetnode()
X{
X	register NODEP rv;
X	NODEP dp;
X
Xagain:
X	rv = hi_node();
X	if (rv == NULL) {
X		rv = allocnode();
X		rv->e_token = EOFTOK;
X		strcpy(rv->n_name, "*EOF*");
X	} else
X	if (rv->e_token == ID) {
X		if (in_if_x && strcmp(rv->n_name, "defined") == 0) {
X			skip_id = 1;
X			goto out;
X		}
X		if (skip_id) {
X			skip_id = 0;
X			goto out;
X		}
X		if ((dp = hlook(deflist, rv)) != NULL) {
X			expand(dp);
X			freenode(rv);
X			goto again;
X		} else if (rv->n_name[0] == '_' && builtin(rv))
X			return rv;
X		else
X			kw_tok(rv);
X	}
Xout:
X#ifdef DEBUG
X	if (debugt) {
X		putchar('[');
X		put_nnm(rv);
X		printf("] ");
X	}
X#endif
X	return rv;
X}
X
Xbuiltin(np)
Xregister NODEP np;
X{
X	int rv;
X
X	if (strcmp(np->n_name, "__LINE__") == 0) {
X		np->e_token = ICON;
X		np->e_ival = lineno;
X		return 1;
X	}
X	else if (strcmp(np->n_name, "__FILE__") == 0) {
X		np->e_token = SCON;
X		nscpy(np, inname);
X		return 1;
X	}
X	return 0;
X}
X
Xskiplines()
X{
X	for (;;) {
X		if (nxttok()== 0)
X			return;
X		if (curtok.tnum == '#') {
X			dopound(1);
X			return;
X		}
X		tk_flags |= TK_ONLY1;
X	}
X}
X
Xstatic defnargs;
X
Xp_def()
X{
X	NODE *args;
X	NODE *val;
X	NODE *def;
X	NODE *def_rgs(), *def_val();
X
X	defnargs = -1;
X	args = NULL;
X	val = NULL;
X	nxttok();
X	if (curtok.tnum != ID) {
X		error("bad #define");
X		goto flush;
X	}
X	def = tok_to_node();
X
X	tk_flags |= TK_SEEWS;
X	nxttok();
X	switch (curtok.tnum) {
X	case '(':
X		defnargs = 0;
X		args = def_rgs();
X	case WS:
X		goto getval;
X	case NL:
X		goto dodef;
X	default:
X		error("bad #define");
X		goto flush;
X	}
Xgetval:
X	val = def_val();
Xdodef:
X	def->e_ival = defnargs;
X	define(def, val, args);
Xflush:
X	;
X}
X
Xoptdef(s,as)
Xchar *s, *as;
X{
X	NODEP val;
X	NODEP def;
X	NODEP id_tok(), def_val();
X
X	defnargs = -1;
X	val = NULL;
X
X	def = id_tok(s);
X	chr_push(as);
X
X	tk_flags |= TK_SEENL;
X
X	val = def_val();
X
X	tk_flags = 0;
X
X	def->e_ival = defnargs;
X	define(def, val, NULL);
X}
X
X/*
Xoptundef(s)
Xchar *s;
X{
X	NODEP np, tp, id_tok();
X
X	np = id_tok(s);
X	tp = hlook(deflist, np);
X	if (tp != NULL)
X		tp->n_name[0] = '#';
X	freenode(np);
X}
X*/
X
Xsamedef(p1, p2)
XNODEP p1, p2;
X{
X	if (p1->e_ival != p2->e_ival)
X		return 0;
X	return same_list(p1->n_right, p2->n_right);
X}
X
Xsame_list(p1, p2)
XNODEP p1, p2;
X{
X	if (p1 == NULL)
X		return p2 == NULL;
X	if (p2 == NULL)
X		return 0;
X	if (l_cmp(p1, p2, sizeof(*p1)/sizeof(long)) != 0)
X		return 0;
X	return same_list(p1->n_left, p2->n_left);
X}
X
Xl_cmp(p1, p2, n)
XNODE *p1, *p2;
X{
X	if (xstrcmp(p1,p2) != 0)
X		return 1;
X	if (p1->e_token != p2->e_token ||
X		p1->e_ival != p2->e_ival)
X		return 1;
X	return 0;
X}
X
Xdefine(def, val, args)
XNODEP def, val, args;
X{
X	NODEP oldp;
X
X	if (args != NULL) {
X		argsmod(val, args);
X		freenode(args);
X	}
X	def->n_right = val;
X	if ((oldp = hlook(deflist, def)) != NULL) {
X		if (!samedef(oldp, def))
X			warnn("redefined", def);
X	}
X#ifdef DEBUG
X	if (debugd) {
X		printf("define (%d args)", (int)def->e_ival);
X		printnode(def);
X	}
X#endif
X	puthlist(deflist, def);
X}
X
Xargsmod(toks, args)
XNODEP toks, args;
X{
X	register NODE *np, *vp;
X
X	for (np=toks; np != NULL; np = np->n_next)
X		if (np->e_token == ID) {
X			vp = llook(args,np);
X			if (vp != NULL) {
X				np->e_token = DPARAM;
X				np->e_ival = vp->e_ival;
X				sprintf(np->n_name, "\\%d", (int)np->e_ival);
X			}
X		}
X}
X
XNODE *
Xdef_rgs()
X{
X	NODE *rv;
X	NODE *tail;
X	NODE *np;
X
X	rv = NULL;
X	tail = NULL;
X	nxttok();
X	if (curtok.tnum == ')') {
X		goto out;
X	}
Xmore:
X	if (curtok.tnum != ID) {
X		error("expect ID");
X		goto bad;
X	}
X	np = tok_to_node();
X	np->e_ival = defnargs;	/* hold sequence number */
X	defnargs++;
X	if (tail == NULL) {	/* first one */
X		rv = np;
X		tail = np;
X	} else {			/* more */
X		tail->n_next = np;
X		tail = np;
X	}
X	nxttok();
X	if (curtok.tnum == ',') {
X		nxttok();
X		goto more;
X	}
X	if (curtok.tnum == ')')
X		goto out;
X	error("define arg syntax");
Xbad:
X	freenode(rv);
X	rv = NULL;
X	defnargs = 0;
Xout:
X	return rv;
X}
X
XNODE *
Xdef_val()
X{
X	NODE *rv;
X	NODE *tail;
X	NODE *np;
X
X	rv = NULL;
X	tail = NULL;
Xmore:
X	nxttok();
X	if (curtok.tnum == NL) {
X		goto out;
X/*
X	} else if (curtok.tnum == '\\') {
X		nxttok();
X		if (curtok.tnum != NL)
X			goto bad;
X		goto more;
X*/
X	}
X	np = tok_to_node();
X	if (tail == NULL) {	/* first one */
X		rv = np;
X		tail = np;
X	} else {			/* more */
X		tail->n_next = np;
X		tail = np;
X	}
X	goto more;
X
Xbad:
X	freenode(rv);
X	rv = NULL;
Xout:
X	return rv;
X}
X
XNODE *
Xgath1(sep)
Xint *sep;
X{
X	NODE *np, *rv, *tail;
X	int inparen;
X
X	inparen = 0;
X	rv = NULL;
X	tail = NULL;
Xmore:
X	np = hi_node();
X	if (np == NULL) {
X		goto bad;
X	}
X	switch (np->e_token) {
X	case ')':
X	case ',':
X		if (inparen) {	/* dont end, part of subexpr */
X			if (np->e_token == ')')
X				inparen--;
X			break;
X		}
X		*sep = np->e_token;
X		freenode(np);
X		goto out;
X	case '(':
X		inparen++;
X		break;
X	}
X	if (tail == NULL) {	/* first one */
X		rv = np;
X		tail = np;
X	} else {			/* more */
X		tail->n_next = np;
X		tail = np;
X	}
X	goto more;
Xbad:
X	freenode(rv);
X	rv = NULL;
X	*sep = 0;
Xout:
X	return rv;
X}
X
XNODE *
Xgath_args(n)
X{
X	NODE *rv;
X	NODE *tail;
X	NODE *np;
X	int sep;
X	int getn;
X
X	getn = 0;
X	rv = NULL;
X	tail = NULL;
X	np = hi_node();
X	if (np->e_token != '(') {
X		error("expect (");
X		goto bad;
X	}
X	freenode(np);
X	if (n == 0) {
X		np = hi_node();
X		if (np->e_token != ')') {
X			error("expect )");
X			goto bad;
X		}
X		freenode(np);
X		return NULL;
X	}
Xmore:
X	np = gath1(&sep);
X	if (np == NULL) {
X		error("expect arg");
X		goto bad;
X	}
X	getn++;
X	if (tail == NULL) {	/* first one */
X		rv = np;
X		tail = np;
X	} else {			/* more */
X		tail->n_right = np;
X		tail = np;
X	}
X	if (sep) switch (sep) {
X	case ',':
X		goto more;
X	case ')':
X		if (getn != n) {
X			error("arg num mismatch");
X			goto bad;
X		}
X		goto out;
X	}
X	error("expand arg syntax");
Xbad:
X	freenode(rv);
X	rv = NULL;
Xout:
X	return rv;
X}
X
XNODE *
Xargfix(val, args, rt)
XNODE *val, *args;
XNODE **rt;
X{
X	register NODE *scan, *sub;
X	NODE *head;
X	NODE *tail, *back;
X	NODE *rthnode();
X	NODE *copylist();
X
X	head = val;
X	back = NULL;
X	for (scan = val; scan != NULL; back=scan, scan=scan->n_next)
X		if (scan->e_token == DPARAM) {
X			sub = rthnode(args, (int)scan->e_ival);
X			sub = copylist(sub,&tail);
X			if (back) {
X				back->n_next = sub;
X				tail->n_next = scan->n_next;
X			} else {
X				head = sub;
X				tail->n_next = scan->n_next;
X			}
X			scan->n_next = NULL;
X			freenode(scan);
X			scan = tail;
X		}
X	*rt = back;
X	return head;
X}
X
Xexpand(dp)
XNODEP dp;
X{
X	int nargs;
X	NODEP args;
X	register NODEP val;
X	NODEP tail;
X
X	val = dp->n_right;
X	if (val)
X		val = copylist(val, &tail);
X	nargs = dp->e_ival;
X	if (nargs >= 0) {
X		args = gath_args(nargs);
X		if (args) {
X			if (val)
X				val = argfix(val,args,&tail);
X			freenode(args);
X		}
X	}
X	if (val == NULL)
X		return;
X#ifdef DEBUG
X	if (debugd > 1) {
X		printf("Expand");
X		printnode(val);
X	}
X#endif
X	tail->n_next = holdtok;
X	holdtok = val;
X}
X
Xp_undef()
X{
X	NODEP np, tp;
X
X	nxttok();
X	if (curtok.tnum != ID) {
X		error("bad #undef");
X		goto out;
X	}
X	tp = tok_to_node();
X	if ((np = hlook(deflist, tp)) != NULL)
X		/* quick and dirty */
X		np->n_name[0] = '#';
X	freenode(tp);
Xout:
X	;
X}
X
X#endif
X#if PART_2
X
Xp_inc()
X{
X	int chkhere;
X	FILE *newf, *srch_open();
X	char *scopy(), *newnm;
X
X	tk_flags |= TK_NOESC|TK_LTSTR;
X	nxttok();
X	switch (curtok.tnum) {
X	case SCON:
X		chkhere = 1;
X		break;
X	case SCON2:
X		chkhere = 0;
X		break;
X	case NL:
X	case EOF:
X		error("bad #include");
X		return;
X	}
X	newf = srch_open(curstr, chkhere);
X	if (newf == NULL) {
X		fatals("Cant open ", curstr);
X		return;
X	}
X	newnm = scopy(curstr);
X	do 
X		nxttok();
X	while (curtok.tnum != NL);
X	newfile(newf,newnm);
X}
X
Xint inclvl;
Xstruct svinc {
X	int lineno;
X	FILE *fd;
X	char *filenm;
X} svincs[MAXINCL];
X
X#if NEEDBUF
Xchar p_buf[MAXINCL][BUFSIZ];
X#endif
X
Xstatic char obuf[MAXSTR];
X
Xnewfile(fd,s)
XFILE *fd;
Xchar *s;
X{
X	register struct svinc *p;
X
X	inclvl++;
X	if (inclvl > MAXINCL) {
X		inclvl--;
X		fclose(fd);
X		error("too many includes");
X		return;
X	}
X	p = &svincs[inclvl-1];
X	p->lineno = lineno;
X	p->fd = input;
X	p->filenm = inname;
X	input = fd;
X	lineno = 1;
X	inname = s;
X#if NEEDBUF
X	setbuf(input, p_buf[inclvl-1]);
X#endif
X}
X
Xendfile()
X{
X	register struct svinc *p;
X
X	if (inclvl == 0)
X		return 0;
X	fclose(input);
X	inclvl--;
X	p = &svincs[inclvl];
X	sfree(inname);
X	input = p->fd;
X	lineno = p->lineno;
X	inname = p->filenm;
X	return 1;
X}
X
X#define MAXIDIR	10
X
X#ifndef FOR_AMIGA
X#ifndef MINIX
Xchar *srchlist[MAXIDIR] = {
X	"",
X	"\\include\\",
X	"\\sozobon\\include\\",
X	"",
X	0
X};
Xstatic int idir_n = 4;		/* number of entries in above table */
X#else
Xchar *srchlist[MAXIDIR] = {
X	"",
X	"/usr/include/",
X	0
X};
Xstatic int idir_n = 2;
X#endif
X#else
Xchar *srchlist[MAXIDIR] = {
X	"",
X	"include:",
X	0
X};
Xstatic int idir_n = 2;		/* number of entries in above table */
X#endif
X
Xstatic int idir_put = 1;	/* where to put -I dirs */
X
Xoptincl(s)
Xchar *s;
X{
X	register char **pp;
X
X	if (idir_n >= MAXIDIR-1) {
X		warn("too many -I dirs");
X		return;
X	}
X	for (pp = &srchlist[idir_n]; pp > &srchlist[idir_put]; ) {
X		pp--;
X		pp[1] = pp[0];
X	}
X	*pp = s;
X	idir_put++;
X	idir_n++;
X}
X
XFILE *
Xsrch_open(s, chkhere)
Xchar *s;
X{
X	char **dir;
X	FILE *fd;
X
X	dir = srchlist;
X	if (chkhere == 0) dir++;
X	while (*dir) {
X		strcpy(obuf, *dir);
X		strcat(obuf, s);
X		fd = fopen(obuf, ROPEN);
X		if (fd != NULL) {
X			return fd;
X		}
X		dir++;
X	}
X	return NULL;
X}
X
Xp_if(kind,skipping)
X{
X	int truth;
X	NODEP tp;
X
X	if (skipping) {
X		ifnest++;
X		return;
X	}
X	switch (kind) {
X	case 0:
X		truth = if_expr();
X		break;
X	case 1:
X	case 2:
X		nxttok();
X		if (curtok.tnum != ID) {
X			error("bad #if(n)def");
X			goto flush;
X		}
X		tp = tok_to_node();
X		truth = (hlook(deflist, tp) != NULL);
X		freenode(tp);
X		if (kind == 2)
X			truth = !truth;
X	}
X	iflevel++;
X	iftruth = truth;
Xflush:
X	;
X}
X
Xif_expr()
X{
X	NODE *tp, *questx();
X	extern NODE *cur;
X	int rv;
X
X	in_if_x = 1;
X	skip_id = 0;
X	advnode();
X	tp = questx();
X	in_if_x = 0;
X	skip_id = 0;
X	if (tp) {
X		pnames(tp);
X		rv = conxval(tp);
X	} else
X		rv = 0;
X	if (cur->e_token != NL) {
X		error("bad #if");
X	} else
X		freenode(cur);
X	return rv;
X}
X
Xpnames(np)
Xregister NODEP np;
X{
Xagain:
X	if (np->e_token == ID) {
X		np->e_token = ICON;
X		np->e_ival = 0;
X	} else if (np->e_token == '(') {
X		NODEP rp, lp;
X		int truth;
X
X		rp = np->n_right;
X		lp = np->n_left;
X		if (lp->e_token == ID && strcmp(lp->n_name, "defined") == 0
X			&& rp && rp->e_token == ID) {
X			truth = (hlook(deflist, rp) != NULL);
X			freenode(rp);
X			freenode(lp);
X			np->n_left = NULL;
X			np->n_right = NULL;
X			np->e_token = ICON;
X			np->e_ival = truth;
X		}
X	}
X	if (np->n_right)
X		pnames(np->n_right);
X	np = np->n_left;
X	if (np)
X		goto again;
X}
X
Xp_swit(kind,skipping)
X{
X	if (skipping && ifnest) {
X		if (kind == 1)
X			ifnest--;
X		return;
X	}
X	if (iflevel == 0) {
X		error("not in #if");
X		goto out;
X	}
X	switch (kind) {
X	case 0:		/* else */
X		iftruth = !iftruth;
X		break;
X	case 1:		/* endif */
X		iflevel--;
X		iftruth = 1;
X		break;
X	}
Xout:
X	;
X}
X
Xp_line()
X{
X	char *scopy();
X
X	nxttok();
X	if (curtok.tnum != ICON) {
X		error("bad #line");
X		goto flush;
X	}
X	tk_flags |= TK_NOESC;
X	nxttok();
X	if (curtok.tnum == SCON) {
X		sfree(inname);
X		inname = scopy(curtok.name);
X	}
X	lineno = curtok.ival;
Xflush:
X	;
X}
X
Xstruct cmds {
X	char *name;
X	int (*fun)();
X	int arg;
X	int skip;
X} pcmds[] = {
X	{"define", p_def, 0, 1},
X	{"undef", p_undef, 0, 1},
X	{"include", p_inc, 0, 1},
X	{"if", p_if, 0, 0},
X	{"ifdef", p_if, 1, 0},
X	{"ifndef", p_if, 2, 0},
X	{"else", p_swit, 0, 0},
X	{"endif", p_swit, 1, 0},
X	{"line", p_line, 0, 1},
X	{0}
X};
X
Xdopound(skipping)
X{
X	register struct cmds *p;
X	register char *cname;
X
X	tk_flags |= TK_SEENL;
X	sawnl = 0;
X	nxttok();
X	if (curtok.tnum != ID) {
X		error("expect name");
X		return;
X	}
X	cname = curtok.name;
X	for (p=pcmds; p->name; p++)
X		if (strcmp(p->name, cname) == 0) {
X			if (!skipping || !p->skip)
X				(*p->fun)(p->arg, skipping);
X			tk_flags = 0;
X			if (sawnl == 0)
X				tk_flags |= TK_ONLY1;
X			return;
X		}
X	error("bad # command");
X}
X
XNODEP
Xtok_to_node()
X{
X	register struct tok *tp;
X	register NODEP np;
X
X	tp = &curtok;
X	np = allocnode();
X	np->e_token = tp->tnum;
X	np->e_flags = tp->flags;
X	if (tp->prec)	/* binary op */
X		np->e_prec = tp->prec;
X	else
X	switch (np->e_token) {
X	case ICON:
X		np->e_ival = tp->ival;
X		break;
X	case FCON:
X		np->e_fval = tp->fval;
X		break;
X	}
X	nscpy(np, tp->name);
X	return np;
X}
X
XNODEP
Xid_tok(s)
Xchar *s;
X{
X	NODEP np;
X
X	np = allocnode();
X	np->e_token = ID;
X	nscpy(np, s);
X	return np;
X}
X
X#endif
END_OF_FILE
if test 14315 -ne `wc -c <'hcc/PRE.C'`; then
    echo shar: \"'hcc/PRE.C'\" unpacked with wrong size!
fi
# end of 'hcc/PRE.C'
fi
echo shar: End of archive 7 \(of 9\).
cp /dev/null ark7isdone
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