1
0
mirror of https://github.com/PDP-10/PCC20.git synced 2026-01-13 23:26:39 +00:00
2018-10-25 11:25:56 +02:00

1147 lines
26 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# include "cc.h"
# include "c2.h"
/*
C COMPILER
Phase P: Parser
Section 3: Declaration and Function Processing
Copyright (c) 1977 by Alan Snyder
*/
/**********************************************************************
ROUTINE DECLARATIONS
**********************************************************************/
dentry *astridn(), *alidn(), *aeidn(), *afidn(), *afdcl();
dentry *dmerge();
int *adeclr();
type maktyp();
type astruct();
type aostruct();
type afield();
type atidn();
type mkstruct();
type mkdummy();
/**********************************************************************
EXTERNAL VARIABLES
**********************************************************************/
extern int *pv, f_node, f_mac, f_symtab, lc_node, nodeno,
ciln, sflag;
/**********************************************************************
DECLARATION PROCESSING VARIABLES
**********************************************************************/
int cblock 0, /* current block, 0 = external */
nblock 0, /* number of blocks */
class UNDEF, /* current storage class */
tclass, /* storage class after defaults */
mtype, /* current type modifier */
cidn, /* current identifier */
cdim, /* current number of dimensions */
dims[MAXDIMS], /* current dimensions */
*dimp, /* pointer to current entry in dims */
strlev 0, /* structure definition level */
in_type_def 0, /* flag indicates processing of type-
declarations (parameter declarations and
structure member definitions) */
*parml, /* pointer to list of parameter names */
nstatic 0, /* static variable counter */
autoloc, /* location counter for auto variables */
framesize, /* maximum allocated size of stack frame */
flineno, /* line number for function definition */
fnarg, /* number of arguments to current function */
objmode UNDEF; /* object mode (pure, impure, data, pdata) */
type btype; /* basic type of declaration statement */
type TUNSPEC UNDEF; /* unspecified type */
dentry **fparms; /* list of parm definitions on stack */
/* Initialization Processing */
int initc, /* counter of initializers */
allow[6], /* allowable initialization classes */
ipc, /* pointer class for variable being initialized */
initflag; /* initialization flag */
type ivtype; /* type of variable being initialized */
type ietype; /* element type of variable being initialized */
dentry *idp; /* dictionary pointer of variable */
/* DICTIONARY */
dentry dict [stsize],
*dbegin {dict}, /* first entry */
*dgdp {dict}, /* entry following global defs */
*dldp, /* first entry in local defs */
*dend; /* following last entry */
/**********************************************************************
DINIT - Initialize Declaration Processing Variables
**********************************************************************/
dinit ()
{dldp = dend = dict+stsize;
typinit ();
}
/**********************************************************************
AFDCL - process function declaration
Begin processing of function defintion. This routine is
called immediately after the function declaration (the type
specification for the function and the list of parameter
names) has been recognized.
Define the function name in the global definition dictionary.
Enter preliminary definitions for the parameters in the
local definition dictionary.
Parameters:
FLAG - 1 ==> type explicitly specified
External variables used:
BTYPE - the basic type of the function
MTYPE - the type modifier of the function
CIDN - the function name
PARML - points to a list of identifiers (the formal
parameters) on the stack. PARML is 0 if
there are no formal parameters
Replace the list of identifiers on the stack with a list of
pointers to the dictionary definitions of the formal
parameters. Set FPARMS to point to that list. Return the
dictionary pointer of the function.
**********************************************************************/
dentry *afdcl (flag)
{int *sp, idn, *ot;
type t;
dentry *fdp;
flineno = lineno;
if (!flag)
{class = c_extdef;
btype = TINT;
}
t = maktyp ();
if (class != c_extdef) errcidn (1019);
if (!parml) parml = top ()+1; /* null parameter list */
/* define function name in global dictionary */
fdp = define (0, cidn, c_extdef, t, cidn);
cblock = ++nblock;
framesize = autoloc = sv_area_sz;
if (sflag) puti (cidn, f_symtab);
/* define parameters in local dictionary */
fparms = sp = parml;
fnarg = 0;
ot = top ();
while (sp <= ot)
{idn = *sp;
*sp++ = define (cblock, idn, c_param, TUNSPEC, UNDEF);
++fnarg;
}
return (fdp);
}
/**********************************************************************
AFPDCL - Process Function Parameter Declarations
This routine is called after the declarations of formal
parameters have been processed. The list of formal
parameter definitions (accessed via FPARMS) is removed
from the stack. Offsets are computed for the parameters.
**********************************************************************/
afpdcl ()
{dentry *dp, **pp, **ot;
int ploc;
type t;
pp = fparms;
ot = get_top (pp);
ploc = 0;
while (pp <= ot)
{dp = *pp++;
if (dp->dtype == TUNSPEC) dp->dtype = TINT;
t = dp->dtype;
ploc = align (ploc, t->align);
dp->offset = ploc;
ploc =+ t->size;
}
}
/**********************************************************************
AFDEF - Terminate Processing of Function Definition
This routine is called after the end of the function
definition has been reached. FDP is a pointer to the
dictionary definition of the function. N is the node
offset of the function body.
**********************************************************************/
afdef (fdp, n) dentry *fdp; int n;
{node (n_prog, fdp->name, tp2o (fdp->dtype), n, framesize, fnarg);
chkdict (dldp, dend);
if (sflag)
{wdict (dldp, dend); /* write parameter defs */
puti (UNDEF, f_symtab);
}
dldp = dend; /* delete parameter defs */
cblock = 0;
}
/**********************************************************************
ATTRIB - process decl-specifiers
Check for valid CLASS and determine default CLASS or TYPE if
possible.
**********************************************************************/
attrib (pclass, pbtype) int pclass, pbtype;
/* check CLASS */
{if (strlev>0) class = c_mos;
else if (in_type_def) class = c_param;
else if (cblock==0) switch (pclass) { /* global declaration */
case UNDEF: class = c_extdef; /* default */
break;
case c_typedef:
case c_extern:
case c_static: class = pclass;
break;
case c_auto: errx (1018);
class = c_extdef;
break;
default: errx (6009);
}
else class = pclass;
/* check TYPE */
if (pbtype == UNDEF) btype = TINT; /* default */
else btype = pbtype;
}
/**********************************************************************
ASTRUCT - Define a Structure Type
DP is the dictionary pointer of the type name, or NULL if
the structure type is unnamed.
FP is a pointer to a list of field definitions.
Return the appropriate structure type.
**********************************************************************/
type astruct (dp, fp) dentry *dp; field *fp;
{int nfields;
field *efp;
--strlev;
efp = (get_top (fp) + 1); /* get definition list */
nfields = efp - fp; /* number of members */
if (dp != NULL) /* named structure type */
{fixdummy (dp->dtype, nfields, fp);
return (dp->dtype);
}
return (mkstruct (nfields, fp));
}
/**********************************************************************
AOSTRUCT - Return type given structure type name.
**********************************************************************/
type aostruct (name)
{dentry *dp;
type t;
--strlev;
dp = find (name + cssiz);
if (dp) return (dp->dtype);
t = mkdummy (name);
define (cblock, name + cssiz, c_ustruct, t, 0);
return (t);
}
/**********************************************************************
ASTRIDN - Define Structure Type Name
Create a dictionary definition for a named structure type
about to be defined.
**********************************************************************/
dentry *astridn (name)
{dentry *dp;
dp = find (name+cssiz);
if (dp)
{if (dp->class == c_ustruct)
{dp->class = c_struct;
return (dp);
}
errx (2018, TIDN, name);
return (NULL);
}
return (define (cblock, name+cssiz, c_struct, mkdummy (name), 0));
}
/**********************************************************************
ADECLR - process declarator
Process the declarator using the following external variables:
CLASS - the storage class (may be UNDEF)
CIDN - the identifier number
STRLEV - indicates whether member of structure
Check for illegally specified CLASS, and determine the default
CLASS if necessary. If we are defining a structure field,
then push a field definition on the stack and return a pointer
to it. Otherwise, enter the definition of the declarator in
the dictionary.
Assign a static variable number to static variables.
Set IDP to point to the dictionary entry of the variable, for
use by the initialization routines. Set INITC to UNDEF so that
variables without initialization can be recognized by AIDECLR.
**********************************************************************/
int *adeclr (t)
type t;
{int *ip, o;
dentry *dp;
if (strlev)
{ip = push (cidn);
push (t);
push (UNDEF);
return (ip);
}
dp = NULL;
if (class == UNDEF)
tclass = ((t->tag==TTFUNC) ? c_extern : c_auto);
else tclass = class;
if (t->tag==TTFUNC && tclass!=c_param && tclass!=c_typedef)
{if (tclass != c_extern && tclass != c_extdef)
errcidn (1021);
tclass = c_extern;
}
if (tclass==c_param)
{if (!(dp = find (cidn))) /* not a parameter */
{errcidn (1027);
tclass = c_auto;
}
else if (dp->class==c_param) /* parameter entry located */
{if (t == TCHAR) t = TINT;
else if (t == TFLOAT) t = TDOUBLE;
else if (t->tag==TTARRAY)
t = mkptr (t->val);
else if (t->tag==TTFUNC || t->tag==TTSTRUCT)
{errcidn (2036);
t = mkptr (t);
}
if (dp->dtype != TUNSPEC) errcidn (2016);
else dp->dtype = t;
}
}
switch (tclass) {
case c_static: o = ++nstatic; break;
case c_extdef:
case c_extern: o = cidn; break;
case c_auto: tclass = c_uauto;
o = autoloc = align (autoloc, t->align);
autoloc =+ t->size;
break;
default: o = UNDEF;
}
if (!dp) dp = define (cblock, cidn, tclass, t, o);
idp = dp; /* for processing initializers */
ivtype = idp->dtype;
initc = UNDEF;
return (0);
}
/**********************************************************************
ADCLR - construct declarator
MTYP is the current type modifier, NEWTYP is the new type
modifier, DIM is the array dimension, ARRAYFLAG indicates that
all type modifiers so far have been "array of". The current
type modifier is stored in external variable MTYPE.
**********************************************************************/
int adclr (mtyp, newtyp, dim) int mtyp, newtyp, dim;
{if (mtyp==0 && newtyp==0) /* new declarator */
{cidn = pv[1];
cdim = 0;
dimp = dims;
return (mtype = newtyp);
}
if (mtyp == UNDEF) return (UNDEF); /* previous error */
mtyp = mtyp << 2 | newtyp;
if (newtyp==MARRAY)
{if (cdim>=MAXDIMS)
{errcidn (2015);
return (mtype = UNDEF);
}
if (dim<=0)
{errcidn (1031);
dim=1;
}
*dimp++ = dim;
++cdim;
}
return (mtype = mtyp);
}
/**********************************************************************
MAKTYP - check for invalid types and correct
Combine type modifier MTYPE and basic type BTYPE.
**********************************************************************/
type maktyp ()
{register int i;
type t;
if (mtype == UNDEF) return (TUNDEF); /* previous error */
if (mtype<<1<0 || mtype<<2<0)
{errcidn (2014);
return (TUNDEF);
}
t = btype;
while (i = (mtype&03))
{switch (i) {
case MPTR: t = mkptr (t); break;
case MFUNC: t = mkfunc (t); break;
case MARRAY: t = mkarray (t, *--dimp); break;
}
mtype =>> 2;
}
return (t);
}
/**********************************************************************
AFIELD - Construct declarator for bit field definition.
(Currently implemented as INT.) This routine performs
the functions of ADCLR and MAKTYP.
**********************************************************************/
type afield (idn, width)
{cidn = idn;
cdim = 0;
if (!strlev) errcidn (1032);
if (width<0) errcidn (1033);
switch (btype->tag) {
case TTCHAR: /* return (mkcfield (width)); */
break;
case TTINT: /* return (mkifield (width)); */
break;
default: errcidn (1034);
}
return (TINT);
}
/**********************************************************************
AIINZ - Initialize for the processing of initializers.
Determine what types of initializers are valid for this
variable and set the array ALLOW accordingly. Also determine
whether or not initialization of this variable is allowed at
all. Output symbol defining macros.
This routine is called after ADECLR is called for the
variable and immediately before the first initializer is
processed.
**********************************************************************/
aiinz ()
{int i;
initflag = FALSE;
for (i=0;i<6;i++) allow[i]=FALSE;
ietype = remarr (ivtype); /* remove arrays */
/* determine valid initializer types */
switch (ietype->tag) {
case TTCHAR:
case TTINT: allow[i_int] = TRUE; break;
case TTFLOAT:
case TTDOUBLE: allow[i_float] = TRUE;
allow[i_negfloat] = TRUE;
break;
case TTSTRUCT: allow[i_string] = TRUE;
allow[i_int] = TRUE;
allow[i_idn] = TRUE;
ipc = tpoint[TTINT];
break;
case TTPTR: allow[i_int] = TRUE;
allow[i_idn] = TRUE;
ipc = ctype (ietype) - ct_p0;
if (ietype==TPCHAR) allow[i_string] = TRUE;
}
/* check CLASS */
switch (tclass) {
case c_extdef: data;
malign (ivtype->align);
mequ (cidn);
break;
case c_static: data;
malign (ivtype->align);
mstatic (idp->offset);
break;
case c_uauto:
case c_auto: errcidn (1024);
initflag = TRUE;
break;
default: errcidn (1026);
initflag = TRUE;
}
initc = 0;
}
/**********************************************************************
INZ - process initializer
Process initializer and increment INITC. Determine whether
the initializer is of a valid type.
Output the initializer onto the MAC file. INITFLAG is used
to prohibit certain multiple error messages.
**********************************************************************/
inz (i_type, index) int i_type, index;
{dentry *dp;
int cls;
if (initflag) return; /* previous error */
if (!allow[i_type])
{errcidn (1022);
return;
}
++initc;
switch (i_type) {
case i_int: if (ietype==TCHAR) mchar (index);
else mint (index);
return;
case i_idn: dp = afidn (index);
switch (cls = dp->class) {
case c_extern: cls = c_extdef;
case c_extdef:
case c_static: madcon (ipc, -cls, dp->offset);
break;
default: mint (0);
errx (2038, TIDN, index);
}
return;
case i_string: mstrcon (index);
return;
case i_float: if (ietype==TFLOAT) mfloat (index);
else mdouble (index);
return;
case i_negfloat:
if (ietype==TFLOAT) mnfloat (index);
else mndouble (index);
return;
}
errx (6041);
}
/**********************************************************************
AIDECL - Finish processing for a variable which may
have been initialized. If it was initialized, determine
the actual size of the variable and output any zero space
needed. If it was not initialized and was an external
definition or a static variable, allocate storage for it.
Check for multiple initializers to a non-structured variable.
**********************************************************************/
aidecl ()
{int esize, isize, dsize, dcount, i, nelem, aesize;
type etype;
dsize = ivtype->size;
if (initc == UNDEF) /* not initialized */
{if (tclass == c_extdef)
{impure;
malign (ivtype->align);
mequ (cidn);
mzero (dsize);
}
if (tclass==c_static)
{impure;
malign (ivtype->align);
mstatic (idp->offset);
mzero (dsize);
}
}
else
{if (ietype->tag==TTSTRUCT) /* finish structure hack */
{esize = ietype->size; /* structure size */
isize = initc * tsize[TTINT]; /* initialzed size */
if (i = isize % esize)
{i = esize - i;
mzero (i); /* fill out structure */
isize =+ i;
}
initc = isize / esize; /* number of structure values */
}
if (ivtype->tag == TTARRAY)
/* initializers may increase size of array */
{esize = ietype->size;
dcount = nelem = dsize/esize;
if (initc > nelem)
{nelem = initc;
etype = ivtype->val;
aesize = etype->size;
ivtype = idp->dtype = mkarray (etype,
(nelem*esize+(aesize-1))/aesize);
dcount = ivtype->size/esize;
}
}
else
{if (initc>1) errcidn (1023);
esize = dsize;
dcount = 1;
}
if (initc < dcount) mzero (esize*(dcount-initc));
}
}
/**********************************************************************
BLOCK STRUCTURE ROUTINES
**********************************************************************/
abegin ()
{push (dldp);
push (autoloc);
}
aend ()
{int n;
dentry *dp, *odp;
if (autoloc > framesize) framesize = autoloc;
n = pop ();
if (n >= sv_area_sz && n <= autoloc) autoloc = n;
dp = pop ();
if (dp >= dldp && dp <= dend)
{odp = dldp;
dldp = dp;
chkdict (odp, dldp); /* obscure ILHACK interaction */
if (sflag) wdict (odp, dldp);
}
}
/**********************************************************************
IDENTIFIER LOOKUP ROUTINES
**********************************************************************/
dentry *aeidn (name)
{dentry *dp;
dp = define (cblock, name, UNDEF, TUNDEF, UNDEF);
if (dp->class == UNDEF)
{errx (2027, TIDN, name);
dp->class = c_auto;
}
else if (dp->class == c_uauto) dp->class = c_auto;
return (dp);
}
dentry *afidn (name)
{dentry *dp;
dp = define (0, name, UNDEF, TUNSPEC, name);
if (dp->class == UNDEF)
{dp->class = c_extern;
dp->dtype = TFINT;
}
else if (dp->class == c_uauto) dp->class = c_auto;
return (dp);
}
dentry *alidn (name)
{dentry *dp;
dp = define (cblock, name, c_ulabel, TINT, UNDEF);
if (dp->offset == UNDEF) dp->offset = ciln++;
return (dp);
}
type atidn (name)
{dentry *dp;
dp = find (name);
if (!dp || dp->class != c_typedef)
{errx (2041, TIDN, name);
return (TUNDEF);
}
return (dp->dtype);
}
/**********************************************************************
MACRO OUTPUT ROUTINES
**********************************************************************/
mhead() {mprint ("%hd()\n");}
mentry(n) {mprint ("%en(%i(*))\n", n);}
extrn(n) {mprint ("%ex(%i(*))\n", n);}
mstatic (n) {mprint ("%st(*)\n", n);}
mequ (n) {mprint ("%eq(%i(*))\n", n);}
mzero (i) {mprint ("%z(*)\n", i);}
malign (ac) {if (ac>0) mprint ("%al*()\n", ac);}
mint (i) {mprint ("%in(*)\n", i);}
mstrcon (i) {mprint ("%sc(*)\n", i);}
madcon (n,b,o) {mprint ("%ad*(0,*,*)\n", n, b, o);}
mchar (i) {mprint ("%c(*)\n", i);}
mfloat (i) {mprint ("%f(*)\n", i);}
mnfloat (i) {mprint ("%nf(*)\n", i);}
mdouble (i) {mprint ("%d(*)\n", i);}
mndouble (i) {mprint ("%nd(*)\n", i);}
mimpure () {mprint ("%im()\n"); objmode=o_impure;}
mpure () {mprint ("%pu()\n"); objmode=o_pure;}
mdata () {mprint ("%da()\n"); objmode=o_data;}
/**********************************************************************
SDEF - Define external references and global names
**********************************************************************/
sdef ()
{dentry *dp;
extern char *fn_hmac;
cclose (f_mac);
f_mac = xopen (fn_hmac, MWRITE, TEXT);
mhead ();
/* DEFINE ENTRY POINTS */
pure;
for (dp=dbegin; dp<dgdp; ++dp)
if (dp->class==c_extdef) mentry (dp->name);
/* DEFINE EXTERNAL REFERENCES */
for (dp=dbegin; dp<dgdp; ++dp)
if (dp->class==c_extern) extrn (dp->name);
cclose (f_mac);
}
/**********************************************************************
SYMBOL TABLE FORMAT
The symbol table consists of two parts: a dictionary (DICT)
and a type table (TYPTAB).
The dictionary is an array of dictionary entries (DENTRY).
The fields of a DENTRY are:
name - index of identifier
class - storge class
dtype - data type
offset - basis for addressing the item:
parameters: offset in parameter list
automatic: offset in stack frame
static: static variable number
external: 0
labels: corresponding internal label number
**********************************************************************/
/**********************************************************************
DEFINE - Create or modify a dictionary entry.
**********************************************************************/
dentry *define (block, name, xclass, dtype, offset)
type dtype;
{dentry *dp;
if (dp = find (name)) /* if old entry exists */
return (dmerge (dp, xclass, dtype, offset));
if (block==0 || xclass==c_extern)
dp = dgdp++;
else dp = --dldp;
if (dldp < dgdp) errx (4005);
dp->name = name; /* copy entry */
dp->class = xclass;
dp->dtype = dtype;
dp->offset = offset;
return (dp);
}
/**********************************************************************
DMERGE - Merge new definition with old one.
**********************************************************************/
dentry *dmerge (dp, xclass, dtype, offset)
dentry *dp;
type dtype;
{type t;
int c;
if (xclass == UNDEF) return (dp);
c = dp->class;
t = dp->dtype;
if (xclass==c_extdef && c==c_extern ||
xclass==c_label && c==c_ulabel)
{c = xclass;
xclass = dp->class;
dp->class = c;
t = dtype;
dtype = dp->dtype;
dp->dtype = t;
}
if (xclass==c_extern && (c==c_extdef || c==c_extern) ||
xclass==c_ulabel && (c==c_label || c==c_ulabel))
{if (dtype == TUNSPEC) return (dp);
if (t == dtype) return (dp);
if (t->tag == TTARRAY && dtype->tag == TTARRAY &&
t->val == dtype->val) return (dp);
}
errx (2016, TIDN, dp->name);
return (dp);
}
/**********************************************************************
FIND - Find the dictionary entry for a identifier
**********************************************************************/
dentry *find (name)
{dentry *p;
p = dldp;
while (p<dend) if (p->name == name) return (p); else ++p;
p = dgdp;
while (--p >= dbegin) if (p->name == name) return (p);
return (NULL);
}
/**********************************************************************
CHKDICT - Check dictionary bounded by P1 and P2 for undefined
things.
**********************************************************************/
chkdict (p1, p2) dentry *p1, *p2;
{type t;
int ilhack;
ilhack = (p2 == dldp && p1 != dbegin);
while (--p2 >= p1)
{t = p2->dtype;
if (t->tag == TTDUMMY)
{errx (2024, TIDN, t->val);
t = p2->dtype = TUNDEF;
}
if (p2->class == c_ulabel)
{if (ilhack) dswap (p2, --dldp);
else
{errx (2017, TIDN, p2->name);
p2->class = c_label;
}
}
else if (p2->class == c_uauto)
{error (1006, flineno, TIDN, p2->name);
p2->class = c_auto;
}
}
}
dswap (p1, p2) dentry *p1, *p2;
{if (p1 != p2)
{swap (&p1->name, &p2->name);
swap (&p1->class, &p2->class);
swap (&p1->dtype, &p2->dtype);
swap (&p1->offset, &p2->offset);
}
}
swap (p1, p2) int *p1, *p2;
{int t;
t = *p1;
*p1 = *p2;
*p2 = t;
}
/**********************************************************************
WSYMTAB - Write Global Symbol Table
**********************************************************************/
wsymtab ()
{puti (UNDEF, f_symtab);
wdict (dbegin, dgdp);
puti (UNDEF, f_symtab);
}
/**********************************************************************
WDICT - Write dictionary bounded by P1 and P2.
**********************************************************************/
wdict (p1, p2) dentry *p1, *p2;
{while (p1 < p2)
{puti (p1->name, f_symtab);
puti (tp2o (p1->dtype), f_symtab);
puti (p1->offset, f_symtab);
puti (p1->class, f_symtab);
++p1;
}
}
dp2o (p) dentry *p;
{if (p==NULL) return (UNDEF);
if (p<dbegin || p>=dend) errx (6035);
if (p >= dgdp) return (010000 + (dend - p));
return (p-dbegin);
}
/**********************************************************************
WTYPTAB - Write Type Table
**********************************************************************/
wtyptab ()
{extern int typtab[], *ctypp, *crecp, *etypp, typform[];
extern char *fn_typtab;
register int *p, fmt;
register field *fp;
int f;
f = xopen (fn_typtab, MWRITE, BINARY);
puti (ctypp-typtab, f);
p = typtab;
while (p < ctypp)
{fmt = typform[p[0]];
puti (*p++, f);
puti (*p++, f);
puti (*p++, f);
switch (fmt) {
case 1: puti (*p++, f); break;
case 2: puti (tp2o (*p++), f); break;
case 3: puti (tp2o (*p++), f);
puti (*p++, f);
break;
case 4: puti (rp2o (*p++), f); break;
}
}
puti (etypp-crecp, f);
p = crecp;
while (p < etypp)
{fp = p;
puti (fp->name, f);
if (fp->name == UNDEF) ++p;
else
{puti (tp2o (fp->dtype), f);
puti (fp->offset, f);
p = fp+1;
}
}
cclose (f);
}
int tp2o (t) type t;
{extern int typtab[], *ctypp;
int *tt;
tt = t;
if (tt < typtab || tt >= ctypp) errx (6005);
return (tt - typtab);
}
int rp2o (p) int *p;
{extern int *crecp, *etypp;
if (p < crecp || p >= etypp) errx (6037);
return (etypp - p);
}
/**********************************************************************
Type Operations Used Only In Phase P
**********************************************************************/
type mkstruct (n, v)
int n;
field v[];
{type t;
t = mkdummy (0);
fixdummy (t, n, v);
return (t);
}
type mkdummy (name)
{type t;
t = typxh (TTDUMMY);
typxh (UNDEF);
typxh (1);
typxh (name);
return (t);
}
fixdummy (t, n, fp)
type t;
int n;
field *fp;
{field *p;
recxl (UNDEF); /* UNDEF name marks end of list */
fp =+ n;
while (--n >= 0)
{--fp;
recxl (fp->offset);
recxl (fp->dtype);
p = recxl (fp->name);
}
t->tag = TTSTRUCT;
t->val = p;
fixstr (t);
}
fixstr (t) type t;
{int salign, offset;
register field *fp;
register type ft;
t->size = -2; /* to catch recursive definition */
fp = t->val; /* field list */
salign = 0;
while (fp->name != UNDEF) /* determine alignment */
{fp->dtype = ft = fixtype (fp->dtype);
if (ft->align > salign) salign = ft->align;
++fp;
}
t->align = salign;
fp = t->val;
offset = 0;
while (fp->name != UNDEF) /* determine offsets */
{ft = fp->dtype;
offset = align (offset, ft->align);
fp->offset = offset;
offset =+ ft->size;
++fp;
}
t->size = align (offset, t->align);
}
/**********************************************************************
ERRCIDN - announce error for current identifier
**********************************************************************/
errcidn (errno) {errx (errno, TIDN, cidn);}