/* * Declare a static variable (i.e. define for use) * * makes an entry in the symbol table so subsequent * references can call symbol by name */ void declglb( int typ , /* typ is CCHAR, CINT, DOUBLE, STRUCT, LONG, */ int storage, TAG_SYMBOL *mtag , /* tag of struct whose members are being declared, or zero */ TAG_SYMBOL *otag , /* tag of struct for object being declared */ int is_struct , /* TRUE if struct member being declared, zero if union */ char sign , /* TRUE if need signed */ char zfar ) /* TRUE if far */ { char sname[NAMESIZE]; int size, ident, more, itag, type, size_st; long addr = -1; char flagdef,match,ptrtofn; char libdef,fastcall,callee; SYMBOL *myptr ; do { if ( endst() ) break; /* do line */ type = typ ; size = 1 ; /* assume 1 element */ more = /* assume dummy symbol not required */ itag = 0 ; /* just for tidiness */ flagdef=libdef=fastcall=callee=NO; match=ptrtofn=NO; while (blanks(),rcmatch('_') ) { match=NO; if (amatch("__APPFUNC__") ) { match=YES; flagdef=1; } if (amatch("__LIB__") /* && libdef==0 */) {match=YES; libdef|=LIBRARY; } if (amatch("__FASTCALL__") ) {match=YES; fastcall=REGCALL; } if (amatch("__SHARED__") ) {match=YES; libdef|=SHARED; } if (amatch("__SHAREDC__") ) {match=YES; libdef|=SHAREDC; } if (amatch("__CALLEE__") ) {match=YES; callee=CALLEE; } if (match ==NO )break; } ident = get_ident() ; if (storage==TYPDEF && ident !=VARIABLE && mtag ==0 ) warning(W_TYPEDEF); if ( symname(sname) == 0 ) /* name ok? */ illname(sname) ; /* no... */ if ( ident == PTR_TO_FNP ) { /* function returning pointer needs dummy symbol */ more = dummy_idx(typ, otag) ; type = (zfar ? CPTR : CINT ); size=0; ptrtofn=YES; } else if ( ident == PTR_TO_FN ) { ident = POINTER ; ptrtofn=YES; #if 0 } else if ( cmatch('@') ) { storage = EXTERNP; constexpr(&addr,1); #endif } else if ( cmatch('(') ) { /* * Here we check for functions, but we can never have a pointer to * function because thats considered above. Which means as a very * nice side effect that we don't have to consider structs/unions * since they can't contain functions, only pointers to functions * this, understandably(!) makes the work here a lot, lot easier! */ storage=AddNewFunc(sname,type,storage,zfar,sign,otag,ident,&addr); /* * On return from AddNewFunc, storage will be: * EXTERNP = external pointer, in which case addr will be set * !! FUNCTION = have prototyped a function (NOT USED!) * 0 = have declared a function/!! prototyped ANSI * * If 0, then we have to get the hell out of here, FUNCTION * then gracefully loop round again, if EXTERNP, carry on with * this function, anything else means that we've come up * against a K&R style function definition () so carry on * as normal! * * If we had our function prefixed with __APPFUNC__ then we want * to write it out to the zcc_opt.def file (this bloody thing * is becoming invaluable for messaging! * * __SHARED__ indicates in a library so preserve carry flag * (so we can test with iferror) * * __CALLEE__ indicates that the function called cleans up * the stack * * __SHAREDC__ is indicates call by rst 8 but is unused.. * (old idea unused, but may yet be useful) */ if (flagdef) WriteDefined(sname,0); if (currfn) { /* djm 1/2/03 - since we can override lib functions don't reset the library flag currfn->flags&=(~LIBRARY); */ if (libdef) { // currfn->flags|=LIBRARY; currfn->flags|=libdef; } if (callee && (libdef&SHARED) != SHARED && \ (libdef&SHAREDC) != SHAREDC ) currfn->flags|=callee; if (fastcall) currfn->flags|=fastcall; } if (storage==0) { if ( addr != -1 ) { currfn->size = addr; } return; } /* * External pointer..check for the closing ')' */ if (storage==EXTERNP) { needchar(')'); } else { /* * Must be a devilishly simple prototype! ();/, type... */ ptrerror(ident) ; if ( ident == POINTER ) { /* function returning pointer needs dummy symbol */ more = dummy_idx(typ, otag) ; type = (zfar ? CPTR : CINT ); ident=FUNCTIONP; } else { ident=FUNCTION; } size = 0 ; } } if (cmatch('[')) { /* array? */ ptrerror(ident) ; if ( ident == POINTER) { /* array of pointers needs dummy symbol */ more = dummy_idx(typ, otag) ; type = (zfar ? CPTR : CINT ); } size = needsub() ; /* get size */ if (size == 0 && ident == POINTER ) size=0; ident = ARRAY; if ( ptrtofn ) needtoken(")()"); } else if ( ptrtofn ) { needtoken(")()") ; } else if ( ident == PTR_TO_PTR ) { ident = POINTER ; more = dummy_idx(typ, otag) ; type = (zfar ? CPTR : CINT ); } if ( cmatch('@') ) { storage = EXTERNP; constexpr(&addr,1); }
/** * declare a static variable * @param type * @param storage * @param mtag tag of struct whose members are being declared, or zero * @param otag tag of struct object being declared. only matters if mtag is non-zero * @param is_struct struct or union or no meaning * @return 1 if a function was parsed */ int declare_global(int type, int storage, TAG_SYMBOL *mtag, int otag, int is_struct) { int dim, identity; char sname[NAMESIZE]; FOREVER { FOREVER { if (endst ()) return 0; dim = 1; if (match ("*")) { identity = POINTER; } else { identity = VARIABLE; } if (!symname (sname)) illname (); if (match ("(")) { /* FIXME: We need to deal with pointer types properly here */ if (identity == POINTER) type = CINT; newfunc_typed(storage, sname, type); /* Can't int foo(x){blah),a=4; */ return 1; } /* FIXME: we need to deal with extern properly here */ if (find_global (sname) > -1) multidef (sname); if (identity == VARIABLE) notvoid(type); if (match ("[")) { dim = needsub (); //if (dim || storage == EXTERN) { identity = ARRAY; //} else { // identity = POINTER; //} } // add symbol if (mtag == 0) { // real variable, not a struct/union member identity = initials(sname, type, identity, dim, otag); add_global (sname, identity, type, (dim == 0 ? -1 : dim), storage); if (type == STRUCT) { symbol_table[current_symbol_table_idx].tagidx = otag; } break; } else if (is_struct) { // structure member, mtag->size is offset add_member(sname, identity, type, mtag->size, storage); // store (correctly scaled) size of member in tag table entry if (identity == POINTER) type = CINT; scale_const(type, otag, &dim); mtag->size += dim; } else { // union member, offset is always zero add_member(sname, identity, type, 0, storage); // store maximum member size in tag table entry if (identity == POINTER) type = CINT; scale_const(type, otag, &dim); if (mtag->size < dim) mtag->size = dim; } } if (!match (",")) return 0; } }
/** * declare local variables * works just like "declglb", but modifies machine stack and adds * symbol table entry with appropriate stack offset to find it again * @param typ * @param stclass * @param otag index of tag in tag_table */ void declare_local(int typ, int stclass, int otag) { int k, j; char sname[NAMESIZE]; FOREVER { FOREVER { if (endst()) return; if (match("*")) j = POINTER; else j = VARIABLE; if (!symname(sname)) illname(); if (-1 != find_locale(sname)) multidef (sname); if (match("[")) { k = needsub(); if (k) { j = ARRAY; if (typ & CINT) { k = k * INTSIZE; } else if (typ == STRUCT) { k = k * tag_table[otag].size; } } else { j = POINTER; k = INTSIZE; } } else { if (j == POINTER) { k = INTSIZE; } else { switch (typ) { case CCHAR: case UCHAR: k = 1; break; case STRUCT: k = tag_table[otag].size; break; default: k = INTSIZE; } } } if (stclass == LSTATIC) { add_local(sname, j, typ, k, LSTATIC); break; } if (stclass == REGISTER) { int r = gen_register(j, k, typ); if (r != -1) { add_local(sname, j, typ, r, REGISTER); break; } } if (match("=")) { gen_modify_stack(stkp); expression(0); gen_push(0); } else stkp = gen_defer_modify_stack(stkp - k); add_local(sname, j, typ, stkp, AUTO); break; } if (!match(",")) return; } }
SYMBOL * #endif getarg( int typ , /* typ = CCHAR, CINT, DOUBLE or STRUCT */ TAG_SYMBOL *otag , /* structure tag for STRUCT type objects */ int deftype, /* YES=ANSI -> addloc NO=K&R -> findloc */ SYMBOL *prevarg, /* ptr to previous argument, only of use to ANSI */ char issigned, /* YES=unsigned NO=signed */ char zfar, /* FARPTR=far NO=near */ char proto) /* YES=prototyping -> names not needed */ { char n[NAMESIZE] ; SYMBOL *argptr ; int legalname, ident, more ; int brkflag; /* Needed to correctly break out for K&R*/ /* * This is of dubious need since prototyping came about, we could * inadvertently include fp packages if the user includes <math.h> but * didn't actually use them, we'll save the incfloat business for * static doubles and definitions of local doubles * * if (typ == DOUBLE) * incfloat=1; */ argptr = NULL; /* Only need while loop if K&R defs */ while ( undeclared) { ident = get_ident() ; more =0; if ( (legalname=symname(n)) == 0 ) { if (!proto) { illname(n); } else { /* * Obligatory silly fake name */ sprintf(n,"sg6p_%d",proto); legalname=1; } } if ( ident == FUNCTIONP ) { needtoken(")()"); /* function returning pointer needs dummy symbol */ more = dummy_idx(typ, otag) ; typ = (zfar ? CPTR : CINT ); } else if ( ident == PTR_TO_FN ) { needtoken(")()") ; ident = POINTER ; } if ( cmatch('[') ) { /* pointer ? */ ptrerror(ident) ; /* it is a pointer, so skip all */ /* stuff between "[]" */ while ( inbyte() != ']' ) if ( endst() ) break; /* add entry as pointer */ ident = (ident == POINTER) ? PTR_TO_PTR : POINTER ; } if ( legalname ) { /* * For ANSI we need to add symbol name to local table - this CINT is * temporary */ if (deftype) { argptr=addloc(n,0,CINT,0,0); argptr->offset.p = prevarg; } /* * If prototyping, then we can't find the name, but if we're prototyping * we have been defined as ANSI, therefore argptr already holds * the correct pointer - kinda neat! */ if ( proto || (argptr=findloc(n)) ) { argptr->flags=(zfar&FARPTR)|(issigned&UNSIGNED); /* add in details of the type of the name */ if ( ident == PTR_TO_PTR ) { /* djm mods will be here for long pointer */ // argptr->flags = UNSIGNED |FARPTR ; /*unsigned*/ argptr->ident = POINTER ; argptr->type = typ; // argptr->type = ( (zfar&FARPTR) ? CPTR : CINT ); argptr->more = dummy_idx(typ, otag) ; } else { argptr->more = more; argptr->ident = ident ; argptr->type = typ ; } } else warning(W_EXPARG); if ( otag ) { argptr->tag_idx = otag - tagtab ; argptr->ident = POINTER ; argptr->type = STRUCT ; } } brkflag=0; if (!deftype) { --undeclared; /* cnt down */ if ( endst() ) { brkflag=1; break; } if ( cmatch(',') == 0 ) warning(W_EXPCOM) ; } if (brkflag || deftype) break; } if (deftype) return(argptr); ns(); return(0); }