int constant(LVALUE *lval) { constype=CINT; conssign=dosigned; lval->is_const = 1 ; /* assume constant will be found */ if ( fnumber(&lval->const_val) ) { lval->val_type=DOUBLE; if ( doublestrings ) { immedlit(litlab); outdec(lval->const_val); nl(); callrts("__atof2"); WriteDefined("math_atof",1); } else { immedlit(dublab); outdec(lval->const_val); nl(); callrts("dload"); } lval->is_const = 0 ; /* floating point not constant */ lval->flags=0; return(1); } else if ( number(&lval->const_val) || pstr(&lval->const_val) ) { /* Insert long stuff/long pointer here? */ if ( (unsigned long )lval->const_val >= 65536LU ) constype = LONG; lval->val_type = constype ; lval->flags = (lval->flags&MKSIGN)|conssign; if (constype == LONG) vlongconst(lval->const_val); else vconst(lval->const_val); return(1); } else if ( tstr(&lval->const_val) ) { lval->is_const = 0 ; /* string address not constant */ lval->ptr_type=CCHAR; /* djm 9/3/99 */ lval->val_type=CINT; lval->flags=0; immedlit(litlab); } else { lval->is_const = 0 ; return(0); } outdec(lval->const_val); nl(); return(1); }
/* * 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); }
/* * Compiler begins execution here */ int main(int argc, char** argv) { gargc = argc; gargv = argv; /* allocate space for arrays */ litq = MALLOC(FNLITQ); /* literals, these 2 dumped end */ dubq = MALLOC(FNLITQ); /* Doubles */ tempq = MALLOC(LITABSZ); /* Temp strings... */ glbq = MALLOC(LITABSZ); /* Used for glb lits, dumped now */ symtab = NULL; loctab = MALLOC(NUMLOC * sizeof(SYMBOL)); wqueue = MALLOC(NUMWHILE * sizeof(WHILE_TAB)); gotoq = MALLOC(NUMGOTO * sizeof(GOTO_TAB)); swnext = MALLOC(NUMCASE * sizeof(SW_TAB)); swend = swnext + (NUMCASE - 1); stage = MALLOC(STAGESIZE); stagelast = stage + STAGELIMIT; glbcnt = 0; /* clear global symbols */ locptr = STARTLOC; /* clear local symbols */ wqptr = wqueue; /* clear while queue */ gltptr = 0; /* clear literal pools */ *litq = 0; /* First entry in literal queue is zero */ litptr = 1; /* So miniprintf search works */ Zsp = /* stack ptr (relative) */ errcnt = /* no errors */ c_errstop = /* keep going after an error */ eof = /* not eof yet */ ncmp = /* no open compound states */ lastst = /* not first file to asm */ lineno = /* no lines read from file */ infunc = /* not in function now */ 0; /* ...all set to zero.... */ stagenext = NULL; /* direct output mode */ input = /* no input file */ inpt2 = /* or include file */ saveout = /* no diverted output */ output = NULL; /* no open units */ currfn = NULL; /* no function yet */ macptr = cmode = 1; /* clear macro pool and enable preprocessing */ ncomp = need_floatpack = 0; c_default_unsigned = NO; nxtlab = 0;/* start numbers at lowest possible */ c_intermix_ccode = 0; /* don't include the C text as comments */ c_errstop =0; /* don't stop after errors */ c_verbose = 0; c_double_strings = 0; c_notaltreg = NO; debuglevel = NO; c_assembler_type = ASM_Z80ASM; c_framepointer_is_ix = -1; c_use_r2l_calling_convention = NO; setup_sym(); /* define some symbols */ /* Parse the command line options */ atexit(atexit_deallocate); /* To free everything */ clear(); filenum = 0; gargc = parse_arguments(sccz80_opts, argc, argv); clear(); if (gargc == 0) { info(); exit(1); } if ( c_maths_mode == MATHS_IEEE ) { c_fp_size = 4; type_double = &(Type){ KIND_DOUBLE, 4, 0, .len=1 }; c_fp_exponent_bias = 126; c_fp_mantissa_bytes = 3; WriteDefined("CLIB_32BIT_FLOATS", 1); } else if ( c_maths_mode == MATHS_MBFS ) {
void #endif dumpfns() { int ident,type,storage; SYMBOL *ptr; FILE *fp; #ifdef HEADERFILE outstr(";\tHeader file for file:\t"); outstr(Filename); outstr("\n;\n;\tEven if empty do not delete!!!\n"); outstr(";\n;\t***START OF HEADER DEFNS***\n\n"); #else outstr("\n\n; --- Start of Scope Defns ---\n\n"); #endif if (!glbcnt) return; /* Start at the start! */ glbptr=STARTGLB; ptr=STARTGLB; while (ptr < ENDGLB) { if (ptr->name[0] != 0 && ptr->name[0] != '0' ) { ident=ptr->ident; if (ident==FUNCTIONP) ident=FUNCTION; type =ptr->type; storage=ptr->storage; if ( ident == FUNCTION && ptr->size != 0 ) { outstr("\tdefc\t"); outname(ptr->name,1); ot("=\t"); outdec(ptr->size); nl(); } else { if (ident == FUNCTION && storage!=LSTATIC ) { if (storage==EXTERNAL) { if (ptr->flags&LIBRARY) { GlobalPrefix(LIB); if ( (ptr->flags&SHARED) && useshare ){ outstr(ptr->name); outstr("_sl\n"); GlobalPrefix(LIB); } } else { GlobalPrefix(XREF); } } else { if (ptr->offset.i == FUNCTION || ptr->storage==DECLEXTN ) GlobalPrefix(XDEF); else GlobalPrefix(XREF); } outname(ptr->name,dopref(ptr)); nl(); } else { if (storage == EXTERNP) { GlobalPrefix(XDEF); outname(ptr->name,1); nl(); outstr("\tdefc\t"); outname(ptr->name,1); ot("=\t"); outdec(ptr->size); nl(); } else if (ident != ENUM && type !=ENUM && ident != MACRO && storage != LSTATIC && storage != LSTKEXT && storage!=TYPDEF ) { if (storage == EXTERNAL) GlobalPrefix(XREF); else GlobalPrefix(XDEF); outname(ptr->name,1); nl(); } } } } ++ptr; } /* * If a module requires floating point then previously we wrote * it out to the header file. However, if the module didn't * contain main() then important routines wouldn't be included. * So, if main didn't need float, but ours did we couldn't * compile correctly. * * The solution was to separate startup code, and then define * a new file to which all the math type headers would be * appended. * * This file is zcc_opt.def in the source code directory. * */ if ( (fp=fopen("zcc_opt.def","a")) == NULL ) { error(E_ZCCOPT); } /* Now output the org */ if (zorg) { fprintf(fp,"\nIF !DEFINED_myzorg\n"); fprintf(fp,"\tDEFINE DEFINED_myzorg\n"); fprintf(fp,"\tdefc myzorg = %u\n",zorg); fprintf(fp,"ENDIF"); } if (appz88) { int k,value=0; fprintf(fp,"\nIF !NEED_appstartup\n"); fprintf(fp,"\tDEFINE\tNEED_appstartup\n"); if (safedata != -1 ) fprintf(fp,"\tdefc safedata = %d\n",safedata); if (intuition) fprintf(fp,"\tdefc intuition = 1\n"); if (farheapsz != -1) { fprintf(fp,"\tDEFINE DEFINED_farheapsz\n"); fprintf(fp,"\tdefc farheapsz = %d\n",farheapsz); } if (reqpag != -1 ) { fprintf(fp,"\tdefc reqpag = %d\n",reqpag); value=reqpag; } else { /* * Consider the malloc pool as well, if defined we need 32 (standard) + * size of malloc - this is a little kludgy, hence the tuning command * line option */ if ( (k=findmac("HEAPSIZE"))) { sscanf(&macq[k],"%d",&value); if (value != 0 ) value/=256; } value+=32; fprintf(fp,"\tdefc reqpag = %d\n",value); } if (value > 32) expanded=YES; fprintf(fp,"\tdefc NEED_expanded = %d\n",expanded); fprintf(fp,"ENDIF\n\n"); } if (incfloat) { fprintf(fp,"\nIF !NEED_floatpack\n"); fprintf(fp,"\tDEFINE\tNEED_floatpack\n"); fprintf(fp,"ENDIF\n\n"); } if (mathz88) { fprintf(fp,"\nIF !NEED_mathz88\n"); fprintf(fp,"\tDEFINE\tNEED_mathz88\n"); fprintf(fp,"ENDIF\n\n"); } if (lpointer) { fprintf(fp,"\nIF !NEED_farpointer\n"); fprintf(fp,"\tDEFINE NEED_farpointer\n"); fprintf(fp,"ENDIF\n\n"); } if (startup) { fprintf(fp,"\nIF !DEFINED_startup\n"); fprintf(fp,"\tDEFINE DEFINED_startup\n"); fprintf(fp,"\tdefc startup=%d\n",startup); fprintf(fp,"ENDIF\n\n"); } /* * Now, we're gonna use #pragma define _FAR_PTR to indicate whether we need * far stuff - this has to go with a -D_FAR_PTR from the compile line * as well for everything to work just right, so if we find this then * we can indicate to the startup code via zcc_opt.def what the scam * is - this could be used for eg. to allocate space for file structures * etc */ if ( (ptr=findglb("_FAR_PTR")) && ptr->ident==MACRO ) { fprintf(fp,"\nIF !NEED_farstartup\n"); fprintf(fp,"\tDEFINE NEED_farstartup\n"); fprintf(fp,"ENDIF\n\n"); } fclose(fp); if ( defvars != 0 ) WriteDefined("defvarsaddr",defvars); switch(printflevel) { case 1: WriteDefined("ministdio",0); break; case 2: WriteDefined("complexstdio",0); break; case 3: WriteDefined("floatstdio",0); break; } /* * DO_inline is obsolete, but it may have a use sometime.. */ if (doinline) outstr("\tDEFINE\tDO_inline\n"); outstr("\n\n; --- End of Scope Defns ---\n\n"); }