[comp.sources.atari.st] v02i095: sozobon1.2 -- Update to Sozobon C compiler part04/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 95
Archive-name: sozobon1.2/part04

#! /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 4 (of 9)."
# Contents:  hcc/D2.C hcc/DECL.C hcc/EXPR.C hcc/TOK.C
# Wrapped by koreth@panarthea on Tue Oct 24 18:40:45 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'hcc/D2.C' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'hcc/D2.C'\"
else
echo shar: Extracting \"'hcc/D2.C'\" \(9938 characters\)
sed "s/^X//" >'hcc/D2.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 *	d2.c
X *
X *	Declaration subroutines
X *
X *	Mostly routines for initializations
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 NODEP cur;
Xextern NODEP symtab[];
Xextern level;
X
Xextern int oflags[];
X#define debugi	oflags['i'-'a']
X
Xsu_size(lp, cp, xp, isunion)
Xregister long *lp;
Xchar *cp;
Xregister NODE *xp;
X{
X	long sz;
X	char al;
X
X	sz = xp->n_tptr->t_size;
X	al = xp->n_tptr->t_aln;
X	if (isunion) {
X		*lp = *lp > sz ? *lp : sz;
X	} else {
X		while (al & (*lp)) {	/* align new field */
X			(*lp)++;
X			xp->e_offs++;
X		}
X		*lp += sz;
X	}
X	*cp = *cp > al ? *cp : al;
X}
X
Xlc_size(lp, rp, xp)
Xregister long *lp;
Xint *rp;
Xregister NODE *xp;
X{
X	long sz;
X	char al;
X	long arg_size();
X#ifdef LAT_HOST
X	long tsz;
X#endif
X
X	if (level > 1 && xp->e_sc == K_REGISTER) {
X		if (lc_reg(rp, xp))
X			return;
X		else
X			xp->e_sc = K_AUTO;
X	}
X	if (xp->e_sc == K_AUTO || level == 1) {
X		sz = xp->n_tptr->t_size;
X		al = xp->n_tptr->t_aln;
X		while (al & (*lp)) {	/* align new field */
X			(*lp)++;
X			xp->e_offs++;
X		}
X		if (level == 1) {
X#ifndef LAT_HOST
X			sz = arg_size(sz,xp);
X#else
X			tsz = arg_size(sz,xp);
X			sz = tsz;
X#endif
X			xp->e_offs += ARG_BASE + *lp;
X		}
X		*lp += sz;
X		if (level != 1)
X			xp->e_offs = LOC_BASE - *lp;
X	}
X}
X
Xsu_fld(lp, alp, xp, fldw, fop)
Xregister long *lp;
Xchar *alp;
Xregister NODE *xp;
Xint *fop;
X{
X	if (*alp < ALN_I)
X		*alp = ALN_I;
X	if (fldw == 0) {
X		afterfld(lp, fop);
X		return;
X	}
X	if (fldw + *fop > 8*SIZE_I)
X		afterfld(lp, fop);
X	if (xp) {
X		xp->e_fldw = fldw;
X		xp->e_fldo = *fop;
X	}
X	*fop += fldw;
X}
X
Xafterfld(szp, fop)
Xlong *szp;
Xint *fop;
X{
X	if (*fop) {
X		*szp += SIZE_I;
X		*fop = 0;
X	}
X}
X
Xok_gsh(sc, np)
XNODE *np;
X{
X	if (sc == K_REGISTER || sc == K_AUTO) {
X		error("reg/auto outside fun");
X		return 0;
X	}
X	return ok_ty(np, NULL);
X}
X
Xok_gx(np, endp)
XNODEP np, endp;
X{
X	if (np)
X		return ok_ty(np->n_tptr, endp);
X	return 0;
X}
X
Xok_lsh(sc, np)
XNODE *np;
X{
X	return ok_ty(np, NULL);
X}
X
Xarytoptr(np)
XNODEP np;
X{
X	NODEP tp = np->n_tptr;
X	NODEP copyone();
X
X	if (np->n_flags & N_COPYT) {	/* cant change if a dupl. */
X		tp = copyone(tp);
X		np->n_tptr = tp;
X		np->n_flags &= ~N_COPYT;
X	}
X	tp->t_token = STAR;
X	strcpy(tp->n_name, "Aptr to");
X}
X
Xok_lx(np,endp)
XNODEP np, endp;
X{
X	if (np) {
X		if (level == 1 && np->n_tptr->t_token == '[')
X			arytoptr(np);
X		return ok_ty(np->n_tptr, endp);
X	}
X	return 0;
X}
X
Xok_suh(np)
XNODEP np;
X{
X	return 1;
X}
X
Xok_sux(np, endp)
XNODEP np, endp;
X{
X	if (np)
X		return ok_ty(np->n_tptr, endp);
X	return 0;
X}
X
Xok_enx(np, endp)
XNODEP np, endp;
X{
X	if (np && np->n_tptr == endp)	/* no modifiers */
X		return 1;
X	return 0;
X}
X
Xok_cast(np, endp)
XNODEP np, endp;
X{
X	if (np)
X		return ok_ty(np, endp);
X	return 0;
X}
X
Xok_ty(np, endp)
Xregister NODEP np, endp;
X{
X	NODEP child;
X	long csize;
X	long conlval();
X
X	if (np == endp)
X		return 1;
X	child = np->n_tptr;
X	if (child) {
X		if (ok_ty(child, endp) == 0)
X			return 0;
X		csize = child->t_size;
X	}
X
X	switch (np->t_token) {
X	case STAR:
X		np->t_size = SIZE_P;
X		np->t_aln = ALN_P;
X		break;
X	case '(':
X		/* size 0 okay - fun ret void */
X		if (child->t_token == '[') {
X			error("bad func");
X			return 0;
X		}
X		/* size 0 */
X		break;
X	case '[':
X		if (csize == 0) {
X			error("bad array");
X			return 0;
X		}
X		if (np->n_right) {
X			csize *= conlval(np->n_right);
X			np->n_right = NULL;
X			np->t_size = csize;
X		}
X		np->t_aln = child->t_aln;
X		break;
X	default:
X		return 1;
X	}
X	return 1;
X}
X
Xok_revx(rv,forcast)
XNODEP rv;
X{
X	if (rv == NULL)
X		return 1;
X	if (forcast == 0 && rv->e_token != ID) {
X		error("need ID");
X		return 0;
X	}
X	if (forcast && rv->e_token == ID) {
X		error("ID in cast");
X		return 0;
X	}
X	return 1;
X}
X
Xopt_ginit(xp)
XNODEP xp;
X{
X	if (xp->e_token != ID)
X		return;
X	if (xp->n_tptr->t_token == '(')
X		return;
X	switch (xp->e_sc) {
X	case K_STATIC:
X	case HERE_SC:
X		if (cur->e_token == '=') {
X			out_gv(xp, 0);
X			fadvnode();
X			g_init(xp->n_tptr);
X		} else
X			out_gv(xp, 1);
X	}
X}
X
Xopt_linit(xp)
XNODEP xp;
X{
X	if (xp->e_token != ID)
X		return;
X	if (xp->n_tptr->t_token == '(')
X		return;
X	switch (xp->e_sc) {
X	case K_STATIC:
X		if (cur->e_token == '=') {
X			out_gv(xp, 0);
X			fadvnode();
X			g_init(xp->n_tptr);
X		} else
X			out_gv(xp, 1);
X		to_text();
X		break;
X	case K_AUTO:
X	case K_REGISTER:
X		if (cur->e_token == '=')
X			a_init(xp);
X		break;
X	}
X}
X
Xa_init(op)
XNODEP op;
X{
X	register NODEP np, xp;
X	NODEP assignx(), copynode();
X
X	np = cur;  advnode();
X	xp = assignx();
X	op = copynode(op);
X	np->n_left = op;
X	np->n_right = xp;
X	np->e_type = E_BIN;
X	do_expr(np, FORSIDE);
X	return;
X}
X
Xopt_enval(intp)
Xint *intp;
X{
X	NODEP np;
X	NODEP questx();
X
X	if (cur->e_token == '=') {
X		fadvnode();
X		np = questx();
X		*intp = conxval(np);
X		return;
X	}
X}
X
Xopt_field(xp,wdp,isunion)
XNODE *xp;
Xint *wdp;
X{
X	NODEP np;
X	NODEP questx();
X	int i;
X
X	*wdp = -1;
X	if (isunion) return;
X	if (cur->e_token == ':') {
X		fadvnode();
X		np = questx();
X		i = conxval(np);
X		if (i > 8*SIZE_I) {
X			error("field too big");
X			i = 8*SIZE_I;
X		}
X		if (xp) {
X			if (i <= 0 || bad_fty(xp->n_tptr)) {
X				error("bad field");
X				return;
X			}
X		} else if (i < 0) {
X			error("neg field width");
X			return;
X		}
X		*wdp = i;
X		return;
X	}
X}
X
Xbad_fty(tp)
XNODEP tp;
X{
X	int tok;
X
X	tok = tp->t_token;
X	if (tok == K_INT || tok == K_UNSIGNED)
X		return 0;
X	return 1;
X}
X
Xfield(xp, wd, ofp)
XNODEP xp;
Xint *ofp;
X{
X}
X
XNODEP
Xdef_type()
X{
X	NODEP bas_type();
X
X	return bas_type(K_INT);
X}
X
X#define NSC	LAST_SC-FIRST_SC+1
X#define NBAS	LAST_BAS-FIRST_BAS+1
X
XNODE basics[NBAS];
XNODE str_ptr, fun_int;
X
Xstruct bt {
X	char	*name;
X	int	size;
X	char	align;
X} btbl[] = {
X	{"Uchar",	SIZE_C, ALN_C},
X	{"Ulong",	SIZE_L, ALN_L},
X	{"Long",	SIZE_L,	ALN_L},
X	{"Short",	SIZE_S, ALN_S},
X	{"Uns",		SIZE_U, ALN_U},
X	{"Int",		SIZE_I, ALN_I},
X	{"Char",	SIZE_C, ALN_C},
X	{"Float",	SIZE_F, ALN_F},
X	{"Dbl",		SIZE_D, ALN_D},
X	{"Void",	0},
X};
X
XNODEP
Xbas_type(btype)
X{
X	NODEP rv;
X	static once = 0;
X
X	if (once == 0) {
X		once++;
X
X		sprintf(str_ptr.n_name, "Ptr to");
X		str_ptr.t_token = STAR;
X		str_ptr.n_tptr = bas_type(K_CHAR);
X		str_ptr.n_flags = N_COPYT;
X		str_ptr.t_size = SIZE_P;
X		str_ptr.t_aln = ALN_P;
X
X		sprintf(fun_int.n_name, "Fun ret");
X		fun_int.t_token = '(';
X		fun_int.n_tptr = bas_type(K_INT);
X		fun_int.n_flags = N_COPYT;
X	}
X	if (btype == SCON)
X		return &str_ptr;
X	else if (btype == '(')
X		return &fun_int;
X	rv = &basics[btype-FIRST_BAS];
X	if (rv->t_token == 0) {
X		rv->t_token = btype;
X		rv->t_size = btbl[btype-FIRST_BAS].size;
X		rv->t_aln = btbl[btype-FIRST_BAS].align;
X		sprintf(rv->n_name, btbl[btype-FIRST_BAS].name);
X	}
X	return rv;
X}
X
X/* new function name seen in expr */
XNODEP
Xnew_fun(op)
XNODE *op;
X{
X	NODEP np;
X	NODEP copyone();
X
X	/* we know left, right and tptr are NULL */
X	np = copyone(op); /* ID node */
X	np->n_tptr = bas_type('(');
X	np->n_flags = N_COPYT;
X	np->e_sc = K_EXTERN;
X	new_sym(symtab, np);
X	return np;
X}
X
X/* declare arg name as int */
Xdef_arg(listpp, op)
XNODE **listpp, *op;
X{
X	register NODEP np;
X	NODEP copyone();
X
X	np = copyone(op);
X	np->n_tptr = bas_type(K_INT);
X	np->n_flags = N_COPYT;
X	np->e_sc = K_AUTO;
X	new_sym(listpp, np);
X}
X
X/* initialize 0 or 1 thing of any type (tp) */
Xg_init(tp)
Xregister NODEP tp;
X{
X	int nsee;
X	long sz;
X	int oldsize;
X	int seebr = 0;
X
X	if (cur->e_token == SCON &&
X		   tp->t_token == '[' &&
X		   tp->n_tptr->t_token == K_CHAR) { /* hack for SCON ary */
X			nsee = out_scon(cur);
X			fadvnode();
X			a_fix(tp, nsee);
X			return 1;
X	}
X
X	if (cur->e_token == '{') {
X		fadvnode();
X		seebr = 1;
X	}
X
X	switch (tp->t_token) {
X	case '[':
X		if (tp->t_size)
X			oldsize = tp->t_size / tp->n_tptr->t_size;
X		else
X			oldsize = 0;
X		nsee = inita(tp->n_tptr, oldsize);
X		if (nsee)
X			a_fix(tp, nsee);
X		break;
X	case K_STRUCT:
X		o_aln(tp->t_aln);
X		nsee = inits(tp->n_right);
X		break;
X	case K_UNION:
X		o_aln(tp->t_aln);
X		nsee = g_init(tp->n_right->n_tptr);
X		if (nsee) {
X			sz = tp->t_size - tp->n_right->n_tptr->t_size;
X			if (sz)
X				o_nz(sz, 0);
X		}
X		break;
X	default:
X		nsee = init1(tp);
X		break;
X	}
X
X	if (seebr) {
X		if (cur->e_token == ',')
X			fadvnode();
X		eat('}');
X	}
X	return nsee ? 1 : 0;
X}
X
X/* initialize one (or 0) scalar to an expr */
Xinit1(tp)
Xregister NODEP tp;
X{
X	NODEP xp;
X	NODEP assignx();
X
X	if (debugi) {
X		printf("init1");
X		printnode(tp);
X	}
X	xp = assignx();
X	if (xp) {
X		if (debugi)
X			printnode(xp);
X		o_vinit(tp, xp);
X		return 1;
X	} else
X		return 0;
X}
X
X/* set array size or fill array with zeros */
Xa_fix(tp, nsee)
Xregister NODEP tp;
X{
X	int oldsize;
X
X	if (tp->t_size) {
X		oldsize = tp->t_size / tp->n_tptr->t_size;
X		if (oldsize > nsee) {
X			o_nz(tp->n_tptr->t_size * (oldsize-nsee),
X				tp->n_tptr->t_aln);
X		} else if (oldsize < nsee) {
X			error("too many init exprs");
X		}
X	} else
X		tp->t_size = nsee * tp->n_tptr->t_size;
X}
X
X/* initialize up to max items of type tp */
X/* if max is 0, any number is okay */
X
Xinita(tp, maxi)
XNODEP tp;
X{
X	int nsee;
X
X	nsee = g_init(tp);
X	if (nsee == 0)
X		return 0;
X
X	while (cur->e_token == ',') {
X		if (nsee == maxi)
X			break;
X		fadvnode();
X		nsee += g_init(tp);
X	}
X	return nsee;
X}
X
X/* initialize (possible) structure */
Xinits(np)
Xregister NODEP np;
X{
X	int see1;
X
X	see1 = g_init(np->n_tptr);
X	if (see1 == 0)
X		return 0;
X
X	while (np->n_next) {
X		np = np->n_next;
X		if (cur->e_token == ',') {
X			fadvnode();
X			see1 = g_init(np->n_tptr);
X		} else
X			see1 = 0;
X		if (see1 == 0)
X			z_init(np->n_tptr);
X	}
X
X	return 1;
X}
X
Xz_init(tp)
Xregister NODEP tp;
X{
X	switch (tp->t_token) {
X	case '[':
X	case K_STRUCT:
X	case K_UNION:
X		o_nz(tp->t_size, tp->t_aln);
X		break;
X	default:
X		out_zi(tp);
X	}
X}
END_OF_FILE
if test 9938 -ne `wc -c <'hcc/D2.C'`; then
    echo shar: \"'hcc/D2.C'\" unpacked with wrong size!
