/** * perform a function call * called from "hier11", this routine will either call the named * function, or if the supplied ptr is zero, will call the contents * of HL * @param ptr name of the function */ void callfunction(char *ptr) { int nargs; nargs = 0; blanks (); if (ptr == 0) gen_push (HL_REG); while (!streq (line + lptr, ")")) { if (endst ()) break; expression (NO); if (ptr == 0) gen_swap_stack (); gen_push (HL_REG); nargs = nargs + INTSIZE; if (!match (",")) break; } needbrack (")"); if (aflag) gnargs(nargs / INTSIZE); if (ptr) gen_call (ptr); else callstk (); stkp = gen_modify_stack (stkp + nargs); }
/** * declare argument types * called from "newfunc", this routine adds an entry in the local * symbol table for each named argument * completely rewritten version. p.l. woods * @param t argument type (char, int) * @return */ void getarg(int t) { int j, legalname, address, argptr; char n[NAMESIZE]; FOREVER { if (argstk == 0) return; if (match("*")) j = POINTER; else j = VARIABLE; if (!(legalname = symname(n))) illname(); if (match("[")) { while (inbyte() != ']') if (endst()) break; j = POINTER; } if (legalname) { if ((argptr = find_locale(n)) > -1) { symbol_table[argptr].identity = j; symbol_table[argptr].type = t; address = argtop - symbol_table[argptr].offset; symbol_table[argptr].offset = address; } else error("expecting argument name"); } argstk = argstk - INTSIZE; if (endst()) return; if (!match(",")) error("expected comma"); } }
void doLocalAnsiArgument(int type) { char symbol_name[NAMESIZE]; int identity, address, argptr, ptr; if (match("*")) { identity = POINTER; } else { if (type == STRUCT) { error("cannot pass struct"); return; } identity = VARIABLE; if (type == VOID) return; } if (symname(symbol_name)) { if (find_locale(symbol_name) > -1) { multidef(symbol_name); } else { argptr = add_local (symbol_name, identity, type, 0, AUTO); argstk = argstk + INTSIZE; ptr = local_table_index; while (ptr != NUMBER_OF_GLOBALS) { // modify stack offset as we push more params ptr = ptr - 1; address = symbol_table[ptr].offset; symbol_table[ptr].offset = address + INTSIZE; /* Struct etc FIXME */ } } } else { error("illegal argument name"); junk(); } if (match("[")) { while (inbyte() != ']') { if (endst()) { break; } } identity = POINTER; symbol_table[argptr].identity = identity; } }
/* * 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); }
/** * "return" statement */ void doreturn(void) { if (endst () == 0) expression (YES); gen_jump(fexitlab); }
void newfunc_typed(int storage, char *n, int type) { int idx; SYMBOL *symbol; char an[NAMESIZE]; fexitlab = getlabel(); if ((idx = find_global(n)) > -1) { symbol = &symbol_table[idx]; if (symbol->identity != FUNCTION) multidef(n); } else { /* extern implies global scope */ idx = add_global(n, FUNCTION, CINT, 0, storage == EXTERN ? PUBLIC : storage); symbol = &symbol_table[idx]; } local_table_index = NUMBER_OF_GLOBALS; //locptr = STARTLOC; argstk = 0; // ANSI style argument declaration if (doAnsiArguments()) { if (storage == EXTERN) { need_semicolon(); return; } /* No body .. just a definition */ if (match(";")) return; } else { // K&R style argument declaration while (!match(")")) { if (symname(an)) { if (find_locale(an) > -1) multidef(an); else { /* FIXME: struct */ add_local(an, 0, 0, argstk, AUTO); argstk = argstk + INTSIZE; } } else { error("illegal argument name"); junk(); } blanks(); if (!streq(line + lptr, ")")) { if (!match(",")) error("expected comma"); } if (endst()) break; } if (storage == EXTERN) { need_semicolon(); return; } /* No body .. just a definition */ if (match(";")) return; stkp = 0; argtop = argstk; while (argstk) { if ((type = get_type()) != -1) { notvoid(type); getarg(type); need_semicolon(); } else { error("wrong number args"); break; } } } if (symbol->offset == FUNCTION) multidef(n); symbol->offset = FUNCTION; output_string(n); output_label_terminator(); newline(); gen_prologue(); statement(YES); print_label(fexitlab); output_label_terminator(); newline(); gen_epilogue(); gen_modify_stack(0); gen_ret(); stkp = 0; local_table_index = NUMBER_OF_GLOBALS; //locptr = STARTLOC; }
/** * 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; } }
/** * 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; } }
newfunc () { char n[NAMESIZE], *ptr; fexitlab = getlabel(); if (!symname (n) ) { error ("illegal function or declaration"); kill (); return; } if (ptr = findglb (n)) { if (ptr[IDENT] != FUNCTION) multidef (n); else if (ptr[OFFSET] == FUNCTION) multidef (n); else ptr[OFFSET] = FUNCTION; } else addglb (n, FUNCTION, CINT, FUNCTION, PUBLIC); prologue (); if (!match ("(")) error ("missing open paren"); prefix (); outstr (n); col (); nl (); locptr = STARTLOC; argstk = 0; while (!match (")")) { if (symname (n)) { if (findloc (n)) multidef (n); else { addloc (n, 0, 0, argstk, AUTO); argstk = argstk + intsize(); } } else { error ("illegal argument name"); junk (); } blanks (); if (!streq (line + lptr, ")")) { if (!match (",")) error ("expected comma"); } if (endst ()) break; } stkp = 0; argtop = argstk; while (argstk) { if (amatch ("register", 8)) { if (amatch("char", 4)) getarg(CCHAR); else if (amatch ("int", 3)) getarg(CINT); else getarg(CINT); ns(); } else if (amatch ("char", 4)) { getarg (CCHAR); ns (); } else if (amatch ("int", 3)) { getarg (CINT); ns (); } else { error ("wrong number args"); break; } } statement(YES); printlabel(fexitlab); col(); nl(); modstk (0); gret (); stkp = 0; locptr = STARTLOC; }
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); }
void DoFnKR( SYMBOL *currfn, char simple) { char n[NAMESIZE]; SYMBOL *prevarg; /* ptr to symbol table entry of most recent argument */ SYMBOL *cptr; TAG_SYMBOL *otag ; /* structure tag for structure argument */ struct varid var; prevarg=0; Zsp=0; /* Reset stack pointer */ undeclared=0; infunc=1; while ( !simple && cmatch(')') == 0 ) { /* then count args */ /* any legal name bumps arg count */ if ( symname(n) ) { /* add link to argument chain */ if ( (cptr=addloc(n,0,CINT,0,0)) ) cptr->offset.p = prevarg ; prevarg = cptr ; ++undeclared ; } else { error(E_ARGNAME); junk(); } blanks(); /* if not closing paren, should be comma */ if ( ch() != ')' && cmatch(',') == 0 ) { warning(W_EXPCOM); } if ( endst() ) break ; } Zsp = 0 ; /* preset stack ptr */ while ( undeclared ) { char regit=NO; if (amatch("register") ) regit=YES; /* Auto is be default in function defns, but someone might * try it on... */ if (amatch("auto") ) warning(W_AUTO); otag=GetVarID(&var,STATIK); if (var.type==STRUCT) { getarg(STRUCT, otag,NO,0,0, var.zfar,NO) ; } else if (var.type || regit) { if (regit && var.type == NO ) var.type=CINT; getarg(var.type,NULL_TAG,NO,0,var.sign,var.zfar,NO); } else { error(E_BADARG) ; break ; } } /* Have finished K&R parsing */ setlocvar(prevarg,currfn); }
/** * begin a function * called from "parse", this routine tries to make a function out * of what follows * modified version. p.l. woods */ newfunc() { char n[NAMESIZE]; int idx, type; fexitlab = getlabel(); if (!symname(n)) { error("illegal function or declaration"); kill(); return; } if (idx = findglb(n)) { if (symbol_table[idx].identity != FUNCTION) multidef(n); else if (symbol_table[idx].offset == FUNCTION) multidef(n); else symbol_table[idx].offset = FUNCTION; } else add_global(n, FUNCTION, CINT, FUNCTION, PUBLIC); if (!match("(")) error("missing open paren"); output_string(n); output_label_terminator(); newline(); local_table_index = NUMBER_OF_GLOBALS; //locptr = STARTLOC; argstk = 0; // ANSI style argument declaration if (doAnsiArguments() == 0) { // K&R style argument declaration while (!match(")")) { if (symname(n)) { if (findloc(n)) multidef(n); else { add_local(n, 0, 0, argstk, AUTO); argstk = argstk + INTSIZE; } } else { error("illegal argument name"); junk(); } blanks(); if (!streq(line + lptr, ")")) { if (!match(",")) error("expected comma"); } if (endst()) break; } stkp = 0; argtop = argstk; while (argstk) { if (type = get_type()) { getarg(type); need_semicolon(); } else { error("wrong number args"); break; } } } statement(YES); print_label(fexitlab); output_label_terminator(); newline(); gen_modify_stack(0); gen_ret(); stkp = 0; local_table_index = NUMBER_OF_GLOBALS; //locptr = STARTLOC; }