extern BoolU4 GetExpression(LexStruct *l,U1 **exp); extern I8 Lex(LexStruct *l); extern U8 PrsUnaryTerm(LexStruct *l,ParseStack *ps); extern U8 PrsUnaryModifier(LexStruct *l,ParseStack *ps); extern U8 PrsDereferrence(LexStruct *l,ParseStack *ps); extern ClassStruct *CmpParseClass(LexStruct *l,BoolU4 is_union,BoolU4 is_public); extern void PrsExcept(LexStruct *l,I1 *name=NULL,I1 *msg=NULL); extern void CmpParseVarList(LexStruct *l,ClassStruct *tempc, I8 mode,U8 union_base=MAX_I4); extern BoolU4 CmpParseStatement(LexStruct *l,ClassStruct *locals,I8 try_count=0, CbMiscStruct *break_label=NULL,CbMiscStruct *continue_label=NULL, BoolU4 saved_prs_semicolon=TRUE); extern I8 ExecuteCmdLine(LexStruct *l); extern I8 ExecuteString(I1 *buf,I1 *filename=NULL); extern I8 ExecuteFile(I1 *name); extern void ContinueUserTask(); extern IntermediateCode *CmpOptPass1(LexStruct *l,ClassStruct *fun_class,BoolU4 combined); extern void CmpOptPass2(LexStruct *l,ClassStruct *fun_class); extern void CmpOptPass3(LexStruct *l,ClassStruct *fun_class); extern void CmpOptPass4(LexStruct *l,ClassStruct *fun_class); LTextern CODE_TABLE U4 code_table[1]; LTextern UNSIGNED_CODE_TABLE U4 unsigned_code_table[1]; LTextern DOUBLE_CODE_TABLE U4 double_code_table[1]; LTextern INTERNAL_TYPES_TABLE U1 internal_types_table[1]; SysHashTable *asm_hash; BoolU4 is_first_compiler; SysHashEntry *sys_internal_types[IT_NUM_IT]; U1 it_to_ec_offset[IT_NUM_IT]={0,0,3,3,2,2,1,1,0,0,0,0}; #define FUT_NULL 0 #define FUT_8_1 1 #define FUT_8_2 2 #define FUT_8_4 3 #define FUT_8_5 4 #define FUT_8_6 5 #define FUT_8_10 6 #define FUT_8_JMP_1 7 #define FUT_32_4 8 #define FUT_32_4_CALL 9 #define FUT_32_4_ABS 10 #define FUT_32_4_ABS2 11 #define FUT_32_5 12 #define FUT_32_6 13 #define FUT_32_7 14 #define FUT_32_9 15 #define FUT_32_4_ENTER 16 #define FUT_32_4P11_4 17 #define FUT_32_JMP_4 18 #define FUT_64_H9_L4 19 #define FUT_ENTER1 20 #define FUT_ENTER2 21 #define FUT_32_4P10_4 22 U1 *signed_fix_up_table,*unsigned_fix_up_table,*double_fix_up_table; U2 *duel_I1_tokens1,*duel_I1_tokens2,*duel_I1_tokens3; U4 *binary_ops_table,*unary_ops_table; U1 *deref_bitmap,*assign_bitmap, *push_bitmap; U2 *push_map; LexStruct *LexNew(I1 *buf,U8 flags,I1 *filename) { LexStruct *l=MAlloc(sizeof(LexStruct)); LexFileStruct *tempf=&l->lfns[0]; MemSet(l,0,offset(LexStruct.lfns)+sizeof(LexFileStruct)); l->next=l; l->last=l; l->flags=flags; l->ESI_offset=MAX_I8; l->EDI_offset=MAX_I8; l->hash_mask=HTT_ALL; l->hash_table_list=Fs->hash_table; l->define_hash_table=Fs->hash_table; l->cur_lfn=tempf; l->next_exe_blk=&l->next_exe_blk; l->last_exe_blk=&l->next_exe_blk; if (!filename) tempf->name=NewString(sys_temp_filename); else tempf->name=filename; if (flags & LF_PROMPT) buf=MAllocZ(4); tempf->buf=buf; tempf->buf_ptr=buf; tempf->line_start=buf; tempf->line_num=1; l->cur_buf_ptr=buf; return l; } void LexDel(LexStruct *l) { LexFileStruct *tempf=l->cur_lfn; void my_LtfDel(Ltf *l,BoolU4 adam_mem); Ltf *ltf; while (tempf!=&l->lfns[0]) { if (ltf=tempf->l) { if (ext[EXT_LTF_DEL]) { my_LtfDel=ext[EXT_LTF_DEL]; my_LtfDel(ltf,FALSE); } } Free(tempf->buf); Free(tempf->name); tempf-=sizeof(LexFileStruct); } Free(tempf->name); if (!(l->flags & LF_DONT_FREE_BUFFER)) Free(tempf->buf); Free(l->ident); Free(l); } void SetSourceFileInfo(LexStruct *l,SysHashEntry *h) { LexFileStruct *tempf=l->cur_lfn; h->source_link=MSPrintF("FL:%s,%d",tempf->name,tempf->line_num); if (Bt(&l->flags,LFf_KEEP_PRIVATE)) h->type|=HTT_PRIVATE; } void LexPutToken(LexStruct *l) { PutChar('"'); if (l->token==TK_IDENT || l->token==TK_STRING) PutS(l->ident); else if (l->token==TK_INTEGER) cout "INT:",l->cur_i; else if (l->token==TK_DOUBLE) cout "DBL:",l->cur_d; else if (l->token>=CH_SHIFT_SPACE && l->token<=0x7E) PutChar(l->token); else { cout "T:",l->token; } PutS("\" "); } U4 lex_zeros=0,lex_line_feed=0x000A; void LexBackupLastChar(LexStruct *l) { LexFileStruct *tempf=l->cur_lfn; tempf->buf_ptr=l->cur_buf_ptr; if (l->flags & LF_USE_LAST_I1) { tempf->last_I1=l->last_I1; l->flags&=~LF_USE_LAST_I1; } else tempf->last_I1=0; } U8 LexGetChar(LexStruct *l) { U1 *src; LexFileStruct *tempf,*tempf1; BoolU4 cont; U8 result; U1 *my_SysPrompt(BoolU4 double_semicolon); Ltf *ltf; LtfEntry *cl; U1 *ptr; void my_LtfDel(Ltf *l,BoolU4 adam_mem); if (l->flags & LF_USE_LAST_I1) { l->flags&=~LF_USE_LAST_I1; return l->last_I1; } do { lex_getchar_start: src=l->cur_buf_ptr++; switch (l->last_I1=result=*src++) { case 0: tempf=l->cur_lfn; if (tempf->flags & LFSF_IS_LTF) { ltf=tempf->l; cl=tempf->cur_entry; cl=cl->next; while (cl!=ltf) { cont=FALSE; tempf->cur_entry=cl; switch (cl->btype) { case LTFT_TEXT: if (*(src=cl->display)) tempf->buf=tempf->buf_ptr=l->cur_buf_ptr=src; else { cont=TRUE; cl=cl->next; } break; case LTFT_CR: src=&lex_line_feed; tempf->buf=tempf->buf_ptr=l->cur_buf_ptr=src; tempf->line_start=cl->next; tempf->line_num=cl->y+2; //+1 because CR is on previous line, +1 because ltf y starts at zero compiled_lines++; if (l->flags & LF_ECHO) CrLf; l->last_I1=CH_CR; return CH_CR; case LTFT_TAB: src=&lex_zeros; tempf->buf=tempf->buf_ptr=l->cur_buf_ptr=src; tempf->line_num=cl->y+1; if (l->flags & LF_ECHO) PutChar(CH_TAB); l->last_I1=CH_TAB; return CH_TAB; case LTFT_PAGE_BREAK: src=&lex_zeros; tempf->buf=tempf->buf_ptr=l->cur_buf_ptr=src; tempf->line_num=cl->y+2; //TODO: should be a page down if (l->flags & LF_ECHO) PutChar(CH_FORM_FEED); l->last_I1=CH_FORM_FEED; return CH_FORM_FEED; case LTFT_INSERT_BINARY: src=&lex_zeros; tempf->buf=tempf->buf_ptr=l->cur_buf_ptr=src; tempf->line_num=cl->y+1; Free(l->ident); l->ident=NULL; l->ident_len=0; if (cl->bin_data) { ptr=MAlloc(cl->bin_data->size); if (cl->bin_data->data) MemCpy(ptr,cl->bin_data->data,cl->bin_data->size); l->ident=ptr; l->ident_len=cl->bin_data->size; } l->last_I1=TK_INSERT_BINARY; return TK_INSERT_BINARY; case LTFT_INSERT_BINARY_TYPE: src=&lex_zeros; tempf->buf=tempf->buf_ptr=l->cur_buf_ptr=src; if (cl->bin_data) l->cur_i=cl->bin_data->type; else l->cur_i=0; tempf->line_num=cl->y+1; l->last_I1=TK_INSERT_BINARY_TYPE; return TK_INSERT_BINARY_TYPE; case LTFT_INSERT_BINARY_SIZE: src=&lex_zeros; tempf->buf=tempf->buf_ptr=l->cur_buf_ptr=src; if (cl->bin_data) l->cur_i=cl->bin_data->size; else l->cur_i=0; tempf->line_num=cl->y+1; l->last_I1=TK_INSERT_BINARY_SIZE; return TK_INSERT_BINARY_SIZE; default: cont=TRUE; cl=cl->next; } if (!cont) break; } if (cl==ltf) { if (ext[EXT_LTF_DEL]) { my_LtfDel=ext[EXT_LTF_DEL]; my_LtfDel(ltf,FALSE); } tempf->l=tempf->buf=NULL; Free(tempf->name); tempf->name=NULL; goto here; } } else { here: tempf=l->cur_lfn; if (tempf!=&l->lfns[0]) { Free(tempf->name); tempf->name=NULL; Free(tempf->buf); tempf->buf=NULL; tempf1=tempf; l->cur_lfn=tempf-=sizeof(LexFileStruct); l->cur_buf_ptr=tempf->buf_ptr; if (l->last_I1=tempf->last_I1) { l->flags&=~LF_USE_LAST_I1; return l->last_I1; } else l->flags&=~LF_USE_LAST_I1; } else { if (l->flags & LF_PROMPT) { Free(tempf->buf); my_SysPrompt=FindExtern("SysPrompt"); l->cur_buf_ptr=tempf->line_start= tempf->buf_ptr=tempf->buf=my_SysPrompt(TRUE); } else { l->last_I1=TK_EOF; l->cur_buf_ptr=src-1; return TK_EOF; } } } break; case CH_CURSOR: case CH_FORM_FEED: goto lex_getchar_start; case CH_LINE_FEED: tempf=l->cur_lfn; if (tempf->flags & LFSF_IS_LTF) return result; else { tempf->line_num++; compiled_lines++; tempf->line_start=src; } default: if (l->flags & LF_ECHO) PutChar(result); return result; } } while (TRUE); } void LexSkipEol(LexStruct *l) { U1 ch; do ch=LexGetChar(l); while (ch && ch!=CH_CR && ch!=CH_LINE_FEED); } void DelExpression(U1 *code) { Free(code); } U8 EvalExpression(LexStruct *l) { U1 *exp; U8 result=0; if (!GetExpression(l,&exp)) LexSkipEol(l); else { result=Run(exp); DelExpression(exp); } return result; } void LexIncludeString(LexStruct *l,I1 *filename, I1 *src,BoolU4 actual_file) { LexFileStruct *tempf; LexBackupLastChar(l); tempf=l->cur_lfn+sizeof(LexFileStruct); l->cur_lfn=tempf; tempf->buf=src; tempf->buf_ptr=src; tempf->line_num=1; tempf->line_start=src; tempf->last_I1=0; if (actual_file) { tempf->name=AbsoluteFileName(filename); tempf->flags=LFSF_IS_INCLUDED; } else { tempf->name=NewString(sys_temp_filename); tempf->flags=0; } l->cur_buf_ptr=src; } void LexIncludeLtf(LexStruct *l,I1 *filename) { BoolU4 is_null; LtfEntry *cl; Ltf *my_LtfRead(I1 *name,U8 flags); Ltf *ltf; LexFileStruct *tempf; LexBackupLastChar(l); tempf=l->cur_lfn+sizeof(LexFileStruct); l->cur_lfn=tempf; tempf->line_start=&lex_zeros; if (!ext[EXT_LTF_READ]) throw(EXCEPT_COMPILER,1); //This should never happen my_LtfRead=ext[EXT_LTF_READ]; ltf=my_LtfRead(filename,LTFF_DOUBLE_DOLLARS); if (!ltf) is_null=TRUE; else { tempf->l=ltf; cl=ltf->dummy.next; while (cl!=ltf) { if (cl->btype==LTFT_TEXT) break; if (cl->btype==LTFT_TAB) break; if (cl->btype==LTFT_CR) break; if (cl->btype==LTFT_INSERT_BINARY) break; if (cl->btype==LTFT_INSERT_BINARY_TYPE) break; if (cl->btype==LTFT_INSERT_BINARY_SIZE) break; cl=cl->next; } if (cl!=ltf) { tempf->line_start=cl; tempf->line_num=cl->y+1; if (cl->btype==LTFT_TEXT) { tempf->cur_entry=cl; tempf->buf=cl->display; tempf->buf_ptr=cl->display; } else { tempf->cur_entry=cl->last; //TODO might be problem at begining of file tempf->buf=&lex_zeros; tempf->buf_ptr=&lex_zeros; } is_null=FALSE; } else is_null=TRUE; } tempf->name=AbsoluteFileName(filename); if (is_null) { tempf->flags=LFSF_IS_INCLUDED; tempf->buf=&lex_zeros; tempf->buf_ptr=&lex_zeros; tempf->line_num=1; } else tempf->flags=LFSF_IS_INCLUDED|LFSF_IS_LTF; tempf->last_I1=0; l->cur_buf_ptr=tempf->buf_ptr; } void LexPush(LexStruct *l) { LexFileStruct *tempf=l->cur_lfn, *tempf1=&l->stack[l->stack_ptr++]; if (l->stack_ptr>=LFN_STACK_CNT) PrsExcept(l,"ST_LEX_STACK_OVERFLOW"); LexBackupLastChar(l); if (tempf->last_I1) l->flags|=LF_USE_LAST_I1; MemCpy(tempf1,tempf,sizeof(LexFileStruct)); } void LexPop(LexStruct *l) { LexFileStruct *tempf=l->cur_lfn, *tempf1=&l->stack[--l->stack_ptr]; l->cur_buf_ptr=tempf1->buf_ptr; if (l->last_I1=tempf1->last_I1) l->flags|=LF_USE_LAST_I1; else l->flags&=~LF_USE_LAST_I1; MemCpy(tempf,tempf1,sizeof(LexFileStruct)); } MemberListStruct *FindMember(I1 *st,ClassStruct *c) { MemberListStruct *ml=c->member_list; while (ml) { if (!StrCmp(ml->string,st)) { ml->use_cnt++; return ml; } ml=ml->next; } return NULL; } void DelMemberList(ClassStruct *tempc) { MemberListStruct *tempm,*tempm1; tempm=tempc->member_list; while (tempm) { tempm1=tempm->next; Free(tempm->string); Free(tempm->fmtstr); Free(tempm->fmtdata); if (tempm->flags & MLF_DEFAULT_AVAILABLE && tempm->member_class==sys_internal_types[IT_I1]+sizeof(ClassStruct)) Free(tempm->default_value); Free(tempm); tempm=tempm1; } tempc->size=0; tempc->last_in_member_list=&tempc->member_list; tempc->member_list=NULL; tempc->member_cnt=0; tempc->parameter_cnt=0; } I8 LexInString(LexStruct *l, I1 *buf,I8 size,BoolU4 *done) { I8 i=0,j,ch; *done=TRUE; while (iflags|=LF_USE_LAST_I1; } else if (ch>='0' && ch<='7') { j=ch-'0'; do { ch=LexGetChar(l); if (ch>='0' && ch<='7') j=j<<3+ch-'0'; } while (ch>='0' && ch<='7'); buf[i++]=j; l->flags|=LF_USE_LAST_I1; } else { l->flags|=LF_USE_LAST_I1; buf[i++]='\\'; } } else if (ch=='$$') { ch=LexGetChar(l); buf[i++]='$$'; if (ch!='$$') l->flags|=LF_USE_LAST_I1; } else buf[i++]=ch; } *done=FALSE; return i; } I8 Lex(LexStruct *l) { U8 ch; I8 i,j,k; double d; SysHashEntry *temph,**temph1; BoolU4 cont,str_done; I1 *fbuf; I1 *buf2,*buf3,buf[LEX_MAX_IDENT]; while (TRUE) { lex_cont: if (!(ch=LexGetChar(l))) return l->token=TK_EOF; if (Bt(alpha_bitmap,ch)) { i=0; buf[i++]=ch; do { if (i>=LEX_MAX_IDENT-1) break; else { if (!(ch=LexGetChar(l))) break; else { if (Bt(alpha_numeric_bitmap,ch)) buf[i++]=ch; else { l->flags|=LF_USE_LAST_I1; break; } } } } while (TRUE); buf[i++]=0; temph=NULL; if (l->local_var_list) { l->local_var_entry=FindMember(buf, l->local_var_list); } else l->local_var_entry=NULL; if (!l->local_var_entry && l->hash_table_list) temph=FindHashEntry(buf, l->hash_table_list,l->hash_mask); if (temph && !(l->flags & LF_NO_DEFINES)) j=temph->type; else j=0; if (j & HTT_STRING_CONSTANT) LexIncludeString(l, temph->string,NewString(temph><(StringConstantStruct *)->data),FALSE); else { l->hash_entry=temph; Free(l->ident); l->ident=NewString(buf); l->ident_len=i; l->token=TK_IDENT; goto lex_end; } } else if (Bt(dec_numeric_bitmap,ch)) { i=ch-'0'; ch=LexGetChar(l); if (ch=='X' || ch=='x') { while (TRUE) { ch=ToUpper(LexGetChar(l)); if (Bt(hex_numeric_bitmap,ch)) { if (ch<='9') i=i<<4+ch-'0'; else i=i<<4+ch-'A'+10; } else { l->cur_i=i; l->flags|=LF_USE_LAST_I1; l->token=TK_INTEGER; goto lex_end; } } } while (TRUE) { if (Bt(dec_numeric_bitmap,ch)) i=MulU8(i,10)+ch-'0'; else { if (ch=='.' || ch=='e' || ch=='E') break; l->cur_i=i; l->flags|=LF_USE_LAST_I1; l->token=TK_INTEGER; goto lex_end; } ch=LexGetChar(l); } if (ch=='.') ch=LexGetChar(l); float_start: //TODO:back-up for cases where i overflows // (people should use 'e', so might not be worth it) j=0; k=0; while (TRUE) { //TODO: maybe replace with log2 and insert bit field if (Bt(dec_numeric_bitmap,ch)) { j=MulU8(j,10)+ch-'0'; k++; } else { d=i+j*Pow10(-k); if (ch=='e' || ch=='E') break; l->cur_d=d; l->flags|=LF_USE_LAST_I1; l->token=TK_DOUBLE; goto lex_end; } ch=LexGetChar(l); } ch=LexGetChar(l); k=1; if (ch=='-') { k=-1; ch=LexGetChar(l); } j=0; while (TRUE) { //TODO: maybe replace with log2 and insert bit field if (Bt(dec_numeric_bitmap,ch)) j=MulU8(j,10)+ch-'0'; else { d*=Pow10(j*k); l->cur_d=d; l->flags|=LF_USE_LAST_I1; l->token=TK_DOUBLE; goto lex_end; } ch=LexGetChar(l); } } else if (ch=='"') { l->flags|=LF_IN_QUOTES; buf2=NULL; i=0; do { j=LexInString(l,buf,LEX_MAX_IDENT,&str_done); buf3=MAlloc(i+j); if (buf2) { MemCpy(buf3,buf2,i); Free(buf2); buf2=buf3; MemCpy(buf2+i,buf,j); } else { buf2=buf3; MemCpy(buf2,buf,j); } i+=j; } while (!str_done); Free(l->ident); l->ident=MAlloc(i); MemCpy(l->ident,buf2,i); Free(buf2); l->ident_len=i; l->flags&=~LF_IN_QUOTES; l->token=TK_STRING; goto lex_end; } else if (ch==0x27) { // "'" ch=LexGetChar(l); if (!ch || ch==0x27) i=0x27; else if (ch=='\\') { ch=LexGetChar(l); if (ch=='n') i=10; else if (ch=='r') i=13; else if (ch=='"') i='"'; else if (ch==0x27) i=0x27; else if (ch=='\`') i='\`'; else if (ch=='\\') i='\\'; else if (ch=='t') i=9; else if (ch=='x') { i=0; while (TRUE) { ch=ToUpper(LexGetChar(l)); if (Bt(hex_numeric_bitmap,ch)) { if (ch<='9') i=i<<4+ch-'0'; else i=i<<4+ch-'A'+10; } else break; } l->flags|=LF_USE_LAST_I1; } else if (ch>='0' && ch<='7') { i=ch-'0'; do { ch=LexGetChar(l); if (ch>='0' && ch<='7') i=i<<3+ch-'0'; } while (ch>='0' && ch<='7'); l->flags|=LF_USE_LAST_I1; } else { l->flags|=LF_USE_LAST_I1; i='\\'; } } else if (ch=='$$') { ch=LexGetChar(l); i='$$'; if (ch!='$$') l->flags|=LF_USE_LAST_I1; } else i=ch; ch=LexGetChar(l); if (ch!=0x27) l->flags|=LF_USE_LAST_I1; l->cur_i=i; l->token=TK_INTEGER; goto lex_end; } else if (ch=='#') { if (Lex(l)!=TK_IDENT) //skip '#' goto lex_end; if (!(temph=l->hash_entry)) goto lex_end; if (!(temph->type & HTT_KEYWORD)) goto lex_end; i=temph->user0; if (i==KW_INCLUDE) { if (Lex(l)!=TK_STRING) goto lex_end; if (l->flags & LF_ASM_EXPRESSIONS) fbuf=DefaultExtension(l->ident,"ASZ"); else fbuf=DefaultExtension(l->ident,"CPZ"); if (ext[EXT_LTF_READ]) LexIncludeLtf(l,fbuf); else LexIncludeString(l,fbuf,ReadTextFile(fbuf),TRUE); Free(fbuf); } else if (i==KW_DEFINE) { l->flags|=LF_NO_DEFINES; if (Lex(l)==TK_IDENT) { temph=MAllocZ(sizeof(StringConstantStruct)); temph->string=l->ident; l->ident=0; temph->use_cnt=0; temph->type=HTT_STRING_CONSTANT; SetSourceFileInfo(l,temph); i=0; do ch=LexGetChar(l); while (ch && (ch<=CH_SPACE || ch>0x7E)); if (ch>CH_SPACE && ch<=0x7E) { buf[i++]=ch; while (i=CH_SHIFT_SPACE && ch<=0x7E || ch==CH_TAB); break; } else { buf[i++]='/'; l->flags|=LF_USE_LAST_I1; } } else if (ch>=CH_SHIFT_SPACE && ch<=0x7E || ch==CH_TAB) buf[i++]=ch; else break; } } buf[i++]=0; temph><(StringConstantStruct *)->data=NewString(buf); temph1=FindHashBucket(temph->string,l->define_hash_table); temph->next=*temph1; *temph1=temph; } l->flags&=~LF_NO_DEFINES; } } else if (ch==TK_INSERT_BINARY || ch==TK_INSERT_BINARY_TYPE || ch==TK_INSERT_BINARY_SIZE) { l->token=ch; goto lex_end; } else if (ch=='.') { ch=LexGetChar(l); if (ch>='0' && ch<='9') { i=0; goto float_start; } l->flags|=LF_USE_LAST_I1; l->token='.'; goto lex_end; } else if (ch>=0x21 && ch<=0x7E) { i=duel_I1_tokens1[ch]; if (!i) { if (ch=='$$') { do ch=LexGetChar(l); while (ch && ch!='$$'); goto lex_cont; } else { l->token=ch; goto lex_end; } } else { j=LexGetChar(l); if (i.u1[0]==j) { i>>=8; if (!i) { // "/*" cont=TRUE; while (cont) { do ch=LexGetChar(l); while (ch && ch!='*'); while (cont && ch=='*') { ch=LexGetChar(l); if (ch=='/') cont=FALSE; } } goto lex_cont; } else { l->token=i; goto lex_end; } } if (i=duel_I1_tokens2[ch]) { if (i.u1[0]==j) { i>>=8; if (!i) { // "//" LexSkipEol(l); goto lex_cont; } else { if (i==TK_SHL || i==TK_SHR) { j=LexGetChar(l); if (j=='=') { if (i==TK_SHL) i=TK_SHL_EQUAL; else i=TK_SHR_EQUAL; } else l->flags|=LF_USE_LAST_I1; } l->token=i; goto lex_end; } } if (i=duel_I1_tokens3[ch]) { if (i.u1[0]==j) { l->token=i.u1[1]; goto lex_end; } } } l->flags|=LF_USE_LAST_I1; l->token=ch; goto lex_end; } } } lex_end: if (Bt(&l->flags,LFf_LEX_TRACE)) LexPutToken(l); return l->token; } I1 *LexExtendString(LexStruct *l,U8 *size) { U8 len=l->ident_len,len1,len2; I1 *st=l->ident,*st1,*st2; l->ident=NULL; while (l->token==TK_STRING) { st1=st; len1=len; if (Lex(l)==TK_STRING) { len2=l->ident_len; st2=l->ident; l->ident=NULL; len=len1+len2-1; st=MAlloc(len); if (len1>1) MemCpy(st,st1,len1-1); MemCpy(st+len1-1,st2,len2); Free(st1); Free(st2); } } *size=len; return st; } I1 *LexPutLine(LexStruct *l,I1 *start) { LtfEntry *my_LtfPutLine(LtfEntry *cl); I1 *ptr; if (!start) return; if (l->cur_lfn->flags&LFSF_IS_LTF) { if (my_LtfPutLine=FindExtern("LtfPutLine")) return my_LtfPutLine(start); } else { ptr=start; while (*ptr && *ptr!=CH_LINE_FEED && *ptr!=CH_CR) PutChar(*ptr++); CrLf; return (*ptr) ? ptr+1:ptr; } return NULL; } I8 LexLineNum(LexStruct *l) { return l->cur_lfn->line_num; } void LexPutLink(LexStruct *l) { PutFileLink(l->cur_lfn->name,l->cur_lfn->line_num); AdamErr("%s,%d\r",l->cur_lfn->name,l->cur_lfn->line_num); PutS(" "); } void PutLexError(LexStruct *l,I1 *name=NULL,I1 *msg=NULL) { PutSysText("ST_ERROR"); l->error_cnt++; AdamErr("Tsk:%08X ",Fs); if (name) { PutSysText(name); AdamErr("%S",name); } if (msg) { PutS(msg); AdamErr("%s\r\n",msg); } LexPutToken(l); LexPutLink(l); LexPutLine(l,l->cur_lfn->line_start); } void PutLexWarning(LexStruct *l,I1 *name=NULL,I1 *msg=NULL) { PutSysText("ST_WARNING"); l->warning_cnt++; if (name) PutSysText(name); if (msg) PutS(msg); LexPutToken(l); LexPutLink(l); LexPutLine(l,l->cur_lfn->line_start); } void PutAsmError(LexStruct *l,I1 *name) { PutLexError(l,name); LexSkipEol(l); Lex(l); } void PutAsmWarning(LexStruct *l,I1 *name) { PutLexWarning(l,name); LexSkipEol(l); Lex(l); } void PrsExcept(LexStruct *l,I1 *name=NULL,I1 *msg=NULL) { PutLexError(l,name,msg); IntFlushMsgs; throw(EXCEPT_COMPILER,0); } void CbPutClass(ClassStruct *c) { I8 i; if (!c) return; if (c->pointer_cnt>4) { coutln "ERROR:put_class ptrcnt=",c->pointer_cnt; while (TRUE) //TODO: SwapInNext; } for (i=0;ipointer_cnt;i++) PutChar('*'); c-=sizeof(ClassStruct)*c->pointer_cnt; if (c->string) PutS(c->string); else { coutln "ERROR:put_class string=NULL"; while (TRUE) //TODO: SwapInNext; } PutChar(CH_SPACE); } void CbPutIc(IntermediateCode *tempi) { I1 *st; U8 opcode=tempi->ic_code.u2[0]; if (opcode>EC_NOP) { st=PointAtListEntry(opcode,SysText("ST_INTERMEDIATE_CODE")); PrintF("%20ts %016X ", st+1,tempi->ic_data); if (tempi->ic_flags & ICF_NO_PUSHES) PutS("!PUSH "); CbPutClass(tempi->ic_class); if (tempi->ic_flags & ICF_TO_DOUBLE) PutS("->double "); if (tempi->ic_flags & ICF_TO_INT) PutS("->int "); if (tempi->ic_flags & ICF_NO_PUSHES_TO_DOUBLE_OR_INT) PutS("!PUSH2 "); if (tempi->ic_flags & ICF_USE_DOUBLE_TEMPLATE) PutS("[double] "); if (tempi->ic_flags & ICF_USE_UNSIGNED_TEMPLATE) PutS("[unsigned] "); CrLf; } } void CbInitOutPtrs(LexCbStack *ll) { CodeBlk *cb=MAlloc(sizeof(CodeBlk)); cb->next=NULL; ll->cb_out_first=cb; ll->cb_out_last=cb; ll->cb_misc_list=NULL; ll->cb_misc_list_end=&ll->cb_misc_list; ll->cb_out_end=cb+sizeof(CodeBlk); ll->cb_out_ptr=&cb->data; ll->cb_last_out_ptr=&cb->data; } void CbInitInPtrs(LexCbStack *ll) { CodeBlk *cb=ll->cb_out_first; ll->cb_in_first=cb; ll->cb_in_end=cb+sizeof(CodeBlk); ll->cb_in_ptr=&cb->data; } void CbPutAllIc(LexStruct *l) { IntermediateCode *tempi; CbInitInPtrs(&l->cb); tempi=l->cb.cb_in_ptr; while (tempi->ic_code) { CbPutIc(tempi); tempi+=sizeof(IntermediateCode); } } void CbAddIc(LexStruct *l, U8 opcode,U8 arg, ClassStruct *c,U8 flags=0) { IntermediateCode *tempi=l->cb.cb_out_ptr; CodeBlk *cb,*cb1; l->cb.cb_last_out_ptr=tempi; tempi->ic_code=opcode; tempi->ic_data=arg; tempi->ic_class=c; tempi->ic_flags=flags; tempi->ic_line=l->cur_lfn->line_num; if (l->flags & LF_PARSE_TRACE) CbPutIc(tempi); tempi+=sizeof(IntermediateCode); if (tempi==l->cb.cb_out_end) { cb=MAlloc(sizeof(CodeBlk)); cb->next=NULL; cb1=l->cb.cb_out_last; cb1->next=cb; l->cb.cb_out_last=cb; tempi=&cb->data; l->cb.cb_out_end=cb+sizeof(CodeBlk); } l->cb.cb_out_ptr=tempi; } IntermediateCode *CbGetIc1(LexCbStack *l) { IntermediateCode *tempi=l->cb_in_ptr, *tempi1=tempi+sizeof(IntermediateCode); CodeBlk *cb; if (tempi1==l->cb_in_end) { cb=tempi1-sizeof(CodeBlk); cb=cb->next; l->cb_in_end=cb+sizeof(CodeBlk); tempi1=&cb->data; } l->cb_in_ptr=tempi1; return tempi; } void CbPush(LexStruct *l) { LexCbStack *templ=MAlloc(sizeof(LexCbStack)); MemCpy(templ,&l->cb,sizeof(LexCbStack)); if (l->cb.cb_misc_list_end==&l->cb.cb_misc_list) templ->cb_misc_list_end=&templ->cb_misc_list; l->cb.cb_next=templ; } void CbPop(LexStruct *l) { LexCbStack *templ=l->cb.cb_next; MemCpy(&l->cb,templ,sizeof(LexCbStack)); if (templ->cb_misc_list_end==&templ->cb_misc_list) l->cb.cb_misc_list_end=&l->cb.cb_misc_list; Free(templ); } CbMiscStruct *CbFindGotoLabel(LexStruct *l,I1 *name) { CbMiscStruct *templ=l->cb.cb_misc_list; while (templ) { if (templ->type==CBMT_GOTO_LABEL) { if (!StrCmp(templ->string,name)) return templ; } templ=templ->next; } return NULL; } CbMiscStruct *CbMiscNew(LexStruct *l,U8 t) { CbMiscStruct *result=MAllocZ(sizeof(CbMiscStruct)); l->cb.cb_misc_list_end->next=result; l->cb.cb_misc_list_end=result; result->address=INVALID_PTR; result->type=t; return result; } void DelCbMiscList(LexStruct *l) { CbMiscStruct *mc=l->cb.cb_misc_list,*mc1; while (mc) { mc1=mc->next; if (mc->type==CBMT_GOTO_LABEL && !mc->address) { l->cb.cb_misc_list=NULL; //prevent recursion cout SysText("ST_ERROR"),SysText("ST_UNDEFINED_GOTO_LABEL"); coutln mc->string; throw(EXCEPT_COMPILER,1); } Free(mc->string); Free(mc->jmp_table); Free(mc); mc=mc1; } } LexStruct *CbPopNoFree(LexStruct *l) { LexCbStack *templ=l->cb.cb_next; MemCpy(&l->cb,templ,sizeof(LexCbStack)); if (templ->cb_misc_list_end==&templ->cb_misc_list) l->cb.cb_misc_list_end=&l->cb.cb_misc_list; return templ; } void CbAppend(LexStruct *l, LexCbStack *ll) { IntermediateCode *tempi; CbInitInPtrs(ll); do { tempi=CbGetIc1(ll); if (tempi->ic_code) { CbAddIc(l,tempi->ic_code,tempi->ic_data, tempi->ic_class,tempi->ic_flags); } } while (tempi->ic_code); DelLinkedList(ll->cb_out_first); if (ll->cb_misc_list_end!=&ll->cb_misc_list) { l->cb.cb_misc_list_end->next=ll->cb_misc_list; l->cb.cb_misc_list_end=ll->cb_misc_list_end; } Free(ll); } void CbCombine(LexStruct *l) { CodeBlk *cb=l->cb.cb_out_first,*cb1,*cb2; I8 i=0,j=sizeof(CodeBlk)-4; U4 *ptr; while (cb) { i++; cb=cb->next; } if (i>1) { cb1=MAlloc(i*j+4); cb1->next=NULL; cb=l->cb.cb_out_first; ptr=&cb1->data; while (cb) { cb2=cb->next; MemCpy(ptr,&cb->data,j); ptr+=j; Free(cb); cb=cb2; } l->cb.cb_out_first=cb1; } } U8 CbCountCode(LexStruct *l,I8 pass,I8 *min_line,I8 *max_line) { U8 result=0,code; I8 i,min_line2=-1,last_line=0; ClassStruct *tempc; IntermediateCode *tempi; CbMiscStruct *lb; CbInitInPtrs(&l->cb); tempi=l->cb.cb_in_ptr; while (code=tempi->ic_code.u2[0]) { if (code>EC_END_EXP) { if (code==EC_LABEL) { lb=tempi->ic_data; lb->address=result; } else if (code>=EC_SKIPZ && code<=EC_OR_OR_SKIPNZ2) { if (pass==2) { lb=tempi->ic_data; if (lb->address!=INVALID_PTR) { i=lb->address-result; if (i<116 && i>-116) //U1 disp tempi->ic_code= --code; } } } i=unsigned_code_table[code+1]-unsigned_code_table[code]; tempc=tempi->ic_class; if (!(tempi->ic_flags & ICF_USE_UNSIGNED_TEMPLATE)) { if (tempc->sub_type==IT_DOUBLE || tempi->ic_flags & ICF_USE_DOUBLE_TEMPLATE) { if (double_code_table[code+1]-double_code_table[code]) i=double_code_table[code+1]-double_code_table[code]; } else if (!(tempc->sub_type & 1) && code_table[code+1]-code_table[code]) i=code_table[code+1]-code_table[code]; } result+=i; if (tempi->ic_flags & ICF_NO_PUSHES) result-=2; if (tempi->ic_flags & ICF_TO_DOUBLE) { result+=unsigned_code_table[EC_TO_DOUBLE+1]- unsigned_code_table[EC_TO_DOUBLE]; if (tempi->ic_flags & ICF_NO_PUSHES_TO_DOUBLE_OR_INT) result-=2; } if (tempi->ic_flags & ICF_TO_INT) { result+=unsigned_code_table[EC_TO_INT+1]- unsigned_code_table[EC_TO_INT]; if (tempi->ic_flags & ICF_NO_PUSHES_TO_DOUBLE_OR_INT) result-=2; } if (pass==2 && i) { i=tempi->ic_line; if (i>=last_line) { last_line=i; if (i<*min_line) *min_line=i; if (i>*min_line && i*max_line) *max_line=i; } } } tempi+=sizeof(IntermediateCode); } lb=l->cb.cb_misc_list; while (lb) { if (lb->type==CBMT_STRING_CONSTANT) { // lb->address=result+sizeof(U4); // result+=sizeof(U4)+lb->st_len; lb->address=result; result+=lb->st_len; } else if (lb->type==CBMT_JMP_TABLE) { lb->address=result; result+=lb->st_len<<2; } lb=lb->next; } if (pass==2) { if (min_line2!=-1 && (min_line2-*min_line)>10) //Defines screw things up *min_line=min_line2; } return result; } U1 *CbCompile(LexStruct *l,ClassStruct *fun_class, U8 *code_size,DbgInfo **dbg_info,U8 *type=NULL) { U1 *result,*dst,*bb; I8 min_line=MAX_I8,max_line=0; U8 i,code,p1,p2,size,fix_up_type; U4 *dd; ClassStruct *tempc; IntermediateCode *tempi; CbMiscStruct *lb,*lb1; DbgInfo *my_dbg=NULL; ExeAbsoluteAddressStruct *tempa; AsmCtrlStruct *a=l->a; U8 Dasm2(U1 *ip,I8 cnt,BoolU4 use16); CbCombine(l); if (Bt(&l->flags,LFf_OPT_TRACE)) { coutln "$$IV 1$$Before Pass 1:$$IV 0$$"; CbPutAllIc(l); } CmpOptPass1(l,fun_class,TRUE); if (Bt(&l->flags,LFf_OPT_TRACE)) { coutln "$$IV 1$$After Pass 1:$$IV 0$$"; CbPutAllIc(l); } CmpOptPass2(l,fun_class); if (Bt(&l->flags,LFf_OPT_TRACE)) { coutln "$$IV 1$$After Pass 2:$$IV 0$$"; CbPutAllIc(l); } CmpOptPass3(l,fun_class); if (Bt(&l->flags,LFf_OPT_TRACE)) { coutln "$$IV 1$$After Pass 3:$$IV 0$$"; CbPutAllIc(l); } CmpOptPass4(l,fun_class); if (Bt(&l->flags,LFf_OPT_TRACE)) { coutln "$$IV 1$$After Pass 4:$$IV 0$$"; CbPutAllIc(l); } CbCountCode(l,1,NULL,NULL); *code_size=CbCountCode(l,2,&min_line,&max_line); result=MAlloc(*code_size); if (max_line>=min_line && max_line-min_line<10000) { my_dbg=MAllocZ(offset(DbgInfo.body)+sizeof(U4)*(max_line-min_line+1)); my_dbg->min_line=min_line; my_dbg->max_line=max_line; } if (dbg_info) *dbg_info=my_dbg; dst=result; CbInitInPtrs(&l->cb); tempi=l->cb.cb_in_ptr; while (code=tempi->ic_code.u2[0]) { if (code>EC_END_EXP) { if (type) { if (tempc=tempi->ic_class) { if (tempi->ic_flags & ICF_TO_DOUBLE) *type=IT_DOUBLE; else if (tempi->ic_flags & ICF_TO_INT) *type=IT_I8; else *type=tempc->sub_type; } } p1=unsigned_code_table[code]; p2=unsigned_code_table[code+1]; size=p2-p1; fix_up_type=unsigned_fix_up_table[code]; tempc=tempi->ic_class; if (!(tempi->ic_flags & ICF_USE_UNSIGNED_TEMPLATE)) { if (tempc->sub_type==IT_DOUBLE || tempi->ic_flags & ICF_USE_DOUBLE_TEMPLATE) { if (double_code_table[code+1]-double_code_table[code]) { p1=double_code_table[code]; p2=double_code_table[code+1]; size=p2-p1; fix_up_type=double_fix_up_table[code]; } } else if (!(tempc->sub_type & 1) && code_table[code+1]-code_table[code]) { p1=code_table[code]; p2=code_table[code+1]; size=p2-p1; fix_up_type=signed_fix_up_table[code]; } } if (tempi->ic_flags & ICF_NO_PUSHES) { p1+=2; size-=2; } if (size) { MemCpy(dst,p1,size); if (my_dbg) { if (tempi->ic_line>=min_line && tempi->ic_line<=max_line) { i=tempi->ic_line-min_line; if (!my_dbg->body[i]) { if (a) my_dbg->body[i]=a->ip+dst-result; else my_dbg->body[i]=dst; } } } } dst+=size; switch (fix_up_type) { case FUT_8_1: bb=dst-1; *bb=tempi->ic_data; break; case FUT_8_2: bb=dst-2; *bb=tempi->ic_data; break; case FUT_8_4: bb=dst-4; *bb=tempi->ic_data; break; case FUT_8_5: bb=dst-5; *bb=tempi->ic_data; break; case FUT_8_6: bb=dst-6; *bb=tempi->ic_data; break; case FUT_8_10: bb=dst-10; *bb=tempi->ic_data; break; case FUT_8_JMP_1: lb=tempi->ic_data; if (a) i=lb->address-(dst-result); else i=(result+lb->address)-dst; bb=dst-1; *bb=i; break; case FUT_32_4: dd=dst-4; *dd=tempi->ic_data; break; case FUT_32_4_CALL: if (a) i=tempi->ic_data-(a->ip+dst-result); else i=tempi->ic_data-dst; dd=dst-4; *dd=i; break; case FUT_32_4_ABS: dd=dst-4; *dd=tempi->ic_data; if (a && !(l->flags & LF_ASM_EXPRESSIONS)) { tempa=MAllocZ(sizeof(ExeAbsoluteAddressStruct)); tempa->next=a->absolutes; a->absolutes=tempa; tempa->ip=a->ip+dd-result; } break; case FUT_32_4_ABS2: lb=tempi->ic_data; if (a) i=lb->address+a->ip; else i=lb->address+result; dd=dst-4; *dd=i; if (a && !(l->flags & LF_ASM_EXPRESSIONS)) { tempa=MAllocZ(sizeof(ExeAbsoluteAddressStruct)); tempa->next=a->absolutes; a->absolutes=tempa; tempa->ip=a->ip+dd-result; } break; case FUT_32_5: dd=dst-5; *dd=tempi->ic_data; break; case FUT_32_6: dd=dst-6; *dd=tempi->ic_data; break; case FUT_32_7: dd=dst-7; *dd=tempi->ic_data; break; case FUT_32_9: dd=dst-9; *dd=tempi->ic_data; break; case FUT_32_4P10_4: dd=dst-4; *dd=tempi->ic_data; dd=dst-10; *dd=tempi->ic_data+4; break; case FUT_32_4P11_4: dd=dst-4; *dd=tempi->ic_data; dd=dst-11; *dd=tempi->ic_data+4; break; case FUT_32_JMP_4: lb=tempi->ic_data; if (a) i=lb->address-(dst-result); else i=(result+lb->address)-dst; dd=dst-4; *dd=i; break; case FUT_64_H9_L4: dd=dst-4; *dd=tempi->ic_data.u4[0]; dd=dst-9; *dd=tempi->ic_data.u4[1]; break; case FUT_ENTER1: dd=dst-11; *dd=tempi->ic_data; dd=dst-4; *dd=l->ESI_offset; break; case FUT_ENTER2: dd=dst-18; *dd=tempi->ic_data; dd=dst-10; *dd=l->ESI_offset; dd=dst-4; *dd=l->EDI_offset; break; } if (tempi->ic_flags & ICF_TO_DOUBLE) { p1=unsigned_code_table[EC_TO_DOUBLE]; p2=unsigned_code_table[EC_TO_DOUBLE+1]; size=p2-p1; if (tempi->ic_flags & ICF_NO_PUSHES_TO_DOUBLE_OR_INT) { p1+=2; size-=2; } MemCpy(dst,p1,size); dst+=size; } if (tempi->ic_flags & ICF_TO_INT) { p1=unsigned_code_table[EC_TO_INT]; p2=unsigned_code_table[EC_TO_INT+1]; size=p2-p1; if (tempi->ic_flags & ICF_NO_PUSHES_TO_DOUBLE_OR_INT) { p1+=2; size-=2; } MemCpy(dst,p1,size); dst+=size; } } tempi+=sizeof(IntermediateCode); } lb=l->cb.cb_misc_list; while (lb) { if (lb->type==CBMT_STRING_CONSTANT) { /* i=(lb->st_len+7) & -4; MemCpy(result+lb->address-sizeof(U4),&i,sizeof(U4)); */ MemCpy(result+lb->address,lb->string,lb->st_len); } else if (lb->type==CBMT_JMP_TABLE) { for (i=0;ist_len;i++) { lb1=lb->jmp_table[i]; dd=result+lb->address+i<<2; if (a) { tempa=MAllocZ(sizeof(ExeAbsoluteAddressStruct)); tempa->next=a->absolutes; a->absolutes=tempa; tempa->ip=a->ip+dd-result; *dd=lb1->address+a->ip; } else *dd=lb1->address+result; } } lb=lb->next; } Free(l->cb.cb_out_first); DelCbMiscList(l); if (Bt(&l->flags,LFf_COMPILE_TRACE)) { if (Dasm2=FindExtern("Dasm2")) Dasm2(result,*code_size,FALSE); } return result; } void DelHashTable(SysHashTable *tempht) { I8 i; SysHashEntry *temph,*temph1; ClassStruct *tempc; GlblVarStruct *tempg; if (!tempht) return; for (i=0;i<=tempht->mask;i++) { temph=tempht->body[i]; while (temph) { temph1=temph->next; Free(temph->string); if (temph->type & (HTT_FUNCTION | HTT_CLASS | HTT_STRING_CONSTANT | HTT_GLBL_VAR | HTT_SYS_SYMBOL)) { Free(temph->source_link); if (temph->type & (HTT_FUNCTION | HTT_CLASS)) { tempc=temph; Free(tempc->debug); Free(tempc->import_name); DelMemberList(tempc); //assumes code not on heap } else if (temph->type&HTT_STRING_CONSTANT) Free(temph><(StringConstantStruct *)->data); else if (temph->type&HTT_GLBL_VAR) { tempg=temph; Free(tempg->import_name); } } Free(temph); temph=temph1; } } Free(tempht); }