fi
# end of 'hcc/D2.C'
fi
if test -f 'hcc/DECL.C' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'hcc/DECL.C'\"
else
echo shar: Extracting \"'hcc/DECL.C'\" \(10944 characters\)
sed "s/^X//" >'hcc/DECL.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 *	decl.c
X *
X *	Do all declarations
X *
X *	Currently, 
X *		struct tags are local
X *		struct members are tied to the struct
X *		enum tags are ignored
X *		enum members are local
X */
X
X#include <stdio.h>
X#include "param.h"
X#include "tok.h"
X#include "nodes.h"
X
Xextern NODE *cur;
Xextern level;
X
XNODEP symtab[NHASH], tagtab;
Xextern NODE *blktab;
X
XNODEP alltags(), allsyms(), llook(), hlook();
X
Xextern int oflags[];
X#define debug	oflags['v'-'a']
X
X/* look for global data decls
X	return when see something weird
X	return last ID declared */
XNODEP
Xglb_decls()
X{
X	register NODEP head, xp;
X	NODEP d_type(), def_type(), d_declr();
X	int sclass;
X
X	for(;;) {
X		sclass = d_scl(HERE_SC);
X		head = d_type();
X		if (head == NULL)
X			head = def_type();
X		if (ok_gsh(sclass, head) == 0)
X			continue;
X	more:
X		xp = d_declr(head,0);
X		if (ok_gx(xp,head)) {
X			xp->e_sc = sclass;
X			opt_ginit(xp);
X			new_sym(symtab,xp);
X			if (xp->n_tptr->t_token == '(') {	/* func */
X				if (cur->e_token == ',' ||
X				    cur->e_token == ';')
X					fix_fun(xp);
X				else
X					return xp;
X			}
X		}
X
X		if (cur->e_token == ',') {
X			fadvnode();
X			goto more;
X		}
X
X		if (cur->e_token == ';') {
X			fadvnode();
X		} else
X			return NULL;
X	}
X}
X
X/* do local or arg decls
X	return 1 if see something */
Xloc_decls()
X{
X	register NODEP head, xp;
X	NODEP d_type(), def_type(), d_declr();
X	int sclass;
X	int regs;
X	long size;
X	int rv = 0;
X
X	size = level > 2 ? blktab->n_next->b_size : 0;
X	regs = level > 1 ? blktab->n_next->b_regs : 0;
X	while (is_ty_start()) {
X		rv++;
X		sclass = d_scl(K_AUTO);
X		head = d_type();
X		if (head == NULL)
X			head = def_type();
X		if (ok_lsh(sclass, head) == 0)
X			continue;
X	more:
X		xp = d_declr(head,0);
X		if (ok_lx(xp,head)) {
X			xp->e_sc = sclass;
X			if (level > 1) {	/* not args */
X				lc_size(&size, &regs, xp);
X				out_advice(xp);
X			}
X			new_sym(&blktab->b_syms,xp);
X			fix_fun(xp);
X			opt_linit(xp,sclass);
X		}
X
X		if (cur->e_token == ',') {
X			fadvnode();
X			goto more;
X		}
X
X		if (cur->e_token == ';') {
X			fadvnode();
X		} else {
X			error("expect ;");
X			return 1;
X		}
X	}
X	while (STACKALN & size)
X		size++;
X	blktab->b_size = size;
X	blktab->b_regs = regs;
X	return rv;
X}
X
X/* Decls inside Struct/Union */
Xsu_decls(listpp, isunion, sizep, alnp)
XNODEP *listpp;
Xlong *sizep;
Xchar *alnp;
X{
X	register NODEP head, xp;
X	NODEP d_type(), d_declr();
X	long size;
X	char aln;
X	int fldw, fldoff;
X
X	aln = 0;
X	size = 0;
X	fldoff = 0;
X	for(;;) {
X		head = d_type();
X		if (head == NULL)
X			goto out;
X		if (ok_suh(head) == 0)
X			continue;
X	more:
X		xp = d_declr(head,0);
X		opt_field(xp,&fldw,isunion);
X		if (ok_sux(xp,head)) {
X			if (fldw > 0) {	/* handle field */
X				su_fld(&size,&aln,xp,fldw,&fldoff);
X				xp->e_offs = size;
X			} else {		/* handle non-field */
X				afterfld(&size,&fldoff);
X				xp->e_offs = isunion ? 0 : size;
X				su_size(&size,&aln,xp,isunion); 
X			}
X			new_sym(listpp,xp);
X			listpp = &xp->n_next;
X		} else if (fldw == 0) {
X			afterfld(&size, &fldoff);
X		}
X
X		if (cur->e_token == ',') {
X			fadvnode();
X			goto more;
X		}
X
X		if (cur->e_token == ';') {
X			fadvnode();
X		} else
X			goto out;
X	}
Xout:
X	afterfld(&size,&fldoff);
X	while (aln & size)
X		size++;
X	*sizep = size;
X	*alnp = aln;
X	return;
X}
X
X/* Decls inside Enum */
Xen_decls()
X{
X	register NODEP head, xp;
X	NODEP bas_type(), d_declr();
X	int curval = 0;
X
X	for(;;) {
X		head = bas_type(K_INT);
X	more:
X		xp = d_declr(head,0);
X		if (ok_enx(xp,head)) {
X			opt_enval(&curval);
X			xp->e_ival = curval++;
X			xp->e_sc = ENUM_SC;
X			new_sym(level ? blktab->b_syms : (NODE *)symtab,
X				xp);
X		}
X
X		if (cur->e_token == ',') {
X			fadvnode();
X			goto more;
X		}
X
X		return;
X	}
X}
X
X/*
X * called from expr.c, make a cast
X * only called if is_ty_start();
X */
XNODE *
Xmakecast()
X{
X	NODEP head, xp;
X	register NODEP np;
X	NODEP d_type(), d_declr(), def_type();
X
X	head = d_type();	/* we know this is not NULL */
X	xp = d_declr(head, 1);
X	if (ok_cast(xp,head) == 0) {
X		xp = def_type();	/* return cast to INT */
X	}
X	np = allocnode();
X	np->e_token = TCONV;
X	np->n_tptr = xp;
X	if (xp == head)
X		np->n_flags |= N_COPYT;
X	if (debug) {
X		printf("Make cast");
X		printnode(np);
X	}
X	return np;
X}
X
Xis_ty_start()
X{
X	NODEP rv;
X
X	if (is_tykw(cur->e_token))
X		return 1;
X	if (cur->e_token == ID) {
X		rv = allsyms(cur);
X		if (rv && rv->e_sc == K_TYPEDEF)
X			return 1;
X	}
X	return 0;
X}
X
X/* assemble decl and put in listpp */
Xnew_sym(listpp, xp)
XNODEP *listpp;
XNODEP xp;
X{
X	NODEP old;
X
X	if (xp == NULL)
X		return 0;
X/* put in table */
X	if (debug) {
X		printf("New sym sc %c", "EARTSCH"[xp->e_sc-K_EXTERN]);
X		printnode(xp);
X	}
X	/* later look for previous definition */
X	if (listpp == (NODE **)symtab) {
X		old = hlook(listpp, xp);
X		if (old == NULL || def2nd(old, xp))
X			puthlist(listpp, xp);
X	} else {
X		old = llook(*listpp, xp);
X		if (old == NULL || def2nd(old, xp))
X			putlist(listpp, xp);
X	}
X	return 1;
X}
X
X/* look for storage class */
Xd_scl(defau)
X{
X	int rv;
X
X	if (is_sclass(cur->e_token)) {
X		rv = cur->e_token;
X		fadvnode();
X		return rv;
X	}
X	/* no storage class specified */
X	return defau;
X}
X
XNODEP
Xd_declr(head, forcast)
XNODEP head;
X{
X	NODEP e1;
X	NODEP declarator(), rev_decl();
X	NODEP xp, tailp;
X
X	e1 = declarator();
X	xp = rev_decl(e1, &tailp, forcast);
X	if (xp) {
X		tailp->n_tptr = head;
X		tailp->n_flags |= N_COPYT;
X		return xp;
X	} else if (forcast)
X		return head;
X	else
X		return NULL;
X}
X
XNODEP
Xrev_decl(np,tailpp,forcast)
XNODEP np, *tailpp;
X{
X	NODEP rv, scan, nxt;
X
X	rv = NULL;
X	for (scan = np; scan != NULL; scan = nxt) {
X		nxt = scan->n_next;
X		scan->n_next = NULL;
X		if (rv == NULL) {
X			*tailpp = scan;
X			scan->n_tptr = NULL;
X			rv = scan;
X		} else {
X			scan->n_tptr = rv;
X			rv = scan;
X		}
X		e_to_t(rv);
X		switch (rv->t_token) {
X		case UNARY '*':
X			sprintf(rv->n_name, "Ptr to");
X			break;
X		case '(':
X			sprintf(rv->n_name, "Fun ret");
X			break;
X		case '[':
X			sprintf(rv->n_name, "Ary of");
X			break;
X		case ID:
X			break;
X		default:
X			error("bad type xpr");
X			return NULL;
X		}
X	}
X	/* if normal decl and see something, must see id first */
X	if (!ok_revx(rv,forcast))
X		rv = NULL;
X	return rv;
X}
X
X/*
X * Looking for type part of a decl
X */
XNODEP
Xd_type()
X{
X	int btype, adj;
X	NODEP rv;
X	NODEP bas_type(), decl_su(), decl_enum();
X
X	/* look for 'struct', 'union', 'enum' or typedef ID */
X	switch (cur->e_token) {
X	case ID:
X		rv = allsyms(cur);
X		if (rv && rv->e_sc == K_TYPEDEF) {
X			fadvnode();
X			rv = rv->n_tptr;
X			return rv;
X		}
X		return NULL;
X	case K_STRUCT:
X		return decl_su(0);
X	case K_UNION:
X		return decl_su(1);
X	case K_ENUM:
X		return decl_enum();
X	}
X
X	/* look for modifiers 'long', 'short', 'unsigned' */
X	adj = 0;
X	while (is_tadj(cur->e_token)) {
X		switch (cur->e_token) {
X		case K_SHORT:
X			adj |= SAW_SHORT;
X			break;
X		case K_LONG:
X			adj |= SAW_LONG;
X			break;
X		case K_UNSIGNED:
X			adj |= SAW_UNS;
X			break;
X		}
X		fadvnode();
X	}
X
X	/* look for base type 'char', 'int', 'float', 'double', 'void'*/
X	if (is_btype(cur->e_token)) {
X		btype = cur->e_token;
X		fadvnode();
X	} else if (adj == 0)	/* saw nothing */
X		return NULL;
X	else
X		btype = K_INT;
X
X	if (adj)
X		btype = adj_type(btype, adj);
X	rv = bas_type(btype);
X	return rv;
X}
X
XNODEP
Xdecl_enum()
X{
X	NODEP bas_type();
X
X	fadvnode();	/* skip 'enum' */
X
X	if (cur->e_token == ID) {	/* ignore tag */
X		fadvnode();
X	}
X	if (cur->e_token == '{') {	/* new declaration */
X		fadvnode();	/* skip '{' */
X		en_decls();	/* global scope */
X		if (cur->e_token != '}')
X			error("expect }");
X		else
X			fadvnode();	/* skip '}' */
X	}
X	return bas_type(K_INT);
X}
X
XNODEP
Xdecl_su(isunion)
X{
X	register NODEP rv, tagp;
X	NODEP *attab;
X	extern lineno;
X
X	fadvnode();	/* skip 'struct' or 'union' */
X
X	attab = level ? &blktab->b_tags : &tagtab;
X	tagp = NULL;
X	if (cur->e_token == ID) {	/* hold on to ID node */
X		tagp = cur;
X		e_to_t(tagp);
X		advnode();
X		nnmadd(tagp, isunion ? ".U" : ".S");
X	}
X	if (cur->e_token == '{') {	/* new declaration */
X		if (tagp == NULL) {	/* make fake name */
X			tagp = allocnode();
X			sprintf(tagp->n_name, isunion ? "%dU" : 
X					"%dS", lineno);
X		}
X		fadvnode();	/* skip '{' */
X		if (rv = llook(*attab, tagp)) {
X			freenode(tagp);
X			if (rv->n_right) {
X				errors("struct redefined", rv->n_name);
X				freenode(rv->n_right);
X				rv->n_right = NULL;
X			}
X		} else {		/* new defn */
X			rv = tagp;
X			rv->t_token = isunion ? K_UNION : K_STRUCT;
X			rv->n_flags |= N_BRKPR;	/* break print loops */
X			putlist(attab, rv);
X		}
X		su_decls(&rv->n_right, isunion,
X				&rv->t_size, &rv->t_aln);
X		if (cur->e_token != '}')
X			error("expect }");
X		else
X			fadvnode();	/* skip '}' */
X	} else {		/* reference to old */
X		if (tagp == NULL) {
X			error("nonsense struct");
X			goto out;
X		}
X		/* ANSI special decl
X			struct <tag> ;
X		   for hiding old tag within block */
X		if (cur->e_token == ';' && level)
X			rv = llook(*attab, tagp);
X		else
X			rv = alltags(tagp);
X		if (rv == NULL) {	/* delayed tag */
X			rv = tagp;
X			rv->t_token = isunion ? K_UNION : K_STRUCT;
X			rv->n_flags |= N_BRKPR;	/* break print loops */
X			putlist(attab, rv);
X			goto out;
X		} else
X			freenode(tagp);
X	}
Xout:
X	return rv;
X}
X
XNODE *
Xalltags(np)
XNODE *np;
X{
X	register NODE *bp;
X	NODE *rv;
X
X	for (bp=blktab; bp != NULL; bp = bp->n_next)
X		if ((rv = llook(bp->b_tags, np)) != NULL)
X			return rv;
X	return llook(tagtab, np);
X}
X
XNODE *
Xallsyms(np)
XNODE *np;
X{
X	register NODE *bp;
X	NODE *rv;
X
X	for (bp=blktab; bp != NULL; bp = bp->n_next)
X		if ((rv = llook(bp->b_syms, np)) != NULL)
X			return rv;
X	return hlook(symtab, np);
X}
X
Xsim_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_size != b->t_size && a->t_size && b->t_size)
X		return 0;
X	a = a->n_tptr;
X	b = b->n_tptr;
X	goto more;
X}
X
X/* 2nd def of same name at same level */
X/* OK if one extern and types the same */
Xdef2nd(old,new)
XNODEP old, new;
X{
X	int osc, nsc;
X
X	if (sim_type(old->n_tptr, new->n_tptr) == 0)
X		goto bad;
X	osc = old->e_sc;
X	nsc = new->e_sc;
X	if (nsc == K_EXTERN) {	/* works only if no further use allowed */
X		freenode(new);
X		return 0;
X	}
X	if (osc == K_EXTERN) {
X		/* replace old def with new one */
X		/* for now, just put new one on list too */
X		return 1;
X	}
Xbad:
X	errorn("bad 2nd decl of ", new);
X	/* use 2nd def so other stuff works */
X	return 1;
X}
X
X/* saw fun but no body */
Xfix_fun(np)
XNODE *np;
X{
X	if (np == NULL) return;
X	if (np->n_tptr->t_token == '(') {	/* fix to extern */
X		if (np->e_sc != K_TYPEDEF)
X			np->e_sc = K_EXTERN;
X	}
X}
X
Xe_to_t(np)
XNODE *np;
X{
X	int token;
X
X	token = np->e_token;
X	np->t_token = token;
X	np->t_size = 0;
X	np->t_aln = 0;
X}
END_OF_FILE
if test 10944 -ne `wc -c <'hcc/DECL.C'`; then
    echo shar: \"'hcc/DECL.C'\" unpacked with wrong size!
