mirror of
https://github.com/PDP-10/PCC20.git
synced 2026-01-13 23:26:39 +00:00
1147 lines
26 KiB
C
1147 lines
26 KiB
C
# 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);}
|
||
|