/* 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); }