fi
# end of 'hcc/DECL.C'
fi
if test -f 'hcc/EXPR.C' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'hcc/EXPR.C'\"
else
echo shar: Extracting \"'hcc/EXPR.C'\" \(9558 characters\)
sed "s/^X//" >'hcc/EXPR.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 *	expr.c
X *
X *	Expression parse routines
X *
X *	All routines return either NULL or a valid tree
X *		binop nodes have non-null left and right
X *		unop nodes have non-null left
X *
X *	Special nodes:
X *		'(' : function call.  left:name-expr right:args 
X *		',': if part of function arg list, ival:num. descendants
X *		'?' : ?switch.  left:test-expr right:':' part
X *		  ':' : left:true-expr right:false-expr
X *		TCONV: left:convertee tptr:type-list
X *		TSIZEOF: tptr:type-list
X *
X */
X
X#include <stdio.h>
X#include "param.h"
X#include "nodes.h"
X#include "tok.h"
X
Xextern NODEP cur;
XNODEP getnode();
XNODEP opt_follow();
X
Xextern int oflags[];
X#define debug oflags['x'-'a']
X
Xadvnode()
X{
X	cur = getnode();
X}
X
Xfadvnode()
X{
X	freenode(cur);
X	cur = getnode();
X}
X
XNODEP
Xgete_or_ty()
X{
X	NODEP getexpr(), makecast();
X	NODEP rv;
X
X	if (is_ty_start()) {
X		rv = makecast();
X		if (debug) {
X			printf("TY_X");
X			printnode(rv);
X		}
X		return rv;
X	} else
X		return getexpr();
X}
X
X/* call this for any expr including comma's */
XNODEP
Xgetexpr()
X{
X	NODEP np, get_f_expr();
X
X	np = get_f_expr(0);
X	return np;
X}
X
XNODEP
Xget_f_expr(flg)
Xint flg;
X{
X	NODEP assignx();
X	register NODEP op, lpart, rpart;
X	int i = 0;
X
X	lpart = assignx();
X	if (lpart == NULL) {
X		return NULL;
X	}
X	i++;
Xmore:
X	if (cur->e_token != ',')
X		return lpart;
X
X	op = cur;  advnode();
X	rpart = assignx();
X	if (rpart == NULL) {
X		error("',' expr syntax");
X		return lpart;
X	}
X	i++;
X	op->n_left = lpart;
X	op->n_right = rpart;
X	op->e_type = E_BIN;
X	op->e_ival = flg ? i : 0;
X	lpart = op;
X	if (debug) {
X		printf("COMMA");
X		printnode(op);
X	}
X	goto more;
X}
X
X/* call this if you want expr w/o comma's */
XNODEP
Xassignx()
X{
X	NODEP questx();
X	register NODEP op, lpart, rpart;
X
X	lpart = questx();
X	if (lpart == NULL)
X		return NULL;
X	if (!isassign(cur->e_token) && cur->e_token != '=')
X		return lpart;
X	op = cur;  advnode();
X	rpart = assignx();
X	if (rpart == NULL) {
X		error("'=op' expr syntax");
X		return lpart;
X	}
X	op->n_left = lpart;
X	op->n_right = rpart;
X	op->e_type = E_BIN;
X	if (debug) {
X		printf("ASSIGN");
X		printnode(op);
X	}
X	return op;
X}
X
X/* call this if you want expr w/o assign's or comma's */
X/* i.e. constant-expression */
XNODEP
Xquestx()
X{
X	NODEP binary();
X	register NODEP holdq, holdc;
X	NODEP qpart, tpart, fpart;
X
X	qpart = binary();
X	if (qpart == NULL)
X		return NULL;
X	if (cur->e_token != '?')
X		return qpart;
X	holdq = cur;  advnode();
X	tpart = questx();
X	if (tpart == NULL || cur->e_token != ':') {
Xbad:
X		error("'?:' expr syntax");
X		return qpart;
X	}
X	holdc = cur;  advnode();
X	fpart = questx();
X	if (fpart == NULL) goto bad;
X	holdc->n_left = tpart;
X	holdc->n_right = fpart;
X	holdc->e_type = E_BIN;
X	holdq->n_left = qpart;
X	holdq->n_right = holdc;
X	holdq->e_type = E_BIN;
X	if (debug) {
X		printf("QUEST");
X		printnode(holdq);
X	}
X	return holdq;
X}
X
XNODEP
Xbinary()
X{
X	NODEP unary(), buildbin();
X	register NODEP rv, op, e2;
X
X	rv = unary();
X	if (rv == NULL)
X		return NULL;
X	rv->e_prec = 0;
Xmore:
X	if (cur->e_prec == 0)	/* not binary op */
X		return rv;
X	op = cur;  advnode();
X	e2 = unary();
X	if (e2 == NULL) {
X		error("bin-op expr syntax");
X		return rv;
X	}
X	e2->e_prec = 0;
X	rv = buildbin(rv, op, e2);
X	if (debug) {
X		printf("BINARY");
X		printnode(rv);
X	}
X	goto more;
X}
X
XNODEP
Xbuildbin(lpart, op, upart)
XNODEP lpart, op, upart;
X{
X	register NODEP look, tail;
X	NODEP rv;
X
X	tail = NULL;
X	look = lpart;
X	for (look=lpart; op->e_prec < look->e_prec; look=look->n_right)
X		tail = look;
X	if (tail == NULL) {
X		op->n_left = lpart;
X		op->n_right = upart;
X		rv = op;
X	} else {
X		tail->n_right = op;
X		op->n_left = look;
X		op->n_right = upart;
X		rv = lpart;
X	}
X	op->e_type = E_BIN;
X	return rv;
X}
X
XNODEP
Xunary()
X{
X	register NODEP tp,e1;
X	NODEP primary();
X
X	if (cur->e_flags & CAN_U) {
X		tp = cur;  advnode();
X		if (tp->e_prec) {  /* also have BINARY op */
X			tp->e_token = UNARY tp->e_token;
X			strcat(tp->n_name, "U");
X		}
X		tp->n_left = unary();
X		tp->e_type = E_UNARY;
X		goto check;
X	} else
X	switch (cur->e_token) {
X	case '(':
X		fadvnode();
X		tp = gete_or_ty();
X		if (cur->e_token != ')') {
X			error("missing )");
X		} else
X			fadvnode();
X		if (tp == NULL)
X			return NULL;
X		if (tp->e_token == TCONV && tp->n_left == NULL) {
X			sprintf(tp->n_name, "cast to");
X			tp->n_left = unary();
X			tp->e_type = E_UNARY;
X		} else {
X			tp = opt_follow(tp);
X			goto out;
X		}
X		goto check;
X	case K_SIZEOF:
X		tp = cur;
X		advnode();
X		if (cur->e_token == '(') { /* may be type expr */
X			fadvnode();
X			e1 = gete_or_ty();
X			if (cur->e_token != ')') {
X				error("missing )");
X			} else
X				fadvnode();
X		} else
X			e1 = unary();
X		if (e1 == NULL) {
X			error("sizeof expr syntax");
X			return NULL;
X		}
X		if (e1->e_token == TCONV) {
X			freeunit(tp);
X			e1->e_token = TSIZEOF;
X			sprintf(e1->n_name, "T-sizeof");
X			tp = e1;
X			tp->e_type = E_LEAF;
X			goto out;
X		} else {
X			tp->e_type = E_UNARY;
X			tp->n_left = e1;
X		}
X		goto check;
X	default:
X		tp = primary();
X		goto out;
X	}
Xcheck:
X	if (tp == NULL) return NULL;
X	if (tp->n_left == NULL) {
X		error("u-op expr syntax");
X		return NULL;
X	}
Xout:
X	if (debug) {
X		printf("UNARY");
X		printnode(tp);
X	}
X	return tp;
X}
X
XNODEP
Xprimary()
X{
X	register NODEP e1;
X
X	switch (cur->e_token) {
X	case ID:
X	case ICON:
X	case FCON:
X	case SCON:
X		e1 = cur;
X		e1->e_type = E_LEAF;
X		advnode();
X		break;
X	case '(':
X		fadvnode();
X		e1 = getexpr();
X		if (cur->e_token != ')')
X			error("missing )");
X		else
X			fadvnode();
X		break;
X	default:
X		e1 = NULL;
X	}
X	if (e1 == NULL)
X		return NULL;
X	return opt_follow(e1);
X}
X
XNODEP
Xopt_follow(np)
XNODEP np;
X{
X	register NODEP tp, e1, t2;
X
X	switch (cur->e_token) {
X	case '[':
X		tp = cur;  advnode();
X		e1 = getexpr();
X		if (cur->e_token != ']') {
X			error("missing ]");
X			return np;
X		} else {
X			t2 = cur;  advnode();
X		}
X		if (e1 == NULL) {
X			error("empty []");
X			return np;
X		}
X		t2->n_left = np;
X		t2->n_right = e1;
X		t2->e_type = E_BIN;
X		t2->e_token = '+';
X		strcpy(t2->n_name, "+ [");
X
X		tp->n_left = t2;
X		tp->e_type = E_UNARY;
X		tp->e_token = STAR;
X		strcpy(tp->n_name, "U*");
X
X		goto out;
X	case '(':
X		tp = cur;
X		advnode();
X		e1 = get_f_expr(1);
X		if (cur->e_token != ')')
X			error("expect )");
X		else
X			fadvnode();
X		tp->n_left = np;
X		tp->n_right = e1;
X		tp->e_type = E_SPEC;
X		goto out;
X	case '.':
X	case ARROW:
X		tp = cur;  advnode();
X		if (cur->e_token != ID) {
X			error("expect ID");
X			return np;
X		}
X		tp->n_left = np;
X		tp->n_right = cur;
X		tp->e_type = E_SPEC;
X		if (tp->e_token == ARROW) { /* make into (*X).Y */
X			tp->e_token = '.';
X			strcpy(tp->n_name, ".");
X
X			t2 = allocnode();
X			t2->e_token = STAR;
X			t2->n_left = np;
X			t2->e_type = E_UNARY;
X			strcpy(t2->n_name, "U*");
X
X			tp->n_left = t2;	
X		}
X		advnode();
X		goto out;
X	case DOUBLE '+':
X	case DOUBLE '-':
X		tp = cur;  advnode();
X		tp->e_token = (tp->e_token == DOUBLE '+') ? POSTINC : POSTDEC;
X		strcat(tp->n_name, "post");
X		tp->n_left = np;
X		tp->e_type = E_UNARY;
X		goto out;
X	default:
X		return np;
X	}
Xout:
X	return opt_follow(tp);
X}
X
X/* restricted version of unary for declarations or coertions */
X/* allows NULL primary part */
XNODEP
Xdeclarator()
X{
X	register NODEP tp,e1;
X	NODEP ty_primary(), ty_follow();
X
X	if (cur->e_token == '*') {
X		tp = cur;
X		tp->e_token = UNARY tp->e_token;
X		strcat(tp->n_name, "U");
X		advnode();
X		tp->n_left = declarator();
X		return tp;
X	} else
X	switch (cur->e_token) {
X	case '(':
X		tp = cur;
X		advnode();
X		e1 = declarator();
X		if (cur->e_token != ')') {
X			error("expect )");
X		} else
X			fadvnode();
X		if (e1 == NULL) {	/* special "fun of" */
X			/* left and right already NULL */
X			return ty_follow(tp);
X		} else {
X			freeunit(tp);
X			return ty_follow(e1);
X		}
X	default:
X		return ty_primary();
X	}
X}
X
X/* restricted version of primary for "declarator" */
XNODEP
Xty_primary()
X{
X	register NODEP e1;
X	NODEP ty_follow();
X
X	switch (cur->e_token) {
X	case ID:
X		e1 = cur;
X		advnode();
X		break;
X	case '(':
X		fadvnode();
X		e1 = declarator();
X		if (cur->e_token != ')')
X			error("expect )");
X		else
X			fadvnode();
X		break;
X	default:
X		e1 = NULL;
X	}
X	return ty_follow(e1);
X}
X
X/* restricted version of opt_follow for 'declarator' */
X/* allow null [] */
XNODEP
Xty_follow(np)
XNODEP np;
X{
X	register NODEP tp, e1;
X	NODEP ty_args();
X
X	switch (cur->e_token) {
X	case '[':
X		tp = cur;
X		advnode();
X		e1 = questx();
X		if (cur->e_token != ']')
X			error("expect ]");
X		else
X			fadvnode();
X		tp->n_left = np;
X		tp->n_right = e1;
X		goto out;
X	case '(':
X		tp = cur;
X		advnode();
X		e1 = ty_args();	/* allow args of fun to follow */
X		if (cur->e_token != ')')
X			error("expect )");
X		else
X			fadvnode();
X		tp->n_left = np;
X		tp->n_right = e1;
X		goto out;
X	default:
X		return np;
X	}
Xout:
X	return ty_follow(tp);
X}
X
X/* called for args of function declaration or NULL */
XNODEP
Xty_args()
X{
X	NODEP opt_id();
X	register NODEP rv, tail, new;
X
X	rv = opt_id();
X	if (rv == NULL)
X		return NULL;
X	tail = rv;
Xmore:
X	if (cur->e_token != ',')
X		return rv;
X	fadvnode();
X	new = opt_id();
X	if (new == NULL) {
X		error("expect as-op value");
X		return rv;
X	}
X	tail->n_left = new;
X	tail = new;
X	goto more;
X}
X
XNODEP
Xopt_id()
X{
X	NODEP rv;
X
X	if (cur->e_token == ID) {
X		rv = cur;
X		advnode();
X		return rv;
X	} else
X		return NULL;
X}
END_OF_FILE
if test 9558 -ne `wc -c <'hcc/EXPR.C'`; then
    echo shar: \"'hcc/EXPR.C'\" unpacked with wrong size!
