static cell do_caseovl(FILE *fbin,const char *params,cell opcode,cell cip) { ucell v=hex2ucell(params,¶ms); ucell p=hex2ucell(params,NULL); (void)opcode; (void)cip; if (fbin!=NULL) { write_cell(fbin,v); write_cell(fbin,p); } /* if */ return opcodes(0)+opargs(2); }
static cell do_case(FILE *fbin,const char *params,cell opcode,cell cip) { int i; ucell p,v; (void)opcode; v=hex2ucell(params,¶ms); i=(int)hex2ucell(params,NULL); assert(i>=0 && i<sc_labnum); if (fbin!=NULL) { assert(lbltab!=NULL); p=lbltab[i]-cip; write_cell(fbin,v); write_cell(fbin,p); } /* if */ return opcodes(0)+opargs(2); }
SC_FUNC ucell getparamvalue(const char *s,const char **n) { ucell result=0; for ( ;; ) { result+=hex2ucell(s,&s); if (*s!='+') break; s++; } /* for */ if (n!=NULL) *n=(char*)s; return result; }
static cell do_switch(FILE *fbin,const char *params,cell opcode,cell cip) { int i; ucell p; i=(int)hex2ucell(params,NULL); assert(i>=0 && i<sc_labnum); if (fbin!=NULL) { assert(lbltab!=NULL); p=lbltab[i]-cip; write_cell(fbin,opcode); write_cell(fbin,p); } /* if */ return opcodes(1)+opargs(1); }
static cell do_call(FILE *fbin,const char *params,cell opcode,cell cip) { char name[sNAMEMAX+1]; int i; symbol *sym; ucell p; for (i=0; !isspace(*params); i++,params++) { assert(*params!='\0'); assert(i<sNAMEMAX); name[i]=*params; } /* for */ name[i]='\0'; if (name[0]=='l' && name[1]=='.') { /* this is a label, not a function symbol */ i=(int)hex2ucell(name+2,NULL); assert(i>=0 && i<sc_labnum); if (fbin!=NULL) { assert(lbltab!=NULL); p=lbltab[i]-cip; /* make relative address */ } /* if */ } else { /* look up the function address; note that the correct file number must * already have been set (in order for static globals to be found). */ sym=findglb(name,sGLOBAL); assert(sym!=NULL); assert(sym->ident==iFUNCTN || sym->ident==iREFFUNC); assert(sym->vclass==sGLOBAL); p=sym->addr-cip; /* make relative address */ } /* if */ if (fbin!=NULL) { write_cell(fbin,opcode); write_cell(fbin,p); } /* if */ return opcodes(1)+opargs(1); }
SC_FUNC int assemble(FILE *fout,FILE *fin) { AMX_HEADER hdr; AMX_FUNCSTUB func; int numpublics,numnatives,numoverlays,numlibraries,numpubvars,numtags; int padding; long nametablesize,nameofs; char line[512]; char *instr,*params; int i,pass,size; int16_t count; symbol *sym; symbol **nativelist; constvalue *constptr; cell mainaddr; char nullchar; #if !defined NDEBUG /* verify that the opcode list is sorted (skip entry 1; it is reserved * for a non-existant opcode) */ { #define MAX_OPCODE 176 unsigned char opcodearray[MAX_OPCODE+1]; assert(opcodelist[1].name!=NULL); memset(opcodearray,0,sizeof opcodearray); for (i=2; i<(sizeof opcodelist / sizeof opcodelist[0]); i++) { assert(opcodelist[i].name!=NULL); assert(stricmp(opcodelist[i].name,opcodelist[i-1].name)>0); /* also verify that no opcode number appears twice */ assert((int)opcodelist[i].opcode<=MAX_OPCODE); assert(opcodelist[i].opcode==0 || opcodearray[(int)opcodelist[i].opcode]==0); opcodearray[(int)opcodelist[i].opcode] += 1; } /* for */ } #endif writeerror=FALSE; nametablesize=sizeof(int16_t); numpublics=0; numnatives=0; numpubvars=0; numoverlays=0; mainaddr=-1; /* count number of public and native functions and public variables */ for (sym=glbtab.next; sym!=NULL; sym=sym->next) { int match=0; if (sym->ident==iFUNCTN) { if ((sym->usage & uNATIVE)!=0 && (sym->usage & uREAD)!=0 && sym->index>=0) match=++numnatives; if ((sym->usage & uPUBLIC)!=0 && (sym->usage & uDEFINE)!=0) match=++numpublics; if (pc_overlays>0 && (sym->usage & uNATIVE)==0 && (sym->usage & (uREAD | uPUBLIC))!=0 && (sym->usage & uDEFINE)!=0) { if (strcmp(sym->name,uENTRYFUNC)!=0) ++numoverlays; /* there is no stub function for state entry functions */ if (sym->states!=NULL) { /* for functions with states, write an overlay block for every implementation */ statelist *stlist; for (stlist=sym->states->next; stlist!=NULL; stlist=stlist->next) ++numoverlays; } /* if */ } /* if */ if (strcmp(sym->name,uMAINFUNC)==0) { assert(sym->vclass==sGLOBAL); mainaddr=(pc_overlays>0) ? sym->index : sym->addr; } /* if */ } else if (sym->ident==iVARIABLE) { if ((sym->usage & uPUBLIC)!=0 && (sym->usage & (uREAD | uWRITTEN))!=0) match=++numpubvars; } /* if */ if (match) { char alias[sNAMEMAX+1]; assert(sym!=NULL); if ((sym->usage & uNATIVE)==0 || !lookup_alias(alias,sym->name)) { assert(strlen(sym->name)<=sNAMEMAX); strcpy(alias,sym->name); } /* if */ nametablesize+=(int)strlen(alias)+1; } /* if */ } /* for */ assert(numnatives==ntv_funcid); /* count number of libraries */ numlibraries=0; if (pc_addlibtable) { for (constptr=libname_tab.next; constptr!=NULL; constptr=constptr->next) { if (constptr->value>0) { assert(strlen(constptr->name)>0); numlibraries++; nametablesize+=(int)strlen(constptr->name)+1; } /* if */ } /* for */ } /* if */ /* count number of public tags */ numtags=0; for (constptr=tagname_tab.next; constptr!=NULL; constptr=constptr->next) { if ((constptr->value & PUBLICTAG)!=0) { assert(strlen(constptr->name)>0); numtags++; nametablesize+=(int)strlen(constptr->name)+1; } /* if */ } /* for */ /* adjust the number of overlays by the special overlays */ if (pc_overlays>0) for (i=0; i<ovlFIRST; i++) if (pc_ovl0size[i][1]!=0) numoverlays++; /* pad the header to sc_dataalign * => thereby the code segment is aligned * => since the code segment is padded to a sc_dataalign boundary, the data segment is aligned * => and thereby the stack top is aligned too */ assert(sc_dataalign!=0); padding= (int)(sc_dataalign - (sizeof hdr + nametablesize) % sc_dataalign); if (padding==sc_dataalign) padding=0; /* write the abstract machine header */ memset(&hdr, 0, sizeof hdr); if (pc_cellsize==2) hdr.magic=(unsigned short)AMX_MAGIC_16; else if (pc_cellsize==4) hdr.magic=(unsigned short)AMX_MAGIC_32; else if (pc_cellsize==8) hdr.magic=(unsigned short)AMX_MAGIC_64; hdr.file_version=CUR_FILE_VERSION; hdr.amx_version=MIN_AMX_VERSION; hdr.flags=(short)(sc_debug & sSYMBOLIC); if (sc_debug==0) hdr.flags|=AMX_FLAG_NOCHECKS; if (pc_memflags & suSLEEP_INSTR) hdr.flags|=AMX_FLAG_SLEEP; if (pc_overlays>0) hdr.flags|=AMX_FLAG_OVERLAY; if (pc_cryptkey!=0) hdr.flags|=AMX_FLAG_CRYPT; hdr.defsize=sizeof(AMX_FUNCSTUB); hdr.publics=sizeof hdr; /* public table starts right after the header */ hdr.natives=hdr.publics + numpublics*sizeof(AMX_FUNCSTUB); hdr.libraries=hdr.natives + numnatives*sizeof(AMX_FUNCSTUB); hdr.pubvars=hdr.libraries + numlibraries*sizeof(AMX_FUNCSTUB); hdr.tags=hdr.pubvars + numpubvars*sizeof(AMX_FUNCSTUB); hdr.overlays=hdr.tags + numtags*sizeof(AMX_FUNCSTUB); hdr.nametable=hdr.overlays + numoverlays*sizeof(AMX_OVERLAYINFO); hdr.cod=hdr.nametable + nametablesize + padding; hdr.dat=(int32_t)(hdr.cod + code_idx); hdr.hea=(int32_t)(hdr.dat + glb_declared*pc_cellsize); hdr.stp=(int32_t)(hdr.hea + pc_stksize*pc_cellsize); hdr.cip=(int32_t)(mainaddr); hdr.size=hdr.hea; pc_writebin(fout,&hdr,sizeof hdr); /* dump zeros up to the rest of the header, so that we can easily "seek" */ nullchar='\0'; for (nameofs=sizeof hdr; nameofs<hdr.cod; nameofs++) pc_writebin(fout,&nullchar,1); nameofs=hdr.nametable+sizeof(int16_t); /* write the public functions table */ count=0; for (sym=glbtab.next; sym!=NULL; sym=sym->next) { if (sym->ident==iFUNCTN && (sym->usage & uPUBLIC)!=0 && (sym->usage & uDEFINE)!=0) { assert(sym->vclass==sGLOBAL); /* in the case of overlays, write the overlay index rather than the address */ func.address=(uint32_t)((pc_overlays>0) ? sym->index : sym->addr); func.nameofs=nameofs; #if BYTE_ORDER==BIG_ENDIAN align32(&func.address); align32(&func.nameofs); #endif pc_resetbin(fout,hdr.publics+count*sizeof(AMX_FUNCSTUB)); pc_writebin(fout,&func,sizeof func); pc_resetbin(fout,nameofs); pc_writebin(fout,sym->name,(int)strlen(sym->name)+1); nameofs+=(int)strlen(sym->name)+1; count++; } /* if */ } /* for */ /* write the natives table */ /* The native functions must be written in sorted order. (They are * sorted on their "id", not on their name). A nested loop to find * each successive function would be an O(n^2) operation. But we * do not really need to sort, because the native function id's * are sequential and there are no duplicates. So we first walk * through the complete symbol list and store a pointer to every * native function of interest in a temporary table, where its id * serves as the index in the table. Now we can walk the table and * have all native functions in sorted order. */ if (numnatives>0) { nativelist=(symbol **)malloc(numnatives*sizeof(symbol *)); if (nativelist==NULL) error(103); /* insufficient memory */ #if !defined NDEBUG memset(nativelist,0,numnatives*sizeof(symbol *)); /* for NULL checking */ #endif for (sym=glbtab.next; sym!=NULL; sym=sym->next) { if (sym->ident==iFUNCTN && (sym->usage & uNATIVE)!=0 && (sym->usage & uREAD)!=0 && sym->index>=0) { assert(sym->index < numnatives); nativelist[(int)sym->index]=sym; } /* if */ } /* for */ count=0; for (i=0; i<numnatives; i++) { char alias[sNAMEMAX+1]; sym=nativelist[i]; assert(sym!=NULL); if (!lookup_alias(alias,sym->name)) { assert(strlen(sym->name)<=sNAMEMAX); strcpy(alias,sym->name); } /* if */ assert(sym->vclass==sGLOBAL); func.address=0; func.nameofs=nameofs; #if BYTE_ORDER==BIG_ENDIAN align32(&func.address); align32(&func.nameofs); #endif pc_resetbin(fout,hdr.natives+count*sizeof(AMX_FUNCSTUB)); pc_writebin(fout,&func,sizeof func); pc_resetbin(fout,nameofs); pc_writebin(fout,alias,(int)strlen(alias)+1); nameofs+=(int)strlen(alias)+1; count++; } /* for */ free(nativelist); } /* if */ /* write the libraries table */ if (pc_addlibtable) { count=0; for (constptr=libname_tab.next; constptr!=NULL; constptr=constptr->next) { if (constptr->value>0) { assert(strlen(constptr->name)>0); func.address=0; func.nameofs=nameofs; #if BYTE_ORDER==BIG_ENDIAN align32(&func.address); align32(&func.nameofs); #endif pc_resetbin(fout,hdr.libraries+count*sizeof(AMX_FUNCSTUB)); pc_writebin(fout,&func,sizeof func); pc_resetbin(fout,nameofs); pc_writebin(fout,constptr->name,(int)strlen(constptr->name)+1); nameofs+=(int)strlen(constptr->name)+1; count++; } /* if */ } /* for */ } /* if */ /* write the public variables table */ count=0; for (sym=glbtab.next; sym!=NULL; sym=sym->next) { if (sym->ident==iVARIABLE && (sym->usage & uPUBLIC)!=0 && (sym->usage & (uREAD | uWRITTEN))!=0) { assert((sym->usage & uDEFINE)!=0); assert(sym->vclass==sGLOBAL); func.address=(uint32_t)sym->addr; func.nameofs=nameofs; #if BYTE_ORDER==BIG_ENDIAN align32(&func.address); align32(&func.nameofs); #endif pc_resetbin(fout,hdr.pubvars+count*sizeof(AMX_FUNCSTUB)); pc_writebin(fout,&func,sizeof func); pc_resetbin(fout,nameofs); pc_writebin(fout,sym->name,(int)strlen(sym->name)+1); nameofs+=(int)strlen(sym->name)+1; count++; } /* if */ } /* for */ /* write the public tagnames table */ count=0; for (constptr=tagname_tab.next; constptr!=NULL; constptr=constptr->next) { if ((constptr->value & PUBLICTAG)!=0) { assert(strlen(constptr->name)>0); func.address=(uint32_t)(constptr->value & TAGMASK); func.nameofs=nameofs; #if BYTE_ORDER==BIG_ENDIAN align32(&func.address); align32(&func.nameofs); #endif pc_resetbin(fout,hdr.tags+count*sizeof(AMX_FUNCSTUB)); pc_writebin(fout,&func,sizeof func); pc_resetbin(fout,nameofs); pc_writebin(fout,constptr->name,(int)strlen(constptr->name)+1); nameofs+=(int)strlen(constptr->name)+1; count++; } /* if */ } /* for */ /* write the "maximum name length" field in the name table */ assert(nameofs==hdr.nametable+nametablesize); pc_resetbin(fout,hdr.nametable); count=sNAMEMAX; #if BYTE_ORDER==BIG_ENDIAN align16(&count); #endif pc_writebin(fout,&count,sizeof count); /* write the overlay table */ if (pc_overlays>0) { AMX_OVERLAYINFO info; #if !defined NDEBUG int count=0; #endif pc_resetbin(fout,hdr.overlays); /* first the special overlay(s) for the return point(s) */ for (i=0; i<ovlFIRST; i++) { if (pc_ovl0size[i][1]!=0) { info.offset=pc_ovl0size[i][0]; info.size=pc_ovl0size[i][1]; #if BYTE_ORDER==BIG_ENDIAN align32(&info.offset); align32(&info.size); #endif pc_writebin(fout,&info,sizeof info); #if !defined NDEBUG count++; #endif } /* if */ } /* for */ /* now all real overlay functions */ for (sym=glbtab.next; sym!=NULL; sym=sym->next) { if (sym->ident==iFUNCTN && (sym->usage & uNATIVE)==0 && (sym->usage & (uREAD | uPUBLIC))!=0 && (sym->usage & uDEFINE)!=0) { assert(sym->vclass==sGLOBAL); assert(strcmp(sym->name,uENTRYFUNC)==0 || sym->index==count++);/* overlay indices must be in sequential order */ assert(strcmp(sym->name,uENTRYFUNC)==0 || sym->addr<sym->codeaddr); /* write the overlay for the stub function first */ if (strcmp(sym->name,uENTRYFUNC)!=0) { /* there is no stub function for state entry functions */ info.offset=(int32_t)sym->addr; info.size=(uint32_t)(sym->codeaddr - sym->addr); #if BYTE_ORDER==BIG_ENDIAN align32(&info.offset); align32(&info.size); #endif pc_writebin(fout,&info,sizeof info); } /* if */ if (sym->states!=NULL) { /* for functions with states, write an overlay block for every implementation */ statelist *stlist; for (stlist=sym->states->next; stlist!=NULL; stlist=stlist->next) { assert(stlist->label==count++); info.offset=(int32_t)stlist->addr; info.size=(int32_t)(stlist->endaddr - stlist->addr); #if BYTE_ORDER==BIG_ENDIAN align32(&info.offset); align32(&info.size); #endif pc_writebin(fout,&info,sizeof info); } /* for */ } /* if */ } /* if */ } /* for */ } /* if */ pc_resetbin(fout,hdr.cod); /* First pass: relocate all labels */ /* This pass is necessary because the code addresses of labels is only known * after the peephole optimization flag. Labels can occur inside expressions * (e.g. the conditional operator), which are optimized. */ lbltab=NULL; if (sc_labnum>0) { cell codeindex=0; /* address of the current opcode similar to "code_idx" */ /* only very short programs have zero labels; no first pass is needed * if there are no labels */ lbltab=(cell *)malloc(sc_labnum*sizeof(cell)); if (lbltab==NULL) error(103); /* insufficient memory */ memset(lbltab,0,sc_labnum*sizeof(cell)); pc_resetasm(fin); while (pc_readasm(fin,line,sizeof line)!=NULL) { stripcomment(line); instr=skipwhitespace(line); /* ignore empty lines */ if (*instr=='\0') continue; if (tolower(*instr)=='l' && *(instr+1)=='.') { int lindex=(int)hex2ucell(instr+2,NULL); assert(lindex>=0 && lindex<sc_labnum); assert(lbltab[lindex]==0); /* should not already be declared */ lbltab[lindex]=codeindex; } else { /* get to the end of the instruction (make use of the '\n' that fgets() * added at the end of the line; this way we will *always* drop on a * whitespace character) */ for (params=instr; *params!='\0' && !isspace(*params); params++) /* nothing */; assert(params>instr); i=findopcode(instr,(int)(params-instr)); assert(opcodelist[i].name!=NULL); assert(opcodelist[i].opt_level<=pc_optimize || pc_optimize==0 && opcodelist[i].opt_level<=1); if (opcodelist[i].segment==sIN_CSEG) codeindex+=opcodelist[i].func(NULL,skipwhitespace(params),opcodelist[i].opcode,codeindex); } /* if */ } /* while */ } /* if */ /* Second pass (actually 2 more passes, one for all code and one for all data) */ for (pass=sIN_CSEG; pass<=sIN_DSEG; pass++) { cell codeindex=0; /* address of the current opcode similar to "code_idx" */ pc_resetasm(fin); while (pc_readasm(fin,line,sizeof line)!=NULL) { stripcomment(line); instr=skipwhitespace(line); /* ignore empty lines and labels (labels have a special syntax, so these * must be parsed separately) */ if (*instr=='\0' || tolower(*instr)=='l' && *(instr+1)=='.') continue; /* get to the end of the instruction (make use of the '\n' that fgets() * added at the end of the line; this way we will *always* drop on a * whitespace character) */ for (params=instr; *params!='\0' && !isspace(*params); params++) /* nothing */; assert(params>instr); i=findopcode(instr,(int)(params-instr)); assert(opcodelist[i].name!=NULL); assert(opcodelist[i].opt_level<=pc_optimize || pc_optimize==0 && opcodelist[i].opt_level<=1); if (opcodelist[i].segment==pass) codeindex+=opcodelist[i].func(fout,skipwhitespace(params),opcodelist[i].opcode,codeindex); } /* while */ } /* for */ if (lbltab!=NULL) { free(lbltab); #if !defined NDEBUG lbltab=NULL; #endif } /* if */ assert(hdr.size==pc_lengthbin(fout)); if (!writeerror && (sc_debug & sSYMBOLIC)!=0) append_dbginfo(fout); /* optionally append debug file */ if (writeerror) error(101,"disk full"); /* adjust the header (for Big Endian architectures) */ size=(int)hdr.cod; /* save, the value in the header may need to be swapped */ #if BYTE_ORDER==BIG_ENDIAN align32(&hdr.size); align16(&hdr.magic); align16(&hdr.flags); align16(&hdr.defsize); align32(&hdr.publics); align32(&hdr.natives); align32(&hdr.libraries); align32(&hdr.pubvars); align32(&hdr.tags); align32(&hdr.nametable); align32(&hdr.cod); align32(&hdr.dat); align32(&hdr.hea); align32(&hdr.stp); align32(&hdr.cip); pc_resetbin(fout,0); pc_writebin(fout,&hdr,sizeof hdr); #endif /* return the size of the header (including name tables, but excluding code * or data sections) */ return size; }
static void append_dbginfo(FILE *fout) { AMX_DBG_HDR dbghdr; AMX_DBG_LINE dbgline; AMX_DBG_SYMBOL dbgsym; AMX_DBG_SYMDIM dbgidxtag[sDIMEN_MAX]; int index,dim,dbgsymdim; const char *str,*prevstr,*name,*prevname; ucell codeidx,previdx; constvalue *constptr; char symname[2*sNAMEMAX+16]; int16_t id1,id2; ucell address; /* header with general information */ memset(&dbghdr, 0, sizeof dbghdr); dbghdr.size=sizeof dbghdr; dbghdr.magic=AMX_DBG_MAGIC; dbghdr.file_version=CUR_FILE_VERSION; dbghdr.amx_version=MIN_AMX_VERSION; /* first pass: collect the number of items in various tables */ /* file table */ previdx=0; prevstr=NULL; prevname=NULL; for (index=0; (str=get_dbgstring(index))!=NULL; index++) { assert(str!=NULL); assert(str[0]!='\0' && str[1]==':'); if (str[0]=='F') { codeidx=hex2ucell(str+2,&name); if (codeidx!=previdx) { if (prevstr!=NULL) { assert(prevname!=NULL); dbghdr.files++; dbghdr.size+=(int32_t)(sizeof(AMX_DBG_FILE)+strlen(prevname)); } /* if */ previdx=codeidx; } /* if */ prevstr=str; prevname=skipwhitespace(name); } /* if */ } /* for */ if (prevstr!=NULL) { assert(prevname!=NULL); dbghdr.files++; dbghdr.size+=(int32_t)(sizeof(AMX_DBG_FILE)+strlen(prevname)); } /* if */ /* line number table */ for (index=0; (str=get_dbgstring(index))!=NULL; index++) { assert(str!=NULL); assert(str[0]!='\0' && str[1]==':'); if (str[0]=='L') { dbghdr.lines++; dbghdr.size+=sizeof(AMX_DBG_LINE); } /* if */ } /* for */ /* symbol table */ for (index=0; (str=get_dbgstring(index))!=NULL; index++) { assert(str!=NULL); assert(str[0]!='\0' && str[1]==':'); if (str[0]=='S') { dbghdr.symbols++; str=strchr(str+2,':'); assert(str!=NULL); name=skipwhitespace(str+1); str=strchr(name,' '); assert(str!=NULL); assert((int)(str-name)<sizeof symname); strlcpy(symname,name,(int)(str-name)+1); dbghdr.size+=(int32_t)(sizeof(AMX_DBG_SYMBOL)+strlen(symname)); if ((prevstr=strchr(name,'['))!=NULL) while ((prevstr=strchr(prevstr+1,':'))!=NULL) dbghdr.size+=sizeof(AMX_DBG_SYMDIM); } /* if */ } /* for */ /* tag table */ for (constptr=tagname_tab.next; constptr!=NULL; constptr=constptr->next) { assert(strlen(constptr->name)>0); dbghdr.tags++; dbghdr.size+=(int32_t)(sizeof(AMX_DBG_TAG)+strlen(constptr->name)); } /* for */ /* automaton table */ for (constptr=sc_automaton_tab.next; constptr!=NULL; constptr=constptr->next) { assert(constptr->index==0 && strlen(constptr->name)==0 || strlen(constptr->name)>0); dbghdr.automatons++; dbghdr.size+=(int32_t)(sizeof(AMX_DBG_MACHINE)+strlen(constptr->name)); } /* for */ /* state table */ for (constptr=sc_state_tab.next; constptr!=NULL; constptr=constptr->next) { assert(strlen(constptr->name)>0); dbghdr.states++; dbghdr.size+=(int32_t)(sizeof(AMX_DBG_STATE)+strlen(constptr->name)); } /* for */ /* pass 2: generate the tables */ #if BYTE_ORDER==BIG_ENDIAN align32((uint32_t*)&dbghdr.size); align16(&dbghdr.magic); align16(&dbghdr.flags); align16(&dbghdr.files); align16(&dbghdr.lines); align16(&dbghdr.symbols); align16(&dbghdr.tags); align16(&dbghdr.automatons); align16(&dbghdr.states); #endif writeerror |= !pc_writebin(fout,&dbghdr,sizeof dbghdr); /* file table */ previdx=0; prevstr=NULL; prevname=NULL; for (index=0; (str=get_dbgstring(index))!=NULL; index++) { assert(str!=NULL); assert(str[0]!='\0' && str[1]==':'); if (str[0]=='F') { codeidx=hex2ucell(str+2,&name); if (codeidx!=previdx) { if (prevstr!=NULL) { assert(prevname!=NULL); #if BYTE_ORDER==BIG_ENDIAN align32(&previdx); #endif writeerror |= !pc_writebin(fout,&previdx,sizeof(uint32_t)); writeerror |= !pc_writebin(fout,prevname,(int)strlen(prevname)+1); } /* if */ previdx=codeidx; } /* if */ prevstr=str; prevname=skipwhitespace(name); } /* if */ } /* for */ if (prevstr!=NULL) { assert(prevname!=NULL); #if BYTE_ORDER==BIG_ENDIAN align32(&previdx); #endif writeerror |= !pc_writebin(fout,&previdx,sizeof(uint32_t)); writeerror |= !pc_writebin(fout,prevname,(int)strlen(prevname)+1); } /* if */ /* line number table */ for (index=0; (str=get_dbgstring(index))!=NULL; index++) { assert(str!=NULL); assert(str[0]!='\0' && str[1]==':'); if (str[0]=='L') { dbgline.address=(uint32_t)hex2ucell(str+2,&str); dbgline.line=(int32_t)hex2ucell(str,NULL); #if BYTE_ORDER==BIG_ENDIAN align32(&dbgline.address); align32(&dbgline.line); #endif writeerror |= !pc_writebin(fout,&dbgline,sizeof dbgline); } /* if */ } /* for */ /* symbol table */ for (index=0; (str=get_dbgstring(index))!=NULL; index++) { assert(str!=NULL); assert(str[0]!='\0' && str[1]==':'); if (str[0]=='S') { dbgsym.address=(uint32_t)hex2ucell(str+2,&str); dbgsym.tag=(int16_t)hex2ucell(str,&str); str=skipwhitespace(str); assert(*str==':'); name=skipwhitespace(str+1); str=strchr(name,' '); assert(str!=NULL); assert((int)(str-name)<sizeof symname); strlcpy(symname,name,(int)(str-name)+1); dbgsym.codestart=(uint32_t)hex2ucell(str,&str); dbgsym.codeend=(uint32_t)hex2ucell(str,&str); dbgsym.ident=(char)hex2ucell(str,&str); dbgsym.vclass=(char)hex2ucell(str,&str); dbgsym.dim=0; str=skipwhitespace(str); if (*str=='[') { while (*(str=skipwhitespace(str+1))!=']') { dbgidxtag[dbgsym.dim].size=(uint32_t)hex2ucell(str,&str); dbgsym.dim++; } /* while */ } /* if */ dbgsymdim = dbgsym.dim; #if BYTE_ORDER==BIG_ENDIAN align32(&dbgsym.address); align16(&dbgsym.tag); align32(&dbgsym.codestart); align32(&dbgsym.codeend); align16(&dbgsym.dim); #endif writeerror |= !pc_writebin(fout,&dbgsym.address,sizeof dbgsym.codeend); writeerror |= !pc_writebin(fout,&dbgsym.tag,sizeof dbgsym.tag); writeerror |= !pc_writebin(fout,&dbgsym.codestart,sizeof dbgsym.codeend); writeerror |= !pc_writebin(fout,&dbgsym.codeend,sizeof dbgsym.codeend); writeerror |= !pc_writebin(fout,&dbgsym.ident,sizeof dbgsym.ident); writeerror |= !pc_writebin(fout,&dbgsym.vclass,sizeof dbgsym.vclass); writeerror |= !pc_writebin(fout,&dbgsym.dim,sizeof dbgsym.dim); writeerror |= !pc_writebin(fout,symname,(int)strlen(symname)+1); for (dim=0; dim<dbgsymdim; dim++) { #if BYTE_ORDER==BIG_ENDIAN align16(&dbgidxtag[dim].tag); align32(&dbgidxtag[dim].size); #endif writeerror |= !pc_writebin(fout,&dbgidxtag[dim].tag,sizeof dbgidxtag[dim].tag); writeerror |= !pc_writebin(fout,&dbgidxtag[dim].size,sizeof dbgidxtag[dim].size); } /* for */ } /* if */ } /* for */ /* tag table */ for (constptr=tagname_tab.next; constptr!=NULL; constptr=constptr->next) { assert(strlen(constptr->name)>0); id1=(int16_t)(constptr->value & TAGMASK); #if BYTE_ORDER==BIG_ENDIAN align16(&id1); #endif writeerror |= !pc_writebin(fout,&id1,sizeof id1); writeerror |= !pc_writebin(fout,constptr->name,(int)strlen(constptr->name)+1); } /* for */ /* automaton table */ for (constptr=sc_automaton_tab.next; constptr!=NULL; constptr=constptr->next) { assert(constptr->index==0 && strlen(constptr->name)==0 || strlen(constptr->name)>0); id1=(int16_t)constptr->index; address=(ucell)constptr->value; #if BYTE_ORDER==BIG_ENDIAN align16(&id1); align32(&address); #endif writeerror |= !pc_writebin(fout,&id1,sizeof id1); writeerror |= !pc_writebin(fout,&address,sizeof(uint32_t)); writeerror |= !pc_writebin(fout,constptr->name,(int)strlen(constptr->name)+1); } /* for */ /* state table */ for (constptr=sc_state_tab.next; constptr!=NULL; constptr=constptr->next) { assert(strlen(constptr->name)>0); id1=(int16_t)constptr->value; id2=(int16_t)constptr->index; address=(ucell)constptr->value; #if BYTE_ORDER==BIG_ENDIAN align16(&id1); align16(&id2); #endif writeerror |= !pc_writebin(fout,&id1,sizeof id1); writeerror |= !pc_writebin(fout,&id2,sizeof id2); writeerror |= !pc_writebin(fout,constptr->name,(int)strlen(constptr->name)+1); } /* for */ delete_dbgstringtable(); }
static char *replacesequence(const char *pattern,char symbols[MAX_OPT_VARS+1][MAX_ALIAS+1],int *repl_length) { char *lptr; int var,optsym; char *buffer; /* calculate the length of the new buffer * this is the length of the pattern plus the length of all symbols (note * that the same symbol may occur multiple times in the pattern) plus * line endings and startings ('\t' to start a line and '\n\0' to end one) */ assert(repl_length!=NULL); *repl_length=0; optsym=FALSE; lptr=(char*)pattern; while (*lptr) { switch (*lptr) { case '%': lptr++; /* skip '%' */ assert(isdigit(*lptr)); var=atoi(lptr); assert(var>=0 && var<=MAX_OPT_VARS); assert(symbols[var][0]!='\0' || optsym); /* variable should be defined */ assert(var!=0 || strlen(symbols[var])==pc_cellsize || (symbols[var][0]=='-' && strlen(symbols[var])==pc_cellsize+1) || atoi(symbols[var])==0); *repl_length+=(int)strlen(symbols[var]); optsym=FALSE; break; case '~': /* optional space followed by optional symbol */ assert(lptr[1]=='%'); assert(isdigit(lptr[2])); var=atoi(lptr+2); assert(var>=0 && var<=MAX_OPT_VARS); if (symbols[var][0]!='\0') *repl_length+=1; /* copy space if following symbol is valid */ else optsym=TRUE; /* don't copy space, and symbol is optional */ break; case '#': lptr++; /* skip '#' */ assert(alphanum(*lptr)); while (alphanum(lptr[1])) lptr++; *repl_length+=pc_cellsize*2; break; case '!': *repl_length+=3; /* '\t', '\n' & '\0' */ break; default: *repl_length+=1; } /* switch */ lptr++; } /* while */ /* allocate a buffer to replace the sequence in */ if ((buffer=(char*)malloc(*repl_length))==NULL) { error(103); return NULL; } /* if */ /* replace the pattern into this temporary buffer */ optsym=FALSE; lptr=buffer; *lptr++='\t'; /* the "replace" patterns do not have tabs */ while (*pattern) { assert((int)(lptr-buffer)<*repl_length); switch (*pattern) { case '%': /* write out the symbol */ pattern++; assert(isdigit(*pattern)); var=atoi(pattern); assert(var>=0 && var<=MAX_OPT_VARS); assert(symbols[var][0]!='\0' || optsym); /* variable should be defined */ assert(symbols[var][0]=='\0' || !optsym); /* but optional variable should be undefined */ strcpy(lptr,symbols[var]); lptr+=strlen(symbols[var]); optsym=FALSE; break; case '~': assert(pattern[1]=='%'); assert(isdigit(pattern[2])); var=atoi(pattern+2); assert(var>=0 && var<=MAX_OPT_VARS); if (symbols[var][0]!='\0') *lptr++=' '; /* replace ~ by a space */ else optsym=TRUE; /* don't copy space, and symbol is optional */ break; case '#': { ucell v=hex2ucell(pattern+1,NULL); char *ptr=itoh(v); strcpy(lptr,ptr); lptr+=strlen(ptr); assert(alphanum(pattern[1])); while (alphanum(pattern[1])) pattern++; break; } /* case */ case '!': /* finish the line, optionally start the next line with an indent */ *lptr++='\n'; *lptr++='\0'; if (*(pattern+1)!='\0') *lptr++='\t'; break; default: *lptr++=*pattern; } /* switch */ pattern++; } /* while */ assert((int)(lptr-buffer)==*repl_length); return buffer; }