mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-24 08:54:17 +00:00
Upload
Digital Research
This commit is contained in:
967
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/c068/decl.c
Normal file
967
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/c068/decl.c
Normal file
@@ -0,0 +1,967 @@
|
||||
/*
|
||||
Copyright 1982, 1983
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
|
||||
@(#)decl.c 1.13 1/3/84
|
||||
*/
|
||||
|
||||
#include "parser.h"
|
||||
|
||||
/* PNEXT - if next token is a symbol, skip and return success, allows */
|
||||
/* for clean parsing of declarations */
|
||||
#define PNEXT() next(SYMBOL)
|
||||
#ifdef SYM_TO_DSK
|
||||
/* setup address saving, structure assignment, set pointer to structure */
|
||||
# define ASSG(a,na,e,ne,p) a = na; e = ne; p = &e
|
||||
#endif
|
||||
|
||||
/*
|
||||
* doextdef - external definition syntax
|
||||
* This is fairly complicated since you do not know if you are
|
||||
* parsing a external function declaration or a real function
|
||||
* until after you've already scanned the argument list for the
|
||||
* function. Basically you start off scanning an external declaration
|
||||
* or function in the same way by collecting attributes, scanning
|
||||
* the declarator, then scanning the function arguments if a function.
|
||||
* At that point you look at the next token and if its a '{', keyword
|
||||
* proceed accordingly.
|
||||
* The C Syntax handled by this routine is (roughly):
|
||||
* external_definition:
|
||||
* function_definition
|
||||
* data_definition
|
||||
* function_definition:
|
||||
* type_specifier function_declarator function_body
|
||||
* function_declarator:
|
||||
* declarator ( parameter_list )
|
||||
* data_definition:
|
||||
* EXTERNAL type_specifier init_declarator_list ;
|
||||
* STATIC type_specifier init_declarator_list ;
|
||||
*/
|
||||
doextdef() /* returns 0 for EOF or 1*/
|
||||
{
|
||||
register struct symbol *sp;
|
||||
register short dflag;
|
||||
short sc, type;
|
||||
long size;
|
||||
#ifdef SYM_TO_DSK
|
||||
long sp_addr;
|
||||
struct symbol sp_entry;
|
||||
#endif
|
||||
|
||||
tdflag = 0; /* [vlh] 4.2.b reset on sighting a semicolon */
|
||||
if(!next(SEMI)) {
|
||||
opap = exprp = exprarea;
|
||||
sc = EXTERNAL;
|
||||
type = (xflag?LONG:INT);
|
||||
dflag = gettype(&sc,&type,&size,1);
|
||||
#ifdef DEBUG
|
||||
if(symdebug)
|
||||
printf("dflag %d sc %d type 0%o size %d\n",dflag,sc,type,size);
|
||||
#endif
|
||||
if(type==STRUCT) /* deal with forward ref structures */
|
||||
chksyms(0);
|
||||
while( dodecl(sc,type,0,size), (sp=dsp) != 0 ) {
|
||||
#ifdef SYM_TO_DSK
|
||||
ASSG(sp_addr,dsp_addr,sp_entry,dsp_entry,sp);
|
||||
#endif
|
||||
if (type==STRUCT) { /* [vlh] 4.2 */
|
||||
sp->s_child = sp->s_par = struc_parent[0];
|
||||
TO_DSK(sp,sp_addr);
|
||||
READ_ST(dsp,dsp_addr);
|
||||
}
|
||||
if( !dflag && NOTFUNCTION(sp->s_type) ) {
|
||||
synerr("external definition syntax");
|
||||
return;
|
||||
}
|
||||
if( !ISTYPEDEF(sp) && sc != STATIC )
|
||||
if (NOTFUNCTION(sp->s_type)) /*[vlh] .globl ext. vars*/
|
||||
OUTEXTDEF(sp->s_symbol);
|
||||
if( NOTFUNCTION(sp->s_type) ) { /*not function, check init*/
|
||||
if( !ISTYPEDEF(sp) ) {
|
||||
doinit(sp);
|
||||
if (sc == STATIC)
|
||||
chksyms(0);
|
||||
}
|
||||
}
|
||||
else if( PEEK(RESWORD) || PEEK(LCURBR) ||
|
||||
(PEEK(SYMBOL) && ISTYPEDEF(csp)) ) {
|
||||
if(!ISTYPEDEF(sp) && sc!=STATIC) /*[vlh] .globl local proc*/
|
||||
OUTEXTDEF(sp->s_symbol);
|
||||
funcbody(sp);
|
||||
return;
|
||||
}
|
||||
ZERO_DSP();
|
||||
if( !next(COMMA) )
|
||||
break;
|
||||
}
|
||||
if( gettok(0) != SEMI ) {
|
||||
#ifdef DEBUG
|
||||
if (symdebug) printf("external definition syntax due to lost comma...\n");
|
||||
#endif
|
||||
synerr("external definition syntax");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gettype - get attribute types in attribute list
|
||||
* Handles single word keywords, such as int, char, etc. and also
|
||||
* handles the declarations of structures and unions.
|
||||
**/
|
||||
gettype(defsc,deftype,size,declok) /* returns 0 for no type, 1 otherwise*/
|
||||
short *defsc; /* default storage class*/
|
||||
short *deftype; /* default data type*/
|
||||
long *size; /* size of data element 3.4 int=>long*/
|
||||
int declok; /* as opposed to casting op */
|
||||
{
|
||||
register short token, sc;
|
||||
short dtype, sflag, uflag, lflag, decflag;
|
||||
long tsize;
|
||||
struct symbol *sp;
|
||||
#ifndef SYM_TO_DSK
|
||||
struct symbol *parent;
|
||||
#else
|
||||
long parent;
|
||||
#endif
|
||||
|
||||
if(declok || instmt)
|
||||
tdp = 0;
|
||||
uflag = decflag = lflag = sflag = 0; tsize = 0L; /* tdp=0 4.3 removed */
|
||||
dtype = TYPELESS;
|
||||
sc = *defsc;
|
||||
indecl = 0; /* start off at 0 !!!! */
|
||||
for( ; ; decflag++ ) {
|
||||
if( (token=gettok(0)) == SYMBOL && ISTYPEDEF(csp) ) {
|
||||
dtype = 0;
|
||||
indecl = declok;
|
||||
if (declok || instmt) /* tdp not used in initialization cast */
|
||||
#ifdef SYM_TO_DSK
|
||||
{ ASSG(tdp_addr,csp_addr,tdp_entry,csp_entry,tdp); }
|
||||
#else
|
||||
tdp = csp;
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
if( token != RESWORD )
|
||||
break;
|
||||
indecl = declok; /* if not trying for casting operator */
|
||||
switch( cvalue ) {
|
||||
|
||||
default: /* not a declaration type reserved word */
|
||||
indecl = 0;
|
||||
break;
|
||||
|
||||
case R_TYPEDEF:
|
||||
if( tdflag )
|
||||
error("invalid typedef statement");
|
||||
tdflag++;
|
||||
continue;
|
||||
|
||||
case R_STATIC:
|
||||
if( sc && sc != STATIC && sc != EXTERNAL )
|
||||
error("invalid storage class");
|
||||
sc = STATIC;
|
||||
continue;
|
||||
|
||||
case R_AUTO:
|
||||
if( sc && sc != AUTO )
|
||||
error("invalid storage class");
|
||||
sc = AUTO;
|
||||
continue;
|
||||
|
||||
case R_EXTERNAL:
|
||||
if( sc && sc != EXTERNAL )
|
||||
error("invalid storage class");
|
||||
sc = (scope_level == GLOB_SCOPE) ? DEXTERN : EXTERNAL;
|
||||
continue;
|
||||
|
||||
case R_REGISTER:
|
||||
if( sc && sc != REGISTER && sc != PDECLIST && sc != PDECREG)
|
||||
error("invalid register specification");
|
||||
sc = (sc != PDECLIST) ? REGISTER : PDECREG;
|
||||
continue;
|
||||
|
||||
case R_LONG:
|
||||
lflag++;
|
||||
continue;
|
||||
|
||||
case R_SHORT:
|
||||
sflag++;
|
||||
continue;
|
||||
|
||||
case R_UNSIGNED:
|
||||
uflag++;
|
||||
continue;
|
||||
|
||||
case R_STRUCT:
|
||||
cvalue = STRUCT;
|
||||
case R_UNION:
|
||||
token = get_s_or_u(sp,&parent,&tsize,&dtype);
|
||||
if (token != FRSTRUCT) /* [vlh] 4.2.e */
|
||||
struc_parent[0] = parent;
|
||||
continue;
|
||||
|
||||
case R_INT:
|
||||
if( dtype != TYPELESS )
|
||||
error("invalid type declaration");
|
||||
dtype = INT;
|
||||
continue;
|
||||
|
||||
case R_CHAR:
|
||||
if( dtype != TYPELESS )
|
||||
error("invalid type declaration");
|
||||
dtype = CHAR;
|
||||
continue;
|
||||
|
||||
case R_FLOAT: /*[vlh] ver. 3.4*/
|
||||
case R_DOUBLE:
|
||||
if( dtype != TYPELESS )
|
||||
error("invalid type declaration");
|
||||
dtype = FLOAT;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
pbtok(token);
|
||||
if( dtype == TYPELESS )
|
||||
dtype = INT;
|
||||
if(!sc)
|
||||
sc = AUTO;
|
||||
if( lflag ) { /*allow: long float, long int*/
|
||||
if( dtype == INT )
|
||||
dtype = LONG;
|
||||
else if( dtype == FLOAT )
|
||||
dtype = DOUBLE;
|
||||
else
|
||||
error("invalid long declaration");
|
||||
}
|
||||
if( sflag && dtype != INT )
|
||||
error("invalid short declaration");
|
||||
if( uflag ) /* [vlh] 4.2 legal from now on... */
|
||||
if (dtype == LONG) {
|
||||
dtype = LONG;
|
||||
warning("unsigned long unimplemented, signed long assumed");
|
||||
}
|
||||
else if (dtype == CHAR) {
|
||||
dtype = CHAR;
|
||||
warning("unsigned char unimplemented, signed char assumed");
|
||||
}
|
||||
else if (dtype == INT)
|
||||
dtype = UNSIGNED;
|
||||
else /*[vlh] 4.2+*/
|
||||
error("invalid unsigned declaration");
|
||||
if( !sflag && xflag && dtype == INT )
|
||||
dtype = LONG;
|
||||
*defsc = sc;
|
||||
*deftype = dtype;
|
||||
*size = tsize;
|
||||
return(decflag);
|
||||
}
|
||||
|
||||
/**
|
||||
* get_s_or_u - get attribute types from a union or structure declaration
|
||||
* This routine parses a structure or union. It is called by
|
||||
* "gettype" and returns the token parsed.
|
||||
**/
|
||||
get_s_or_u(sp,parent,ptsize,pdtype) /* returns token */
|
||||
struct symbol *sp;
|
||||
#ifndef SYM_TO_DSK
|
||||
struct symbol **parent;
|
||||
#else
|
||||
long *parent;
|
||||
#endif
|
||||
long *ptsize;
|
||||
short *pdtype;
|
||||
{
|
||||
char sym[8];
|
||||
register short token, stdflag, sbits, fake;
|
||||
#ifdef SYM_TO_DSK
|
||||
struct symbol sp_entry;
|
||||
long sp_addr;
|
||||
#endif
|
||||
|
||||
stdflag = tdflag;
|
||||
tdflag = 0; sp = 0;
|
||||
token = cvalue;
|
||||
smember++;
|
||||
if (!next(SYMBOL)) { /* force fake struct name into symbol table */
|
||||
fake=1;
|
||||
genunique(sym);
|
||||
csp = (struct symbol *)lookup(sym,1); /* [vlh] 4.2 */
|
||||
}
|
||||
else
|
||||
fake=0;
|
||||
/*struct [symbol] { ... }*/
|
||||
#ifdef SYM_TO_DSK
|
||||
ASSG(sp_addr,csp_addr,sp_entry,csp_entry,sp);
|
||||
*parent = sp_addr;
|
||||
#else
|
||||
*parent = sp = csp;
|
||||
#endif
|
||||
if( !sp->s_sc ) {
|
||||
sp->s_attrib |= SDEFINED;
|
||||
if(!infunc)
|
||||
sp->s_attrib |= SGLOBAL;
|
||||
sp->s_sc = STRPROTO;
|
||||
sp->s_type = STRUCT;
|
||||
sp->s_ssp = dalloc(0L);
|
||||
TO_DSK(sp,sp_addr);
|
||||
} /* sc <-- STRPROTO */
|
||||
else if( sp->s_sc != STRPROTO ) {
|
||||
#ifdef DEBUG
|
||||
if (treedebug) {
|
||||
printf("redec2 typ %d sc %d ",sp->s_type,sp->s_sc);
|
||||
printf("scope %d %d\n",sp->s_scope,scope_level);
|
||||
}
|
||||
#endif
|
||||
error("redeclaration: %.8s",sp->s_symbol);
|
||||
}
|
||||
smember = 0;
|
||||
if( next(LCURBR) ) {
|
||||
struc_sib[in_struct] = hold_sib; /* [vlh] 4.2.e */
|
||||
if (hold_sib) { /* [vlh] 4.2, not struct element yet... */
|
||||
#ifndef SYM_TO_DSK
|
||||
hold_sib->s_sib = 0; /* not null parent !! [vlh]4.3 */
|
||||
#else
|
||||
read_st(&volatile,hold_sib);
|
||||
volatile.s_sib = 0;
|
||||
write_st(&volatile,hold_sib);
|
||||
#endif
|
||||
}
|
||||
in_struct++;
|
||||
#ifndef SYM_TO_DSK
|
||||
struc_parent[in_struct] = sp;
|
||||
#else
|
||||
struc_parent[in_struct] = sp_addr;
|
||||
#endif
|
||||
struc_sib[in_struct] = 0;
|
||||
sbits = boffset;
|
||||
boffset = 0;
|
||||
*ptsize = dlist(token==STRUCT?STELCL:UNELCL);
|
||||
boffset = sbits;
|
||||
if(!next(RCURBR))
|
||||
synerr("structure declaration syntax");
|
||||
else if( sp ) {
|
||||
if( dtab[sp->s_ssp] ) {
|
||||
#ifdef DEBUG
|
||||
if (treedebug) {
|
||||
printf("redec3 typ %d sc %d ",sp->s_type,sp->s_sc);
|
||||
printf("scope %d %d\n",sp->s_scope,scope_level);
|
||||
}
|
||||
#endif
|
||||
error("redeclaration: %.8s",sp->s_symbol);
|
||||
}
|
||||
dtab[sp->s_ssp] = *ptsize;
|
||||
}
|
||||
struc_parent[in_struct] = 0;
|
||||
struc_sib[in_struct] = 0;
|
||||
if (!(--in_struct))
|
||||
hold_sib = 0;
|
||||
}
|
||||
else if (fake)
|
||||
error("no structure name");
|
||||
else if( sp->s_sc != STRPROTO )
|
||||
error("invalid structure prototype: %.8s",sp->s_symbol);
|
||||
else if( !dtab[sp->s_ssp] ) { /* FRSTRUCT */
|
||||
if (struc_sib[in_struct]) { /* 4.2+ don't access off of zero */
|
||||
#ifndef SYM_TO_DSK
|
||||
if (struc_sib[in_struct]->s_type == STRUCT) { /* [vlh] 4.2.e */
|
||||
#else
|
||||
read_st(&volatile,struc_sib[in_struct]);
|
||||
if (volatile.s_type == STRUCT) { /* [vlh] 4.2.e */
|
||||
#endif
|
||||
struc_sib[in_struct] = hold_sib;
|
||||
if (hold_sib) {
|
||||
#ifndef SYM_TO_DSK
|
||||
hold_sib->s_sib = hold_sib->s_par = 0;
|
||||
#else
|
||||
read_st(&volatile,hold_sib);
|
||||
volatile.s_sib = volatile.s_par = 0;
|
||||
write_st(&volatile,hold_sib);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
token = FRSTRUCT;
|
||||
if( ++frstp >= NFRSTR )
|
||||
ferror("structure table overflow");
|
||||
#ifndef SYM_TO_DSK
|
||||
frstab[frstp] = sp;
|
||||
#else
|
||||
frstab[frstp] = sp_addr;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
*ptsize = dtab[sp->s_ssp];
|
||||
tdflag = stdflag;
|
||||
if( *pdtype != TYPELESS )
|
||||
error("invalid type declaration");
|
||||
*pdtype = (token == R_UNION) ? STRUCT : token;
|
||||
return(token);
|
||||
}
|
||||
|
||||
/*
|
||||
* dodecl - process a single declarator
|
||||
* This does all the grubby handling of a single declarator given
|
||||
* the attributes for the declarator. Handles typedef attributes
|
||||
* adjusts offsets for structure elements, allocates register
|
||||
* variables, etc.
|
||||
*/
|
||||
long /* [vlh] 3.4 short => long */
|
||||
dodecl(sc,type,offset,size) /* returns size of declarator*/
|
||||
int sc; /* storage class*/
|
||||
int type; /* data type*/
|
||||
int offset; /* offset if in structure or union*/
|
||||
long size; /* size of single data item 3.4 i=> l*/
|
||||
{
|
||||
register struct symbol *sp;
|
||||
register short dtype, j;
|
||||
long constval;
|
||||
#ifdef SYM_TO_DSK
|
||||
struct symbol sp_entry;
|
||||
long sp_addr;
|
||||
#endif
|
||||
|
||||
if( PEEK(SEMI) || PEEK(RPAREN) )
|
||||
return(0);
|
||||
if( in_struct && next(COLON) ) { /*handle bit filler field*/
|
||||
if(!(constval=cexpr()))
|
||||
size = salign(INT,offset);
|
||||
else
|
||||
size = falign(type,(int)constval,offset);
|
||||
}
|
||||
else if( (type |= declarator(0)) >= 0 && dsp != 0 ) {
|
||||
#ifdef SYM_TO_DSK
|
||||
read_st(dsp,dsp_addr); /* be sure we have latest !!! */
|
||||
ASSG(sp_addr,dsp_addr,sp_entry,dsp_entry,sp);
|
||||
#else
|
||||
sp = dsp;
|
||||
#endif
|
||||
if (ISFUNCTION(type)) /* [vlh] 4.2 */
|
||||
sp->s_scope = GLOB_SCOPE;
|
||||
if (tdp) { /*typedef name in declaration*/
|
||||
type = addtdtype(tdp,type,sp->s_dp,&(sp->s_ssp));
|
||||
if (BTYPE(type)==STRUCT) /* [vlh] 4.2 */
|
||||
sp->s_child = sp->s_par = tdp->s_par;
|
||||
}
|
||||
else if( BTYPE(type) == STRUCT ) {
|
||||
sp->s_par = struc_parent[0]; /* [vlh] 4.2 */
|
||||
if( size )
|
||||
sp->s_ssp = dalloc(size);
|
||||
else
|
||||
error("invalid structure declaration: %.8s",sp->s_symbol);
|
||||
}
|
||||
else if( BTYPE(type) == FRSTRUCT )
|
||||
sp->s_ssp = frstp;
|
||||
TO_DSK(sp,sp_addr);
|
||||
READ_ST(dsp,dsp_addr);
|
||||
switch( sp->s_sc ) { /*check for redeclarations.*/
|
||||
|
||||
case STELCL:
|
||||
case UNELCL:
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case PARMLIST:
|
||||
if (sc != PDECLIST && sc != PDECREG)
|
||||
goto redec;
|
||||
break;
|
||||
|
||||
case BFIELDCL:
|
||||
if (sc != STELCL && sc != UNELCL)
|
||||
goto redec;
|
||||
break;
|
||||
|
||||
case STATIC: /* [vlh] 4.2, incomplete handling */
|
||||
if (ISFUNCTION(sp->s_type))
|
||||
break;
|
||||
goto redec;
|
||||
|
||||
case DEXTERN:
|
||||
case EXTERNAL:
|
||||
if (sp->s_type == type) {
|
||||
if (sc == sp->s_sc || sc == EXTERNAL || sc == DEXTERN)
|
||||
break;
|
||||
if (ISFUNCTION(sp->s_type) && sc == STATIC) /* [vlh] 4.2 */
|
||||
break;
|
||||
if (sc == AUTO && SUPTYPE(type) == FUNCTION) {
|
||||
sc = EXTERNAL;
|
||||
break;
|
||||
}
|
||||
} /* fall through...... */
|
||||
default:
|
||||
redec:
|
||||
#ifdef DEBUG
|
||||
if (treedebug) {
|
||||
printf("redec4 typ %d %d sc %d %d ",sp->s_type,type,sp->s_sc,sc);
|
||||
printf("scope %d %d\n",sp->s_scope,scope_level);
|
||||
}
|
||||
#endif
|
||||
if(scope_level==GLOB_SCOPE) /*[vlh] 4.3, extern signif to 7*/
|
||||
error("redeclaration: %.7s",sp->s_symbol);
|
||||
else
|
||||
error("redeclaration: %.8s",sp->s_symbol);
|
||||
return(size);
|
||||
}
|
||||
sp->s_type = type;
|
||||
dtype = SUPTYPE(type);
|
||||
type = BTYPE(type);
|
||||
if( tdflag ) /*we are declaring typedef?*/
|
||||
sp->s_attrib |= STYPEDEF;
|
||||
if( in_struct ) {
|
||||
if( next(COLON) ) { /*handle bit field*/
|
||||
sc = BFIELDCL;
|
||||
constval = cexpr();
|
||||
sp->s_dp = (boffset<<8) | ((int)constval);
|
||||
size = j = falign(type,(int)constval,offset);
|
||||
if (j) /* [vlh] 4.2 implies move to new word.... */
|
||||
sp->s_dp = (int)constval;
|
||||
}
|
||||
else {
|
||||
j=salign(sp->s_type,offset); /* [vlh] 4.1 type is not enough */
|
||||
size = dsize(sp->s_type,sp->s_dp,sp->s_ssp) + j;
|
||||
}
|
||||
offset += j;
|
||||
sp->s_offset = offset;
|
||||
#ifdef DEBUG
|
||||
if(symdebug) printf("%s <= offset %d\n",sp->s_symbol,offset);
|
||||
#endif
|
||||
}
|
||||
if( dtype == FUNCTION ) {
|
||||
if( sc != AUTO && sc != EXTERNAL && sc != DEXTERN && sc != STATIC )
|
||||
error("illegal function declaration");
|
||||
if( sc != STATIC )
|
||||
sc = EXTERNAL;
|
||||
}
|
||||
else if (sc == REGISTER || sc == PDECREG) { /*[vlh]4.3, add PDECREG*/
|
||||
if( !dtype ) {
|
||||
if( !(dinfo[type]&DREG) || !dregtab[ndregs] )
|
||||
sc = AUTO;/* ignore reg specification */
|
||||
else
|
||||
sp->s_offset = dregtab[ndregs++];
|
||||
}
|
||||
else if( !aregtab[naregs] || dtype!=POINTER )
|
||||
sc = AUTO; /*no more regs, make it auto*/
|
||||
else
|
||||
sp->s_offset = aregtab[naregs++];
|
||||
}
|
||||
if( sc == AUTO ) {
|
||||
localsize += WALIGN(dsize(sp->s_type,sp->s_dp,sp->s_ssp));
|
||||
sp->s_offset = -localsize;
|
||||
}
|
||||
else if( sc == STATIC )
|
||||
sp->s_offset = nextlabel++;
|
||||
sp->s_sc = sc;
|
||||
sp->s_attrib |= SDEFINED;
|
||||
if(!infunc)
|
||||
sp->s_attrib |= SGLOBAL;
|
||||
TO_DSK(sp,sp_addr);
|
||||
READ_ST(dsp,dsp_addr);
|
||||
/* trying to output locals in the appropriate order.... */
|
||||
if (infunc && scope_level==FUNC_SCOPE)
|
||||
if (sc==STATIC || sc==PDECREG || sc==REGISTER || sc==AUTO)
|
||||
outlocal(type,sc,sp->s_symbol,sp->s_offset);
|
||||
}
|
||||
return(size);
|
||||
}
|
||||
|
||||
/*
|
||||
* funcbody - do function body declaration
|
||||
* Basically handles function after we have scanned the parameter
|
||||
* list, which is now set up in fargs array. We now proceed to
|
||||
* look for any declarations for the function arguments, then the
|
||||
* function declaration list, followed by the function statement list.
|
||||
* The C syntax is:
|
||||
* function_body:
|
||||
* type_decl_list function_statement
|
||||
* function_statement:
|
||||
* { declaration_list statement_list }
|
||||
*/
|
||||
funcbody(fsp)
|
||||
struct symbol *fsp;
|
||||
{
|
||||
register short olddp, offset, toff;
|
||||
register struct symbol *sp;
|
||||
register struct farg *fp;
|
||||
#ifdef SYM_TO_DSK
|
||||
struct symbol sp_str; /* hold fp... */
|
||||
long sp_addr; /* addresses */
|
||||
#endif
|
||||
|
||||
infunc++;
|
||||
opap = exprp;
|
||||
sp = fsp;
|
||||
frp = (struct farg *)snalloc(delsp(sp->s_type),sp->s_sc,sp->s_type,
|
||||
sp->s_dp, sp->s_ssp);
|
||||
exprp = opap;
|
||||
OUTTEXT();
|
||||
OUTFLAB(fsp->s_symbol);
|
||||
olddp = cdp;
|
||||
dlist(PDECLIST);
|
||||
rlabel = nextlabel++;
|
||||
if(!next(LCURBR))
|
||||
synerr("function body syntax");
|
||||
else {
|
||||
localsize = 0; /*end of first auto offset from l.e.p.*/
|
||||
offset = 8; /*first arg offset from l.e.p.*/
|
||||
scope_level = FUNC_SCOPE; /* [vlh] 4.2 */
|
||||
scope_decls[FUNC_SCOPE] = 1; /* [vlh] 4.2, force at this level */
|
||||
for( fp = &fargtab[0]; fp->f_sp; fp++ ) {
|
||||
#ifndef SYM_TO_DSK
|
||||
sp = fp->f_sp;
|
||||
#else
|
||||
sp_addr = fp->f_sp;
|
||||
sp = &sp_str;
|
||||
read_st(sp,sp_addr);
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
if(symdebug)
|
||||
printf("farg: %s type 0%o sc %d\n",sp->s_symbol,sp->s_type,sp->s_sc);
|
||||
#endif
|
||||
toff = offset;
|
||||
if( sp->s_type == CHAR ) /*char argument*/
|
||||
toff++; /*offset of lower byte in word*/
|
||||
if( sp->s_sc == PDECREG ) {
|
||||
fp->f_offset = toff;
|
||||
sp->s_sc = REGISTER;
|
||||
}
|
||||
else {
|
||||
fp->f_offset = 0; /*really is auto arg*/
|
||||
sp->s_offset = toff;
|
||||
sp->s_sc = AUTO;
|
||||
}
|
||||
if( ISARRAY(sp->s_type) ) { /*change array ref to pointer*/
|
||||
sp->s_type = addsp(delsp(sp->s_type),POINTER);
|
||||
sp->s_dp++;
|
||||
}
|
||||
TO_DSK(sp,sp_addr);
|
||||
offset += WALIGN(dsize(sp->s_type,sp->s_dp,sp->s_ssp));
|
||||
/* [vlh] 4.2, output argument list for debugger */
|
||||
if (sp->s_sc==STATIC || sp->s_sc==AUTO) /* [vlh] not register... */
|
||||
outlocal(sp->s_type,sp->s_sc,sp->s_symbol,sp->s_offset);
|
||||
}
|
||||
if (gflag)
|
||||
outlocal(CHAR,AUTO,"_EnD__",offset); /*[vlh] 4.2, for cdb */
|
||||
offset += 2; /* [vlh] 4.2, for cdb, argument end argument */
|
||||
OUTBENTRY(); /* [vlh] 4.2, must be before declarations */
|
||||
dlist(TYPELESS); /* [vlh] 4.1 was just a zero... */
|
||||
chksyms(0);
|
||||
#ifndef NOPROFILE
|
||||
if(profile)
|
||||
OUTPCALL(fsp->s_symbol);
|
||||
#endif
|
||||
copyargs(); /*copy args to registers where required*/
|
||||
while(!next(RCURBR)) {
|
||||
if( next(EOF) ) {
|
||||
error("{ not matched by }");
|
||||
break;
|
||||
}
|
||||
instmt=1;
|
||||
stmt();
|
||||
instmt=0;
|
||||
}
|
||||
}
|
||||
OUTLAB(rlabel);
|
||||
outbexit(localsize,ndregs,naregs);
|
||||
freesyms(FUNC_SCOPE);
|
||||
cdp = olddp;
|
||||
infunc--;
|
||||
}
|
||||
|
||||
/*
|
||||
* copyargs - copy args to register where required
|
||||
* fargtab has been set so that args declared to be registers have a
|
||||
* non-zero offset value and the register number is in the symbol
|
||||
* table pointed to by symbol.
|
||||
*/
|
||||
copyargs() /* returns - none*/
|
||||
{
|
||||
register struct symbol *sp;
|
||||
register struct farg *fp;
|
||||
#ifdef SYM_TO_DSK
|
||||
struct symbol sp_str;
|
||||
|
||||
sp = &sp_str;
|
||||
#endif
|
||||
|
||||
for( fp = &fargtab[0]; fp->f_sp; fp++ ) {
|
||||
#ifndef SYM_TO_DSK
|
||||
sp = fp->f_sp;
|
||||
#else
|
||||
read_st(sp,fp->f_sp);
|
||||
#endif
|
||||
if( fp->f_offset ) /*was declared register*/
|
||||
outassign(snalloc(sp->s_type,sp->s_sc,sp->s_offset,0,0),
|
||||
snalloc(sp->s_type,AUTO,fp->f_offset,0,0));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* dlist - declaration list
|
||||
* Handles declaration lists in the following places:
|
||||
* function parameter list declarations, structure or union member
|
||||
* declarations and local declarations in functions.
|
||||
*/
|
||||
long
|
||||
dlist(defsc) /* returns length of declarators*/
|
||||
int defsc; /* default storage class*/
|
||||
{
|
||||
register short offset;
|
||||
register long lret, ddsize;
|
||||
struct tnode *tp;
|
||||
char *p;
|
||||
long size; /* [vlh] 3.4 short => long */
|
||||
short type, sc;
|
||||
|
||||
offset = 0; ddsize = 0L;
|
||||
do {
|
||||
sc = defsc;
|
||||
type = INT;
|
||||
if( !gettype(&sc,&type,&size,1) )
|
||||
break;
|
||||
indecl = 1;
|
||||
do {
|
||||
lret = dodecl(sc,type,offset,size);
|
||||
if( defsc != UNELCL ) {
|
||||
offset += (int)lret;
|
||||
ddsize += lret;
|
||||
}
|
||||
else if( lret > ddsize )
|
||||
ddsize = lret;
|
||||
if( sc == STATIC && dsp && !ISTYPEDEF(dsp) )
|
||||
doinit(dsp); /*process any initializer*/
|
||||
ZERO_DSP();
|
||||
|
||||
if (next(ASSIGN)) { /* [vlh] 4.2 auto initialization */
|
||||
indecl = 0; /* don't redeclare expr vars */
|
||||
READ_ST(csp,csp_addr);
|
||||
if (!SIMPLE_TYP(csp->s_type) && NOTPOINTER(csp->s_type)) {
|
||||
synerr("illegal autoinitialization data type");
|
||||
break;
|
||||
}
|
||||
peektok = ASSIGN;
|
||||
commastop++; /* stop initializing at a comma */
|
||||
expr_setup(); /* setup expr op stack */
|
||||
p = get_symbol();
|
||||
if (doopd(p))
|
||||
synerr("auto initilization syntax");
|
||||
else
|
||||
if ((tp = (struct tnode *)expr(1)) != 0)
|
||||
outexpr(tp);
|
||||
else
|
||||
synerr("auto initialization syntax");
|
||||
commastop--; /* back to previous comma handling */
|
||||
indecl = 1;
|
||||
}
|
||||
} while ( next(COMMA) );
|
||||
if(!next(SEMI)) {
|
||||
synerr("declaration syntax");
|
||||
tdflag = 0; /* [vlh] 4.2.b reset on sighting a semicolon */
|
||||
break;
|
||||
}
|
||||
tdflag = 0; /* [vlh] 4.2.b reset on sighting a semicolon */
|
||||
} while( 1 );
|
||||
ddsize += salign(INT,(int)ddsize);
|
||||
return(ddsize);
|
||||
}
|
||||
|
||||
/*
|
||||
* declarator - get one declarator
|
||||
* Basically uses getdecl, which returns the declaration types
|
||||
* reversed in the type word.
|
||||
*/
|
||||
declarator(castflg) /* returns type or -1*/
|
||||
int castflg;
|
||||
{
|
||||
short type;
|
||||
|
||||
ZERO_DSP();
|
||||
if( (type=getdecl(castflg)) >= 0 )
|
||||
return( revsp(type) );
|
||||
return(type);
|
||||
}
|
||||
|
||||
/*
|
||||
* getdecl - get one declarator, handling *, (), etc.
|
||||
* The significance of the value returned by declarator is: the
|
||||
* least significant two bits represent the values (POINTER,FUNCTION,
|
||||
* ARRAY), these values are repeated through the word. For example,
|
||||
* the declarations result in the following values for declarator:
|
||||
* *x() => (POINTER,FUNCTION)
|
||||
* (*x)() => (FUNCTION,POINTER)
|
||||
* *(*x)() => (POINTER,FUNCTION,POINTER)
|
||||
* The following C syntax is handled here:
|
||||
* function_declarator:
|
||||
* declarator ( parameter_list )
|
||||
* declarator:
|
||||
* identifier
|
||||
* ( declarator )
|
||||
* * declarator
|
||||
* declarator [ constant-expression ]
|
||||
*/
|
||||
getdecl(castflg) /* returns special type of declarator*/
|
||||
int castflg; /* casting flag, 1=>allow no declarator*/
|
||||
{
|
||||
register short type, i, sdp;
|
||||
register struct symbol *sp, *tsp, *p;
|
||||
register struct farg *fp;
|
||||
long lvalue, value;
|
||||
#ifdef SYM_TO_DSK
|
||||
long tsp_addr;
|
||||
long sp_addr;
|
||||
struct symbol sp_entry;
|
||||
struct symbol tsp_entry;
|
||||
#endif
|
||||
|
||||
type = 0;
|
||||
if( next(LPAREN) ) { /*( declarator ) ...*/
|
||||
type = getdecl(castflg);
|
||||
if(!next(RPAREN))
|
||||
goto baddec;
|
||||
}
|
||||
if( next(MULT) )
|
||||
return(addsp(getdecl(castflg),POINTER));
|
||||
sdp = cdp;
|
||||
if( next(SYMBOL) ) {
|
||||
#ifdef SYM_TO_DSK
|
||||
ASSG(dsp_addr,csp_addr,dsp_entry,csp_entry,dsp);
|
||||
ASSG(sp_addr,dsp_addr,sp_entry,dsp_entry,sp);
|
||||
#else
|
||||
sp = dsp = csp;
|
||||
#endif
|
||||
type = 0;
|
||||
sp->s_dp = sdp;
|
||||
TO_DSK(sp,sp_addr);
|
||||
}
|
||||
while( 1 ) {
|
||||
if( next(LPAREN) ) { /*declarator ( ... )*/
|
||||
if(!infunc) {
|
||||
ndregs = naregs = 0;
|
||||
scope_level = FUNC_SCOPE; /* [vlh] 4.2 */
|
||||
indecl++; /* [vlh] 4.3 */
|
||||
for( fp = &fargtab[0]; PNEXT(); ) {
|
||||
p = csp;
|
||||
if( p->s_attrib & SDEFINED ) {
|
||||
#ifdef DEBUG
|
||||
if (treedebug) {
|
||||
printf("redec1 typ %d %d sc %d",p->s_type,type,p->s_sc);
|
||||
printf("scope %d %d\n",p->s_scope,scope_level);
|
||||
}
|
||||
#endif
|
||||
error("redeclaration: %.8s",p->s_symbol);
|
||||
}
|
||||
else if( fp >= &fargtab[NFARGS-1] ) {
|
||||
synerr("too many parameters");
|
||||
break;
|
||||
}
|
||||
else {
|
||||
p->s_attrib |= SDEFINED;
|
||||
p->s_scope = FUNC_SCOPE;
|
||||
p->s_sc = PARMLIST;
|
||||
p->s_type = INT; /*default to int*/
|
||||
#ifndef SYM_TO_DSK
|
||||
fp->f_sp = p;
|
||||
#else
|
||||
fp->f_sp = csp_addr;
|
||||
#endif
|
||||
fp++;
|
||||
TO_DSK(p,csp_addr);
|
||||
}
|
||||
if(!next(COMMA))
|
||||
break;
|
||||
}
|
||||
indecl--; /* [vlh] 4.3, must not confuse, we are in decls */
|
||||
fp->f_sp = 0;
|
||||
}
|
||||
if(!next(RPAREN))
|
||||
break;
|
||||
if (!infunc && fp == &fargtab[0]) /* [vlh] 4.2 */
|
||||
scope_level = GLOB_SCOPE;
|
||||
type = addsp(type,FUNCTION);
|
||||
continue;
|
||||
}
|
||||
if( next(LBRACK) ) { /*declarator [ cexpr ]*/
|
||||
if( next(RBRACK) )
|
||||
dalloc(1L);
|
||||
else {
|
||||
#ifdef SYM_TO_DSK
|
||||
ASSG(tsp_addr,dsp_addr,tsp_entry,dsp_entry,tsp);
|
||||
value = cexpr(); /* recurses on sizeof.... resets dsp */
|
||||
if (dsp_addr != tsp_addr) { /* [vlh] 4.2.... */
|
||||
tsp->s_dp = cdp;
|
||||
write_st(&tsp_entry,tsp_addr);
|
||||
ASSG(dsp_addr,tsp_addr,dsp_entry,tsp_entry,dsp);
|
||||
}
|
||||
#else
|
||||
tsp = dsp; /* [vlh] 3.4 save in case of reset */
|
||||
value = cexpr(); /* recurses on sizeof.... resets dsp */
|
||||
if (dsp != tsp) { /* [vlh] 4.2.... */
|
||||
tsp->s_dp = cdp;
|
||||
dsp = tsp; /* [vlh] 3.4 */
|
||||
}
|
||||
#endif
|
||||
lvalue = value; /* [vlh] 3.4 */
|
||||
for( i = sdp; i < cdp; i++)
|
||||
dtab[i] *= lvalue;
|
||||
dalloc(lvalue);
|
||||
if( !next(RBRACK) )
|
||||
break;
|
||||
}
|
||||
type = addsp(type,ARRAY);
|
||||
continue;
|
||||
}
|
||||
if( castflg || dsp ) {
|
||||
if (!infunc && castflg)
|
||||
scope_level = GLOB_SCOPE; /* [vlh] 4.2 */
|
||||
return(type);
|
||||
}
|
||||
break;
|
||||
}
|
||||
baddec:
|
||||
synerr("invalid declarator");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* addtdtype - add typedef info into declarator
|
||||
* here we very carefully add in the dimensions for an array typedef
|
||||
* declaration. Note that declarator has already allocated the
|
||||
* declarator-specific dimensions, now we allocate the typedef
|
||||
* dimensions and adjust the size of the declarator's dimensions.
|
||||
* Note that this must be done before the dalloc for the structure,
|
||||
* otherwise we would mix up array and structure sizes.
|
||||
*/
|
||||
addtdtype(tddp,type,dp,ssp) /* returns type*/
|
||||
struct symbol *tddp;
|
||||
int type;
|
||||
int dp;
|
||||
int *ssp;
|
||||
{
|
||||
register short ntype, t, i, tdf;
|
||||
|
||||
for( tdf = 0, t = tddp->s_type; SUPTYPE(t); t = delsp(t) )
|
||||
if( ISARRAY(t) ) {
|
||||
tdf++;
|
||||
break;
|
||||
}
|
||||
ntype = 0;
|
||||
for( t = type, i = dp; SUPTYPE(t); t = delsp(t) ) {
|
||||
ntype = addsp(ntype,t);
|
||||
if( tdf && ISARRAY(t) ) {
|
||||
dtab[i] *= dtab[tddp->s_dp];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
for( t = tddp->s_type, i = tddp->s_dp; SUPTYPE(t); t = delsp(t) )
|
||||
if( ISARRAY(t) )
|
||||
dalloc(dtab[i++]);
|
||||
for( t = tddp->s_type; SUPTYPE(ntype); ntype = delsp(ntype) )
|
||||
t = addsp(t,ntype);
|
||||
if( (ntype=BTYPE(t)) == STRUCT )
|
||||
*ssp = tddp->s_ssp;
|
||||
else if( ntype == FRSTRUCT )
|
||||
*ssp = frstp;
|
||||
return(t);
|
||||
}
|
||||
Reference in New Issue
Block a user