fi
# end of 'hcc/EXPR.C'
fi
if test -f 'hcc/TOK.C' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'hcc/TOK.C'\"
else
echo shar: Extracting \"'hcc/TOK.C'\" \(10934 characters\)
sed "s/^X//" >'hcc/TOK.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 *	tok.c
X *
X *	Basic level token routines
X *
X *	At this level, we return the following things:
X *		id's - strings of alpha-alnum
X *		integer constants
X *		float constants
X *		string constants
X *		multi-char tokens
X *
X *	We DONT know about:
X *		keywords
X *		#defined id's
X *		any other meaning of a name
X *
X *	Interface:
X *		call nxttok() to get next token
X *		look at 'curtok' for current token
X *		note that curtok.name points to a static area
X *		  for ID or SCON
X *
X *		if EOF is seen, we call endfile() before
X *		  giving up
X *
X *	Special flags:  (tk_flags)
X *		These special flags are needed for the pre-processor.
X *		All but TK_SEENL are 1-shot.
X *
X *		TK_SEENL - want to see \n
X *		TK_WS - want to see white space (for #define)
X *		TK_NOESC - dont do '\' escapes in strings
X *		TK_LTSTR - '<' is a string starter
X *		TK_ONLY1 - skip to token after \n  (for #if--)
X */
X
X#include <stdio.h>
X#include "param.h"
X#include "tok.h"
X
X#if dLibs
X#include <ctype.h>
X#endif
X
Xstruct tok curtok;
Xchar curstr[MAXSTR+1];
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
Xint tk_flags, sawnl;
X
Xextern FILE *input;
Xextern int lineno;
X
X#define NOCHAR	0x100
X
X#ifdef DEBUG
Xextern int oflags[];
X#define debug oflags['b'-'a']
X#endif
X
Xnxttok()
X{
X	register struct tok *t;
X	char *getname();
X	long getnum();
X	register int c;
X	double getfrac();
X
X	t = &curtok;
X	t->name = curstr;
X	t->name[0] = 0;
X	t->prec = 0;
X	t->flags = 0;
Xmore:
X	c = mygetchar();
X	if (c == EOF) {
X		tk_flags = 0;
X		return 0;
X	}
X	if (c == '\n') {
X		tk_flags &= ~TK_ONLY1;
X		if ((tk_flags & TK_SEENL) == 0)
X			goto more;
X		t->tnum = NL;
X		t->name = "\n";
X		goto out;
X	}
X	if (tk_flags & TK_ONLY1)
X		goto more;
X	if (c <= ' ') {
X		if ((tk_flags & TK_SEEWS) == 0)
X			goto more;
X		t->tnum = WS;
X		t->name = " ";
X		goto out;
X	}
X	if (c >= '0' && c <= '9') {
X		t->tnum = ICON;
X		t->ival = getnum(c);
X		if (lookfrac(t->ival) || lookexp(t->ival,0.0))
X			goto out;
X	moresuf:
X		c = mygetchar();
X		if (tolower(c) == 'l') {
X			t->flags |= SEE_L;
X			goto moresuf;
X		} else if (tolower(c) == 'u') {
X			t->flags |= SEE_U;
X			goto moresuf;
X		} else {
X			myungetc(c);
X		}
X		sprintf(curstr, "%ld",
X			t->ival);
X		goto out;
X	}
X	if (isalpha(c) || c == '_') {
X		t->tnum = ID;
X		t->name = getname(c);
X		goto out;
X	}
X	if (c == '.') {
X		c = mygetchar();
X		if (c >= '0' && c <= '9') {
X			gotfrac(0L, getfrac(c));
X			goto out;
X		} else {
X			myungetc(c);
X			matchop('.');
X			goto out;
X		}
X	}
X	if(matchop(c) == 0)
X		goto more;
Xout:
X	if (debug) printf("<%s>", t->name);
X	tk_flags &= TK_SEENL;	/* all but SEENL are 1-shot */
X	return 1;
X}
X
Xlong
Xgetnum(c)
Xregister int c;
X{
X	register long val = 0;
X	int base, i;
X
X	if (c == '0') {
X		base = 8;
X	} else {
X		base = 10;
X		val = c - '0';
X	}
Xmore:
X	c = mygetchar();
X	if (c == EOF)
X		return val;
X	if (tolower(c) == 'x' && val == 0) {
X		base = 16;
X		goto more;
X	}
X	if (c >= '0' && c <= '9') {
X		val = base*val + (c - '0');
X		goto more;
X	}
X	if (base == 16 && (i = ishexa(c))) {
X		val = 16*val + i;
X		goto more;
X	}
X	myungetc(c);
X	return val;
X}
X
Xdouble
Xgetfrac(c)
Xregister c;
X{
X	register double val;
X	register double dig = 0.1;
X
X	val = dig * (c - '0');
Xmore:
X	c = mygetchar();
X	if (c >= '0' && c <= '9') {
X		dig = .1 * dig;
X		val += dig * (c - '0');
X		goto more;
X	}
X	myungetc(c);
X	return val;
X}
X
Xlookfrac(intpart)
Xlong intpart;
X{
X	int c;
X	double frac;
X
X	c = mygetchar();
X	if (c != '.') {
X		myungetc(c);
X		return 0;
X	}
X	c = mygetchar();
X	if (c >= '0' && c <= '9') {
X		frac = getfrac(c);
X	} else {
X		myungetc(c);
X		frac = 0.0;
X	}
X	gotfrac(intpart, frac);
X	return 1;
X}
X
Xgotfrac(intpart, frac)
Xlong intpart;
Xdouble frac;
X{
X	if (lookexp(intpart, frac) == 0)
X		makeflt(intpart, frac, 0);
X}
X
Xlookexp(intpart, frac)
Xlong intpart;
Xdouble frac;
X{
X	int c;
X	int minus;
X	int exp;
X
X	minus = 0;
X	c = mygetchar();
X	if (tolower(c) != 'e') {
X		myungetc(c);
X		return 0;
X	}
X	c = mygetchar();
X	if (c == '-') {
X		minus = 1;
X		c = mygetchar();
X	} else if (c == '+')
X		c = mygetchar();
X	if (c >= '0' && c <= '9') {
X		exp = getnum(c);
X	} else {
X		exp = 0;
X		myungetc(c);
X	}
X	if (minus)
X		exp = -exp;
X	makeflt(intpart, frac, exp);
X	return 1;
X}
X
Xmakeflt(intpart, frac, exp)
Xlong intpart;
Xdouble frac;
X{
X	register double val;
X	double mod, mod10;
X	register struct tok *t;
X
X	val = intpart + frac;
X	if (exp > 0) {
X		mod = 1e1;
X		mod10 = 1e10;
X	} else if (exp < 0) {
X		mod = 1e-1;
X		mod10 = 1e-10;
X		exp = -exp;
X	}
X	while (exp >= 10) {
X		val *= mod10;
X		exp -= 10;
X	}
X	while (exp--)
X		val *= mod;		/* slow and dirty */
X	t = &curtok;
X	t->tnum = FCON;
X	t->fval = val;
X	sprintf(t->name, FLTFORM, val);
X}
X
Xchar *
Xgetname(c)
Xregister int c;
X{
X	register int nhave;
X
X	nhave = 0;
X	do {
X		if (nhave < MAXSTR)
X			curstr[nhave++] = c;
X		c = mygetchar();
X	} while (isalnum(c) || c == '_');
X	myungetc(c);
X	curstr[nhave] = 0;
X	return curstr;
X}
X
Xstatic char *holdstr;
X
Xchr_push(s)
Xchar *s;
X{
X	holdstr = s;
X}
X
Xstatic int holdchar, xholdchar;
X
Xmygetchar()
X{
X	register int c;
X	int c2;
X
X	if (holdchar) {
X		c = holdchar;
X		holdchar = 0;
X		goto out;
X	}
X	if (holdstr) {		/* used for -D args */
X		c = *holdstr++;
X		if (c == 0) {
X			holdstr = NULL;
X			return '\n';
X		}
X		return c;
X	}
X
Xretry:
X	c = xgetc();
X	if (c == EOF) {
X		if (endfile())
X			goto retry;
X	} else if (c == '\\') {		/* ansi handling of backslash nl */
X		c2 = xgetc();
X		if (c2 == '\n') {
X			lineno++;
X			goto retry;
X		} else
X			xholdchar = c2;
X	}
Xout:
X	if (c == '\n') {
X		sawnl++;	/* for pre.c */
X		lineno++;
X	}
X	return c;
X}
X
Xxgetc()
X{
X	register int c;
X
X	if (xholdchar) {
X		c = xholdchar;
X		xholdchar = 0;
X		return c;
X	}
X#if CC68|dLibs
X	if (input == stdin)	/* bypass stupid input */
X		c = hackgetc();
X	else
X#endif
X		c = getc(input);
X	if (c != EOF)
X		c &= 0x7f;
X	return c;
X}
X
Xmyungetc(c)
Xchar c;
X{
X	if (c != EOF)
X		holdchar = c;
X	if (c == '\n')
X		lineno--;
X}
X
Xstruct op {
X	char *name;
X	char *asname;
X	int flags;
X	char prec;
X	char value;
X} ops[] = {
X	{"{"},
X	{"}"},
X	{"["},
X	{"]"},
X	{"("},
X	{")"},
X	{"#"},
X	{"\\"},
X	{";"},
X	{","},
X	{":"},
X	{"."},
X
X	{"\"", 0, SPECIAL},
X	{"'", 0, SPECIAL},
X
X	{"==", 0, C_NOT_A, 5},
X	{"=", 0, 0},
X
X	{"++", 0, CAN_U},
X	{"+", "+=", CAN_AS|C_AND_A, 2},
X
X	{"--", 0, CAN_U},
X	{"->", 0, 0, 0, ARROW},
X	{"-", "-=", CAN_U|CAN_AS, 2},
X
X	{"*", "*=", CAN_U|CAN_AS|C_AND_A, 1},
X	{"%", "%=", CAN_AS, 1},
X
X	{"/*", 0, SPECIAL},
X	{"/", "/=", CAN_AS, 1},
X
X	{"&&", 0, 0, 9},
X	{"&", "&=", CAN_U|CAN_AS|C_AND_A, 6},
X
X	{"||", 0, 0, 10},
X	{"|", "|=", CAN_AS|C_AND_A, 8},
X
X	{"!=", 0, C_NOT_A, 5, NOTEQ},
X	{"!", 0, CAN_U},
X
X	{"~", 0, CAN_U},
X
X	{"^", "^=", CAN_AS|C_AND_A, 7},
X
X	{"<<", "<<=", CAN_AS, 3},
X	{"<=", 0, C_NOT_A, 4, LTEQ},
X	{"<", 0, SPECIAL|C_NOT_A, 4},
X
X	{">>", ">>=", CAN_AS, 3},
X	{">=", 0, C_NOT_A, 4, GTEQ},
X	{">", 0, C_NOT_A, 4},
X
X	{"?", 0, 0},
X
X	{0, 0, 0}
X};
X
X#define FIRST_C	'!'
X#define LAST_C	0177
Xstruct op *opstart[LAST_C-FIRST_C+1];
X
Xmo_init()
X{
X	register struct op *p;
X	register c;
X
X	for (p=ops; p->name; p++) {
X		c = p->name[0];
X		if (opstart[c-FIRST_C] == 0)
X			opstart[c-FIRST_C] = p;
X	}
X}
X
Xmatchop(c)
X{
X	register struct tok *t;
X	register struct op *p;
X	int nxt;
X	int value;
X	static first = 0;
X
X	t = &curtok;
X	nxt = mygetchar();
X	value = c;
X	if (first == 0) {
X		mo_init();
X		first = 1;
X	}
X	p = opstart[c-FIRST_C];
X	if (p)
X	for (; p->name; p++)
X		if (p->name[0] == c)
X			if (p->name[1] == 0 || p->name[1] == nxt) {
X				if (p->name[1] == 0)
X					myungetc(nxt);
X				else {
X					value = p->value ? p->value :
X						DOUBLE value;
X				}
X				if (p->flags & SPECIAL)
X					if (c != '<' || 
X					  tk_flags & TK_LTSTR)
X						return dospec(p);
X				t->flags = p->flags;
X				if (p->flags & CAN_AS) {
X					nxt = mygetchar();
X					if (nxt != '=') {
X						myungetc(nxt);
X					} else {
X						value = ASSIGN value;
X						t->flags = 0;
X					}
X				}
X				t->name = isassign(value)?p->asname:p->name;
X				t->tnum = value;
X				t->prec = isassign(value)? 0 : p->prec;
X				return 1;
X			}
X	myungetc(nxt);
X	t->name = "???";
X	t->tnum = BADTOK;
X	return 0;
X}
X
Xdospec(p)
Xstruct op *p;
X{
X	register struct tok *t;
X	register int c;
X	int nhave;
X	int endc;
X
X	t = &curtok;
X	switch (p->name[0]) {
X	case '/':		/* slash-star */
Xlook:
X		do {
X			c = mygetchar();
X		} while (c != '*');
X		c = mygetchar();
X		if (c == '/')
X			return 0;
X		myungetc(c);
X		goto look;
X	case '\'':
X		t->tnum = ICON;
X		t->ival = getschar('\''); /* allow only 1 for now*/
X		while (getschar('\'') != NOCHAR)
X			;
X		sprintf(curstr, "%d", (int)t->ival);
X		return 1;
X	case '<':
X		endc = '>';
X		t->tnum = SCON2;
X		goto strs;
X	case '"':
X		endc = '"';
X		t->tnum = SCON;
X	strs:
X		t->name = curstr;
X		nhave = 0;
X		c = getschar(endc);
X		while (c != NOCHAR) {
X			if (c >= 0 && c <= 1 && nhave < MAXSTR) {
X				 /* allow null */
X				curstr[nhave++] = 1;
X				c++;
X			}
X			if (nhave < MAXSTR)
X				curstr[nhave++] = c;
X			c = getschar(endc);
X		}
X		curstr[nhave] = 0;
X		return 1;
X	}
X}
X
Xgetoct(c)
X{
X	char n, i;
X
X	n = c - '0';
X	for (i=1; i < 3; i++) {
X		c = mygetchar();
X		if (c < '0' || c > '7') {
X			myungetc(c);
X			return (int)n;
X		}
X		n = 8*n + (c - '0');
X	}
X	return (int)n;
X}
X	
Xgetschar(del)
Xchar del;
X{
X	register int c;
X
Xmore:
X	c = mygetchar();
X	if (c == del)
X		return NOCHAR;
X	if (c == '\n') {
X		error("nl in string");
X		myungetc(c);
X		return NOCHAR;
X	}
X	if (c == '\\' && (tk_flags & TK_NOESC) == 0) {
X		c = mygetchar();
X		if (c == del)
X			return c;
X		if (c >= '0' && c <= '7')
X			return getoct(c);
X		switch (c) {
X/*
X		case '\n':
X			goto more;
X*/
X		case 'b':
X			c = '\b';
X			break;
X		case 'n':
X			c = '\n';
X			break;
X		case 't':
X			c = '\t';
X			break;
X		case 'r':
X			c = '\r';
X			break;
X		case 'f':
X			c = '\f';
X			break;
X		}
X	}
X	return c;
X}
X
X#if !dLibs
X
Xisalpha(c)
Xregister char c;
X{
X	if ((c>='a' && c<='z') ||
X		(c>='A' && c<='Z'))
X		return 1;
X	return 0;
X}
X
Xisalnum(c)
Xregister char c;
X{
X	return (isalpha(c) || (c>='0' && c<='9'));
X}
X
Xtolower(c)
Xregister char c;
X{
X	if (c>='A' && c<='Z')
X		c += 'a'-'A';
X	return c;
X}
X
X#endif
X
Xishexa(c)
Xregister char c;
X{
X	if (c>='a' && c<='f')
X		return (c-'a'+10);
X	if (c>='A' && c<='F')
X		return (c-'A'+10);
X	return 0;
X}
X
X#if CC68
Xhackgetc()
X{
X	register int c;
X
X	c = bios(2,2);
X	switch (c) {
X	case 4:
X		return EOF;
X	case '\r':
X	case '\n':
X		bios(3,2,'\r');
X		bios(3,2,'\n');
X		return '\n';
X	}
X	bios(3,2,c);
X	return c;
X}
X#endif
X
X#if dLibs
Xhackgetc()
X{
X	register int c;
X
X	c = getchar();
X	switch (c) {
X	case 4:
X		return EOF;
X	case '\n':
X		putchar('\n');
X		break;
X	}
X	return c;
X}
X#endif
END_OF_FILE
if test 10934 -ne `wc -c <'hcc/TOK.C'`; then
    echo shar: \"'hcc/TOK.C'\" unpacked with wrong size!
fi
# end of 'hcc/TOK.C'
fi
echo shar: End of archive 4 \(of 9\).
cp /dev/null ark4isdone
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