kolibrios-fun/programs/develop/cmm/tokc.cpp
tsdima 490fec6653 Bugfix for linux port
git-svn-id: svn://kolibrios.org@7545 a494cfbc-eb01-0410-851d-a64ba20cac60
2018-11-09 18:21:10 +00:00

10274 lines
249 KiB
C++

#define _TOKC_
#include <fcntl.h> /* O_ constant definitions */
#include <unistd.h>
#include "tok.h"
void GetFileTime(int fd,struct ftime *buf);
#define MAXIF 32
//idrec *crec=NULL;
char invaliddecrem[]="invalid token to be decremented";
char mesLOOPNZ[]="LOOPNZ";
char mesIF[]="IF";
char mesELSE[]="ELSE";
char mesWHILE[]="WHILE";
char mesFOR[]="FOR";
char mesRETURN[]="RETURN";
int tok,tok2; /* token holders current, next */
unsigned char string[STRLEN],string2[STRLEN+20],
string3[STRLEN]; //ñîäåðæèò íå ïðåîáðàçîâàííóþ ñòðîêó
unsigned int posts=0; /* number of post entrys */
postinfo *postbuf;
unsigned int maxposts=MAXPOSTS;
unsigned int secondcallnum=1; /* # of different second calls and labels */
unsigned int externnum=0;
unsigned long postsize=0; /* total size of all post vars */
unsigned int poststrptr=0; /* post string index in output */
unsigned int outptrsize=MAXDATA; //ðàçìåð âûõîäíîãî áóôåðà äëÿ êîäà
unsigned int outdatasize=MAXDATA; //ðàçìåð âûõîäíîãî áóôåðà äëÿ äàííûõ
long runfilesize;
int error=0; /* current error number holder */
unsigned char dos1=0,dos2=0; /* DOS version required for program execution */
unsigned char cpu=0; /* CPU required, 2 for 80286, 3 for 80386, ... */
unsigned int paramsize=0; /* byte size of all procedure parameters */
unsigned int localsize=0; /* byte size of all procedure local variables */
unsigned int procedure_start=0; /* address of start of procedure */
unsigned int current_proc_type; /* current procedure type */
int returntype; /* return type, (void, byte, word, ...) */
unsigned char warning;
/*+++++++++++++++++++++++ Óñòàíîâêè ïî óìîë÷àíèþ +++++++++++++++++++++++*/
unsigned char am32 = FALSE; // ðåæèì 32 áèòíîé àäðåñàöèè
unsigned char comfile = file_com; // output file format
unsigned char optimizespeed = 1; // optimize for size or speed flag
unsigned char alignword = 1; // flag whether or not to align words
unsigned char aligner = 0; // value used to align words
unsigned char header = 1; // output SPHINX C-- Ver1 Ver2 header
unsigned char chip = 0; // CPU optimization (286,386,486,...)
unsigned char killctrlc = 0; // add disable CTRL-C code in header
unsigned int stacksize = 2048; // stack size (2048 default)
unsigned char splitdata=FALSE; //îòäåëèòü äàííûå îò êîäà
unsigned char AlignCycle=FALSE; //âûðàâíèâàòü íà÷àëà öèêëîâ
/*+++++++++++++++++++ end of flexable compiler options ++++++++++++++++++++*/
unsigned char notdoneprestuff = TRUE; // flag if initial stuff has been entered
unsigned int datasize=0,alignersize=0; /* size of data and other */
unsigned int outptr=0x100,outptrdata=0x100; /* ptr to output */
unsigned char *output;
unsigned char *outputdata=NULL;
unsigned int linenumber=0;
unsigned char dynamic_flag=0; //ôëàã îáðàáîòêè äèíàìè÷åñêèõ ýëåìåíòîâ
unsigned char *input; /* dynamic input buffer */
unsigned int endinptr; /* end index of input array */
unsigned int inptr; /* index in input buffer */
unsigned char cha; /* pipe byte for token production */
char endoffile; /* end of input file flag */
unsigned char insertmode=FALSE;
unsigned int numblocks=0; //íîìåð âëîæåííîãî áëîêà
treelocalrec *tlr=NULL; //öåïî÷êà ëîêàëüíûõ áëîêîâ
treelocalrec *btlr=NULL; //öåïî÷êà èñïîëüçîâàíûõ ëîêàëüíûõ áëîêîâ
RETLIST *listreturn=NULL;
unsigned int numreturn=0;
idrec *staticlist;
unsigned char stat_reg[8]; //òàáëèöà çàíÿòîñòè ðåãèñòðîâ
int sizestack=0; //ðàçìåð íå êîìïåíñèðîâàííûõ ïàðàìåòðîâ ôóíêöèé
unsigned char addstack=TRUE;
extern char shorterr[];
extern unsigned long long li[];
/*-----------------01.05.98 19:22-------------------
äîïîëíèòåëüíûå ïåðåìåííûå äëÿ ðåàëèçàöèè BREAK CONTINUE
--------------------------------------------------*/
#define MAXIN 100 //ìàêñèìàëüíàÿ âëîæåíîñòü öèêëîâ
unsigned int numbr=0; //ñ÷åò÷èê îáùåãî ÷èñëà öèêëîâ LOOP DO-WHILE...
unsigned int listbr[MAXIN]; //òàáëèöà íîìåðîâ öèêëîâ
unsigned int usebr[MAXIN]; //èñïîëüçîâàíî break
unsigned int useco[MAXIN]; //èñïîëüçîâàíî continue
unsigned int curbr=0,curco=0; //òåêóùàÿâëîæåíîñòü öèêëîâ
unsigned int startStartup=0x100;
unsigned int endStartup=0;
unsigned char useStartup=FALSE;
unsigned char notpost=FALSE;
int retproc;
int lastcommand; //ïîñëåäíèé îïåðàòîð â áëîêå
unsigned char FastCallApi=TRUE; //ðàçðåøèòü áûñòðûé âûçîâ API ïðîöåäóð
unsigned char FixUp=FALSE; //Äåëàòü ëè òàáëèöó ïåðåìåùåíèé
unsigned char AlignProc=FALSE;
//------- ðàáîòà ñ union ---------------------------------------------
char param[256]; //áóôåð äëÿ ïàðàìåòðîâ ïðîöåäóðû
char *BackTextBlock; //áóôåð äëÿ ïåðåíåñåííîãî òåêñòà
int SizeBackBuf=0,MaxSizeBackBuf;
struct FILEINFO *startfileinfo=NULL;
unsigned int totalmodule=0;
unsigned int currentfileinfo;
unsigned char setzeroflag; //îïåðàöèÿ ìåíÿåò zero flag
unsigned char notunreach=FALSE;
unsigned int initBP=0;
int inlineflag=0; // flag for disabling entry and exit codes production
unsigned char fstatic=FALSE;
unsigned long addESP=0; //äîáàâêà ñòåêà
unsigned char blockproc=FALSE; //èäåòðàçáîðêà áëîêà ôóíêöèè
unsigned int updatelocalvar(char *str,int tok,unsigned int num);
void setuprm();
void doloop(unsigned int typeb); /* both short and long loops */
void doBREAK(unsigned char typeb);
void doCONTINUE(unsigned char typeb);
void dowhile(unsigned int typeb);
void MakeContinue(unsigned char typeb);
void dofor(unsigned int typeb);
void dodo();
void globalvar(); /* both initialized and unitialized combined */
void doswitch();
void CalcRegPar(int reg,int def,char *&ofsstr);
void JXorJMP();
int loadinputfile(char *inpfile);
int SaveStartUp(int size,char *var_name);
void LoadData(unsigned int size,int filehandle);
void SetNewTok(int type,int typev);
void doreturn(int type=tokens); /* do return(...); */
void notnegit(int notneg);
void insertcode(); // force code procedure at specified location
void interruptproc();
void dobigif();
void doif(void);
void doasmblock();
void declareextern();
unsigned long dounion(int,int);
void RunBackText();
int FindDublString(int segm,unsigned int len,int term);
void *liststring=NULL; //öåïî÷êà èíôîðìàöèîííûõ áëîêîâ î ñòðîêàõ
void GetNameLabel(int type,int num);
void CheckPosts();
SAVEPAR *SRparam(int save,SAVEPAR *par); //save or restore global param compiler
void AddRetList(int pos,int line,int type);
void CheckRealizable();
void declare_procedure(int oflag,int orm,int npointr);
void labelindata();
void AddRegistr(int razr,int reg);
void ClearRegister();
int GetRegister(int mode=0);
void RegAddNum(int reg);
void dowhilefast(unsigned int typeb);
int getrazr(int type);
void RestoreSaveReg();
void killlocals(/*int endp=TRUE*/);
void leaveproc();
int IsSaveReg();
void CorrectParamVar();
extern void ManyLogicCompare();
extern void maxdataerror();
extern void CompareOr();
extern void dynamiclabelerror();
extern void retvoid();
extern int numberbreak;
SAVEREG savereg;
SAVEREG *psavereg=&savereg;
int loadfile(char *filename,int firstflag)
{
int hold;
for(int i=0;i<=numfindpath;i++){
sprintf((char *)string2,"%s%s",findpath[(firstflag==0?i:numfindpath-i)],filename);
#ifndef _WIN32_
for(char* p=(char *)string2; *p; ++p) if(*p=='\\') *p='/';
#endif
if((hold=loadinputfile((char *)string2))!=-2)break;
if(firstflag==2||(firstflag==0&&(i+1)==numfindpath))break;
}
if(hold==-2){
unableopenfile(filename); //ñîîáùåíèå î îøèáêå
exit(e_cannotopeninput); //çàâåðøèòü ðàáîòó åñëè íå ñìîãëè çàãðóçèòü ôàéë
}
return hold;
}
void compilefile(char *filename,int firstflag)
{
int hold;
hold=loadfile(filename,firstflag);
if(hold==1||hold==-1)return;
if(strcmp(filename,"startup.h--")==0)startupfile=currentfileinfo;
inptr=0;
endoffile=0;
startline=(char*)input;
endinput=startline+endinptr;
warning=gwarning;
nextchar();
cha2=cha; //ñèìâîë èç áóôåðà
inptr2=inptr; //çàïîìí óêàçàòåëü íà ñëåä ñèìâîë
linenum2=1; //íîìåð ñòðîêè
{ //ïðîâåðêà íà ôàéë ðåñóðñîâ è åãî îáðàáîòêà
char *a;
if((a=strrchr(filename,'.'))!=NULL){
if(stricmp(a,".rc")==0){
input_res();
free(input);
return;
}
}
}
nexttok(); //îïð òèï ïåðâîãî è âòîðîãî òîêåíà
while(tok!=tk_eof){ //öèêë ïîêà íå êîí÷èòñÿ ôàéë
while(tok==tk_question){
directive();//îáðàáîòêà äèðåêòèâ
if(tok==tk_semicolon)nexttok();
}
usedirectiv=FALSE;
if(notdoneprestuff==TRUE)doprestuff();//startup
switch(tok){
case tk_ID:
case tk_id:
if(FindTeg(TRUE)!=NULL){
InitStruct();
break;
}
if(tok2==tk_colon){
labelindata();
break;
}
case tk_far:
case tk_cdecl:
case tk_pascal:
case tk_stdcall:
case tk_fastcall:
case tk_declare:
case tk_undefproc:
case tk_float:
case tk_long:
case tk_dword:
case tk_word:
case tk_byte:
case tk_char:
case tk_int:
case tk_void:
case tk_export:
case tk_qword:
case tk_double:
case tk_fpust:
if((hold=testInitVar())==FALSE)define_procedure();
else if(hold==TRUE)globalvar();
break;
case tk_struct: InitStruct(); break;
case tk_interrupt: interruptproc(); break;
case tk_at: insertcode(); break; //âñòàâêà ðåãèñòðîâîé ïðîöåäóðû
case tk_colon:
nexttok();
dynamic_flag=2;
break;// îïð äèíàìè÷åñêîé ïðîöåäóðû
case tk_inline:
if(testInitVar()){
preerror("Bad header dynamic function");
nexttok();
}
dynamic_proc();
break;
case tk_static:
fstatic=2;
nexttok();
break;
case tk_enum: doenum(); break;
case tk_from: nexttok(); dofrom(); nextseminext(); break;
case tk_extract: nexttok(); doextract(); seminext(); break;
case tk_loop:
case tk_while:
case tk_do:
case tk_else:
case tk_ELSE:
case tk_if:
case tk_IF:
case tk_interruptproc:
case tk_proc:
case tk_charvar:
case tk_intvar:
case tk_bytevar:
case tk_longvar:
case tk_dwordvar:
case tk_floatvar:
case tk_qwordvar:
case tk_doublevar:
case tk_wordvar: idalreadydefined(); break;
case tk_reg32:
case tk_debugreg:
case tk_controlreg:
case tk_testreg:
case tk_reg:
case tk_seg:
case tk_beg:
case tk_reg64:
preerror("register name cannot be used as an identifier");
nexttok();
case tk_eof: break;
case tk_locallabel: internalerror("local label token found outside function block."); break;
case tk_extern: declareextern(); break;
case tk_union: dynamic_flag=0; dounion(TRUE,fstatic==0?0:f_static); break;
case tk_semicolon: nexttok(); break;
case tk_asm:
if(tok2==tk_openbrace)doasmblock();
else doasm();
break;
case tk_idasm: doasm(TRUE); break;
case tk_dollar: doasm(FALSE); break;
default: unuseableinput();
/* while(itok.type==tp_stopper&&tok!=tk_eof)*/nexttok();
break;
}
if(fstatic)fstatic--;
else if(dynamic_flag)dynamic_flag--;
}
(startfileinfo+currentfileinfo)->stlist=staticlist;
free(input);
}
/* ------------------- output procedures start ------------------- */
int CheckCodeSize()
//ïðîâåðêà ðàçìåðà áóôåðà äëÿ êîäà
{
if(!am32){
maxoutputerror();
return FALSE;
}
outptrsize+=MAXDATA;
output=(unsigned char *)REALLOC(output,outptrsize);
if(splitdata==FALSE)outputdata=output;
return TRUE;
}
int CheckDataSize()
//ïðîâåðêà ðàçìåðà áóôåðà äëÿ êîäà
{
if(!am32){
maxoutputerror();
return FALSE;
}
outdatasize+=MAXDATA;
outputdata=(unsigned char *)REALLOC(outputdata,outdatasize);
return TRUE;
}
void op(int byte)
{
if(outptr>=outptrsize&&CheckCodeSize()==FALSE)return;
output[outptr++]=(unsigned char)byte;
if(splitdata==FALSE)outptrdata=outptr;
retproc=FALSE;
}
void opd(int byte)
{
if(splitdata==FALSE){
if(outptr>=outptrsize&&CheckCodeSize()==FALSE)return;
output[outptr++]=(unsigned char)byte;
outptrdata=outptr;
}
else{
if(outptrdata>=outdatasize&&CheckDataSize()==FALSE)return;
outputdata[outptrdata++]=(unsigned char)byte;
}
}
void CorrectOfsBit(int bitofs)
{
bitofs=(bitofs+7)/8;
if(splitdata)outptrdata+=bitofs;
else{
outptr+=bitofs;
outptrdata=outptr;
}
}
long GetBitMask(int ofs,int size)
{
return (~((li[size]-1)<<ofs));
}
void opb(unsigned long num,unsigned int ofs,unsigned int size)
{
int s;
//ïðîâåðèòü âûõîä çà ãðàíèöû áëîêà ïàìÿòè
s=(ofs+size+7)/8;
if(splitdata==FALSE){
if((outptr+s+8)>=outptrsize&&CheckCodeSize()==FALSE)return;
}
else{
if((outptrdata+s+8)>=outdatasize&&CheckDataSize()==FALSE)return;
}
if(size!=32)num=num&(li[size]-1);
s=outptrdata+ofs/8;
ofs=ofs%8;
*(long *)&outputdata[s]&=GetBitMask(ofs,size);
*(long *)&outputdata[s]|=(num<<ofs);
// printf("ofs=%Xh mask=%X value=%X\n",s,GetBitMask(ofs,size),(num<<ofs));
if((ofs+size)>32){
*(long *)&outputdata[s+4]&=GetBitMask(0,ofs+size-32);
*(long *)&outputdata[s+4]|=(num>>(64-ofs-size));
// printf("continue ofs=%Xh mask=%X value=%X\n",s+4,GetBitMask(0,ofs+size-32),num>>(64-ofs-size));
}
}
void outword(unsigned int num)
{
op(num);
op(num/256);
}
void outwordd(unsigned int num)
{
opd(num);
opd(num/256);
}
void outdword(unsigned long num)
{
outword((unsigned int)(num&0xFFFFL));
outword((unsigned int)(num/0x10000L));
}
void outdwordd(unsigned long num)
{
outwordd((unsigned int)(num&0xFFFFL));
outwordd((unsigned int)(num/0x10000L));
}
void outqword(unsigned long long num)
{
outdword((unsigned long)(num&0xFFFFFFFFL));
outdword((unsigned long)(num/0x100000000LL));
}
void outqwordd(unsigned long long num)
{
outdwordd((unsigned long)(num&0xFFFFFFFFL));
outdwordd((unsigned long)(num/0x100000000LL));
}
void doasmblock()
{
nexttok();
useasm=TRUE;
expecting(tk_openbrace);
for(;;){
if(tok==tk_closebrace)break;
if(tok==tk_eof){
unexpectedeof();
break;
}
lastcommand=tok;
if(dbg)AddLine();
doasm(TRUE);
}
useasm=FALSE;
nexttok();
}
void doblock()
{
expecting(tk_openbrace);
doblock2();
/* for(;;){
if(tok==tk_closebrace)break;
if(tok==tk_eof){
unexpectedeof();
break;
}
docommand();
}
RestoreStack();*/
}
void doblock2()
{
for(;;){
if(tok==tk_closebrace)break;
if(tok==tk_eof){
unexpectedeof();
break;
}
docommand();
}
if(numblocks==1&&addstack&&sizestack&&localsize&&am32&&ESPloc&&IsSaveReg()==FALSE){
localsize+=sizestack;
sizestack=0;
}
else RestoreStack();
}
void gotodo()
{
nexttok();
if(gotol(0))nexttok();
seminext();
}
void GOTOdo()
{
nexttok();
if(GOTO())nexttok();
seminext();
}
void docommand() /* do a single command */
{
unsigned int useflag;
useflag=0;
if(dbg)AddLine();
//loops:
lastcommand=tok;
// printf("tok=%d %s\n",tok,itok.name);
switch(tok){
case tk_ID: useflag++;
case tk_id:
if((useflag=doid((char)useflag,tk_void))!=tokens){
nextseminext();
if(useflag==tk_fpust)preerror("function returned parametr in FPU stack");
}
else if(tok!=tk_closebrace)docommand();
break;
case tk_apiproc:
case tk_undefproc:
case tk_declare:
if(doanyundefproc()!=tokens)nextseminext();
else if(tok!=tk_closebrace)docommand();
break;
case tk_proc:
doanyproc();
nextseminext();
break;
case tk_interruptproc:
outword(0x0E9C); //pushf //push cs
useflag=itok.post;
callloc(itok.number);
nexttok();
expecting(tk_openbracket);
expecting(tk_closebracket);
#ifdef OPTVARCONST
FreeGlobalConst();
#endif
seminext();
clearregstat(useflag);
break;
case tk_bits:
dobits();
break;
case tk_charvar: useflag=1;
case tk_bytevar:
dobytevar(useflag);
break;
case tk_intvar: useflag=1;
case tk_wordvar:
do_d_wordvar(useflag,r16);
break;
case tk_longvar: useflag=1;
case tk_dwordvar:
do_d_wordvar(useflag,r32);
break;
case tk_doublevar:
useflag=4;
case tk_floatvar:
dofloatvar(useflag,tk_floatvar,tk_semicolon);
break;
case tk_qwordvar:
doqwordvar();
break;
case tk_fpust:
dofloatstack(itok.number);
break;
case tk_structvar:
dostruct();
break;
case tk_pointer:
dopointer();
break;
case tk_mult:
dovalpointer();
break;
case tk_RETURN:
case tk_return:
RestoreStack();
#ifdef OPTVARCONST
ClearLVIC();
#endif
doreturn(tok);
CheckRealizable();
break;
case tk_at:
nexttok();
if(tok2==tk_colon){
LLabel();
if(tok!=tk_closebrace)docommand();
}
else if(macros(tk_void)!=0)nextseminext();
break;
case tk_if: RestoreStack(); doif(); break;
case tk_IF: RestoreStack(); dobigif(); break;
case tk_loopnz:
case tk_LOOPNZ:
case tk_loop: RestoreStack(); doloop(tok); break;
case tk_while:
case tk_WHILE: RestoreStack(); dowhilefast(tok); break;
case tk_do: RestoreStack(); dodo(); break;
case tk_for:
case tk_FOR: RestoreStack(); dofor(tok); break;
case tk_reg32: doreg_32((unsigned int)itok.number,r32); break;
case tk_reg: doreg_32((unsigned int)itok.number,r16); break;
case tk_beg: dobeg((unsigned int)itok.number); break;
case tk_reg64: doreg64(itok.number); break;
case tk_seg: doseg((unsigned int)itok.number); break;
case tk_openbrace:
startblock();
doblock();
nexttok();
endblock();
break;
case tk_from: nexttok(); dofrom(); nextseminext(); break;
case tk_extract: nexttok(); doextract(); seminext(); break;
case tk_minus: useflag=8;
case tk_not:
notnegit(useflag);
nextseminext();
break;
case tk_locallabel: RestoreStack(); define_locallabel(); break;
case tk_camma:
case tk_semicolon: nexttok(); break;
case tk_else:
preerror("else without preceeding if or IF");
nexttok();
break;
case tk_ELSE:
preerror("ELSE without preceeding IF or if");
nexttok();
break;
case tk_eof: unexpectedeof(); break;
case tk_void:
case tk_long:
case tk_dword:
case tk_word:
case tk_byte:
case tk_int:
case tk_char:
preerror("cannot declare variables within function { } block");
nexttok();
break;
case tk_GOTO:
RestoreStack();
GOTOdo();
CheckRealizable();
break;
case tk_goto:
RestoreStack();
gotodo();
CheckRealizable();
break;
case tk_BREAK:
RestoreStack();
doBREAK(BREAK_SHORT);
CheckRealizable();
break;
case tk_break:
RestoreStack();
doBREAK((unsigned char)(am32==FALSE?BREAK_NEAR:BREAK_32));
CheckRealizable();
break;
case tk_CONTINUE:
RestoreStack();
doCONTINUE(CONTINUE_SHORT);
CheckRealizable();
break;
case tk_continue:
RestoreStack();
doCONTINUE((unsigned char)(am32==FALSE?CONTINUE_NEAR:CONTINUE_32));
CheckRealizable();
break;
case tk_asm:
if(tok2==tk_openbrace)doasmblock();
else doasm();
break;
case tk_idasm:
useflag=TRUE;
case tk_dollar:
doasm(useflag);
break;
case tk_SWITCH:
case tk_switch: RestoreStack(); doswitch(); break;
case tk_delete: dodelete(); break;
case tk_new: donew(); seminext(); break;
case tk_question:
// calcnumber=FALSE;
while(tok==tk_question)directive();
break;
/* case tk_openbracket:
nexttok();
nexttok();
expectingoperand(tk_closebracket);
goto loops;*/
default: unuseableinput(); break;
}
notunreach=FALSE;
}
void doBREAK(unsigned char typeb)
{
if(curbr==0)preerror("'BREAK' or 'break' use only in loop, do-while..");
else MakeBreak(typeb);
nextseminext();
}
void doCONTINUE(unsigned char typeb)
{
if(curco==0)preerror("'CONTINUE' or 'continue' use only in loop, do-while..");
else MakeContinue(typeb);
nextseminext();
}
void MakeBreak(unsigned char typeb)
{
unsigned int nbr=0;
if(tok2==tk_number){
nexttok();
nbr=itok.number;
if(nbr>=curbr)preerror("'BREAK' or 'break' on incorrect number skip cycle");
}
numberbreak=nbr;
nbr=curbr-1-nbr;
if(usebr[nbr]==0){
GetNameLabel(tk_break,nbr);
addlocalvar((char *)string2,tk_locallabel,secondcallnum,TRUE);
usebr[nbr]=secondcallnum;
secondcallnum++;
}
addacall(usebr[nbr],typeb);
if(typeb==BREAK_SHORT)outword(0x00EB); // JMP SHORT
else jumploc0();
}
void MakeContinue(unsigned char typeb)
{
unsigned int nbr=0;
if(tok2==tk_number){
nexttok();
nbr=itok.number;
if(nbr>=curco)preerror("'CONTINUE' or 'continue' on incorrect number skip cycle");
}
nbr=curco-1-nbr;
if(useco[nbr]==0){
GetNameLabel(tk_continue,nbr);
// printf("%s nbr=%d\n",(char *)string2,nbr);
addlocalvar((char *)string2,tk_locallabel,secondcallnum,TRUE);
useco[nbr]=secondcallnum;
secondcallnum++;
}
addacall(useco[nbr],typeb);
if(typeb==CONTINUE_SHORT)outword(0x00EB); // JMP SHORT
else jumploc0();
}
int CheckExitProc()
{
if(strcmp(itok.name,"EXIT")==0||strcmp(itok.name,"ABORT")==0)return TRUE;
return FALSE;
}
void LLabel()
{
localrec *ptr;
#ifdef OPTVARCONST
ClearLVIC();
#endif
RestoreStack();
clearregstat();
switch(tok){
case tk_id:
case tk_ID:
FindOff((unsigned char *)itok.name,CS);
ptr=addlocalvar(itok.name,tk_number,outptr,TRUE);
if(FixUp)ptr->rec.flag=f_reloc;
break;
case tk_undefproc:
ptr=addlocalvar(itok.name,tk_number,outptr,TRUE);//äîáàâèòü â ëîêàëüíûé ñïèñîê
if(FixUp)ptr->rec.flag=f_reloc;
updatecall((unsigned int)itok.number,outptr,procedure_start);//îáðàáîòàòü ðàííèå îáðàùåíèÿ
break;
default:
preerror("error declaretion local label");
break;
}
nexttok();
nexttok();
}
void AddApiToPost(unsigned int num)
{
CheckPosts();
(postbuf+posts)->type=CALL_32I;
(postbuf+posts)->loc=outptr;
(postbuf+posts)->num=num;
posts++;
outdword(0);
}
/* ---------------------- Procedure Calling Starts -------------------- */
int doanyundefproc(int jumpsend)
{
unsigned int cnum,snum;
int returnvalue;
int regs;
char fname[IDLENGTH];
if(tok2==tk_colon){ // if a label
#ifdef OPTVARCONST
ClearLVIC();
#endif
RestoreStack();
clearregstat();
if(CidOrID()==tk_ID){//local label that has been used, but not placed
localrec *ptr=addlocalvar(itok.name,tk_number,outptr,TRUE);
if(FixUp)ptr->rec.flag=f_reloc;
updatecall((unsigned int)itok.number,outptr,procedure_start);//îáðàáîòàòü ðàííèå îáðàùåíèÿ
}
else{ //ãëîáàëüíàÿ ìåòêà
tok=tk_proc;
itok.number=outptr;
string[0]=0;
updatecall((unsigned int)updatetree(),(unsigned int)itok.number,0);
}
nexttok(); // move past id
nexttok(); // move past :
return(tokens);
}
if(tok2==tk_openbracket){
strcpy(fname,itok.name);
if(tok==tk_declare){ //ñìåíèòü ñòàòóñ ïðîöåäóðû ñ îáúÿâëåíîé íà íåèçâåñòíóþ
tok=tk_undefproc;
updatetree();
if(itok.flag&f_classproc)AddUndefClassProc();
}
cnum=(unsigned int)itok.number;
regs=itok.post;
returnvalue=itok.rm;
unsigned int tproc=itok.flag;
unsigned char apiproc=FALSE;
unsigned int oaddESP=addESP;
int sizestack=-1;
if(tok==tk_apiproc){
apiproc=TRUE;
sizestack=itok.size; //ðàçìåð ñòåêà ïîä ïàðàìåòðû
}
#ifdef OPTVARCONST
if(tproc&f_useidx)ClearLVIC();
else FreeGlobalConst();
#endif
int exitproc=CheckExitProc();
snum=initparamproc();
if(sizestack!=-1){
if(snum>(unsigned int)sizestack)extraparam(fname);
else if(snum<(unsigned int)sizestack)missingpar(fname);
}
if((tproc&f_typeproc)!=tp_cdecl){
snum=0;
addESP=oaddESP;
}
if(FastCallApi==TRUE&&apiproc!=FALSE){
if(jumpsend)outword(0x25ff);
else outword(0x15FF);
AddApiToPost(cnum);
}
else{
addacall(cnum,(unsigned char)((tproc&f_extern)!=0?CALL_EXT:(am32!=FALSE?CALL_32:CALL_NEAR)));
if(jumpsend)jumploc0();
else callloc0(); /* produce CALL [#] */
}
clearregstat(regs);
if(snum!=0&&jumpsend==FALSE)CorrectStack(snum);
retproc=exitproc;
return(returnvalue);
}
thisundefined(itok.name);
nexttok();
return(tk_long);
}
void CorrectStack(unsigned int num)
{
if(addstack){
sizestack+=num;
// printf("%s(%d)> Add %d bytes stacks.\n",startfileinfo==NULL?"":(startfileinfo+currentfileinfo)->filename,linenumber,num);
}
else{
if(short_ok(num)){
outword(0xC483);
op(num);
}
else{
outword(0xC481);
if(am32==FALSE)outword(num);
else outdword(num);
}
addESP-=num;
}
}
unsigned int initparamproc()
{
unsigned int typep=itok.flag,snum=0;
ITOK ostructadr=structadr;
strcpy(param,(char *)string);
nexttok();
switch(typep&f_typeproc){
case tp_cdecl:
case tp_stdcall:
snum=swapparam();
break;
case tp_pascal:
doparams();
break;
case tp_fastcall:
doregparams();
break;
}
// if(crec)printf("after doparams num=%08X\n",crec->recnumber);
if((typep&f_classproc)&&(!(typep&f_static))){
if((current_proc_type&f_static)&&structadr.sib==THIS_PARAM )return snum;
structadr=ostructadr;
if(structadr.sib==THIS_PARAM){
if(structadr.number==0){
op(0xff);
if(ESPloc&&am32){
int num;
num=localsize+addESP+4;
if(short_ok(num,TRUE)){
outword(0x2474);
op(num);
}
else{
outword(0x24B4);
outdword(num);
}
}
else outword(am32==FALSE?0x0476:0x0875);//push[ebp+4]
}
else{
int reg=GetRegister(1);
op(0x8B);
if(ESPloc&&am32){
int num;
num=localsize+addESP+4;
if(short_ok(num,TRUE)){
op(4+reg*8+64);
op(0x24);
op(num);
}
else{
op(4+reg*8+128);
op(0x24);
outdword(num);
}
}
else{
op((am32==FALSE?6:5)+reg*8+64);
op((am32==FALSE?4:8));//mov ESI,[ebp+4]
}
RegAddNum(reg);
op(0x50+reg); //push reg
warningreg(regs[am32][reg]);
}
}
else if(structadr.sib==THIS_REG){
if(structadr.number/*size*/!=0){
int reg=GetRegister(1);
if(reg==structadr.rm)RegAddNum(reg);
else{
if(am32==FALSE){
switch(structadr.rm){
case BX:
structadr.rm=7;
break;
case DI:
structadr.rm=5;
break;
case SI:
structadr.rm=4;
break;
case BP:
structadr.rm=6;
break;
default:
regBXDISIBPexpected();
}
structadr.sib=CODE16;
}
else structadr.sib=CODE32;
structadr.rm|=(structadr.number<128?rm_mod01:rm_mod10);
op(0x8d); //lea reg [reg2+num]
op(structadr.rm+reg*8);
outaddress(&structadr);
}
op(0x50+reg);
warningreg(regs[am32][reg]);
}
else op(0x50+structadr.rm);
}
else if(structadr.sib==THIS_NEW){
RunNew(structadr.number);
op(0x50);
}
else if(structadr.sib==THIS_ZEROSIZE){
outword(0x6a); //push 0
}
else{
// printf("post=%d\n",structadr.post);
if(structadr.post==LOCAL){
int reg=GetRegister(1);
structadr.post=0;
outseg(&structadr,2);
op(0x8d);
op(structadr.rm+reg*8);
outaddress(&structadr);
op(0x50+reg);
warningreg(regs[am32][reg]);
}
else{
if(strinf.bufstr){
int reg=GetRegister(1);
int newreg;
if((newreg=CheckIDXReg(strinf.bufstr,strinf.size,reg))!=NOINREG){
if(newreg!=SKIPREG){
if(am32==FALSE&&newreg!=BX&&newreg!=DI&&newreg!=SI&&newreg!=BP)goto noopt;
waralreadinitreg(regs[am32][reg],regs[am32][newreg]);
reg=newreg;
}
free(strinf.bufstr);
goto cont1;
}
noopt:
if(newreg=CheckMassiv(strinf.bufstr,strinf.size,reg)!=-1)reg=newreg;
cont1:
strinf.bufstr=NULL;
RegAddNum(reg);
op(0x50+reg);
}
else{
op(0x68);
if(structadr.post/*&&structadr.post!=USED_DIN_VAR*/)setwordpost(&structadr);
else if(FixUp)AddReloc();
if(am32==FALSE)outword((unsigned int)structadr.number);
else outdword(structadr.number);
}
}
}
snum+=(am32==FALSE?2:4);
addESP+=(am32==FALSE?2:4);
}
if(typep&f_far)op(0x0e); //push cs
return snum;
}
int doanyproc(int jumpsend)
{
unsigned int cloc,snum;
int returnvalue,dynamicindex;
int regs;
if(tok2==tk_colon){
preerror("dublication global label");
nexttok();
return 0;
}
cloc=(unsigned int)itok.number; /* get address or handle */
returnvalue=itok.rm;
regs=itok.post;
// printf("regs=%08X name=%s\n",regs,itok.name);
int flag=itok.flag;
if(itok.npointr)dopointerproc();
else{
if((itok.flag&f_inline)!=0&&(useinline==TRUE||(useinline==2&&optimizespeed))){
if(macros(tk_void)!=0)return(returnvalue);
}
dynamicindex=itok.segm;
// printf("%s %08X seg=%d\n",rec->recid/*itok.name*/,itok.flag,itok.segm);
if(itok.segm==DYNAMIC){
itok.segm=DYNAMIC_USED;
updatetree();
}
unsigned int oaddESP=addESP;
snum=initparamproc();
if((flag&f_typeproc)!=tp_cdecl){
snum=0;
addESP=oaddESP;
}
if(dynamicindex<NOT_DYNAMIC){ //äèíàìè÷åñêàÿ ïðîöåäóðà
addacall(cloc,(unsigned char)(am32!=FALSE?CALL_32:CALL_NEAR));
if(jumpsend)jumploc0();
else{
callloc0();
if(snum!=0)CorrectStack(snum);
}
}
else{
if(jumpsend)jumploc(cloc);
else{
callloc(cloc);
if(snum!=0)CorrectStack(snum);
}
}
}
#ifdef OPTVARCONST
if(flag&f_useidx)ClearLVIC();
else FreeGlobalConst();
#endif
clearregstat(regs);
return(returnvalue);
}
int doid(char uppercase,int expectedreturn)
{
int cnum;
if(tok2==tk_colon){ // if a label
#ifdef OPTVARCONST
ClearLVIC();
#endif
RestoreStack();
clearregstat();
cnum=FindOff((unsigned char *)itok.name,CS);
if(uppercase){
localrec *ptr=addlocalvar(itok.name,tk_number,outptr,TRUE);
if(FixUp)ptr->rec.flag=f_reloc;
}
else{
tok=tk_proc;
itok.rm=tk_void;
itok.number=outptr;
itok.segm=NOT_DYNAMIC;
itok.flag=0;
string[0]=0;
itok.type=tp_ucnovn;
addtotree(itok.name);
itok.rec->count=cnum;
}
nexttok(); // move past id
nexttok(); // move past :
return(tokens);
}
if(tok2==tk_openbracket){
if((cnum=CheckMacros())!=tokens)return cnum;
tobedefined(am32==FALSE?CALL_NEAR:CALL_32,expectedreturn);
cnum=posts-1;
param[0]=0;
int flag=itok.flag;
int exitproc=CheckExitProc();
unsigned int oaddESP=addESP;
if(itok.flag==tp_stdcall){
nexttok();
swapparam();
}
else{
nexttok();
if(uppercase)doregparams();
else doparams();
}
(postbuf+cnum)->loc=outptr+1;
callloc0(); /* produce CALL [#] */
clearregstat();
addESP=oaddESP;
#ifdef OPTVARCONST
if(flag&f_useidx)ClearLVIC();
else FreeGlobalConst();
#endif
retproc=exitproc;
return(expectedreturn);
}
thisundefined(itok.name);
return(tk_long);
}
int typesize(int vartype) // âîçâðàùàåò ðàçìåð â áàéòàõ êîäà âîçâðàòà
{
switch(vartype){
case tk_char:
case tk_byte: return(1);
case tk_int:
case tk_word: return(2);
case tk_float:
case tk_dword:
case tk_long: return(4);
case tk_double:
case tk_qword: return 8;
}
return(0);
}
void FpuSt2Number()
{
op66(r32); //push EAX
op(0x50);
CheckInitBP();
fistp_stack();
RestoreBP();
fwait3();
op66(r32);
op(0x58); //pop EAX
if(cpu<3)cpu=3;
}
void FpuSt2QNumber()
{
op66(r32); //push EAX
op(0x50);
op66(r32); //push EAX
op(0x50);
CheckInitBP();
fistp_stack(4);
RestoreBP();
fwait3();
op66(r32);
op(0x58+EDX); //pop EAX
op66(r32);
op(0x58); //pop EAX
if(cpu<3)cpu=3;
}
void fwait3_4()
{
if(chip<4)op(0x9B);
}
void convert_returnvalue(int expectedreturn,int actualreturn)
{
if(expectedreturn==tk_void)return; //17.09.05 17:52
if(actualreturn==tk_void/*||expectedreturn==tk_void*/){
retvoid();
return;
}
switch(expectedreturn){
case tk_byte:
case tk_char:
case tk_word:
case tk_int:
if(actualreturn==tk_float||actualreturn==tk_double){
op66(r32);
op(0x50);
FloatToNumer(actualreturn==tk_float?0:4);
}
else if(actualreturn==tk_fpust)FpuSt2Number();
else if(expectedreturn==tk_word||expectedreturn==tk_int){
if(actualreturn==tk_char)cbw();
else if(actualreturn==tk_byte)xorAHAH();
}
break;
case tk_long:
case tk_dword:
switch(actualreturn){
case tk_char:
op66(r32);
op(0x0F); outword(0xC0BE); //MOVSX EAX,AL
break;
case tk_byte: /* MOVZX EAX,AL */
op66(r32);
op(0x0F); outword(0xC0B6);
break;
case tk_word: /* MOVZX EAX,AX */
op66(r32);
op(0x0F); outword(0xC0B7);
break;
case tk_int: /* MOVSX EAX,AX */
op66(r32);
op(0x0F); outword(0xC0BF);
break;
case tk_double:
case tk_fpust:
FpuSt2Number();
break;
// case tk_double:
case tk_float:
op66(r32);
op(0x50);
FloatToNumer(/*actualreturn==tk_float?0:4*/);
break;
}
if(cpu<3)cpu=3;
break;
case tk_qword:
switch(actualreturn){
case tk_char:
op66(r32);
op(0x0F); outword(0xC0BE); //MOVSX EAX,AL
cwdq(r32);
break;
case tk_byte: /* MOVZX EAX,AL */
op66(r32);
op(0x0F); outword(0xC0B6);
ZeroReg(EDX,r32);
break;
case tk_word: /* MOVZX EAX,AX */
op66(r32);
op(0x0F); outword(0xC0B7);
case tk_dword:
ZeroReg(EDX,r32);
break;
case tk_int: /* MOVSX EAX,AX */
op66(r32);
op(0x0F); outword(0xC0BF);
case tk_long:
cwdq(r32);
break;
case tk_fpust:
case tk_double:
FpuSt2QNumber();
break;
case tk_float:
op66(r32);
op(0x50);
FloatToNumer(actualreturn==tk_float?0:4);
cwdq(r32);
break;
}
if(cpu<3)cpu=3;
break;
case tk_fpust:
if(tok2==tk_semicolon)break;
switch(actualreturn){
case tk_char:
CheckInitBP();
cbw();
op66(r32);
outword(0xDF50); //push EAX
goto endfxld; //fild ss[bp-4]/[esp]
case tk_byte:
CheckInitBP();
xorAHAH();
op66(r32);
outword(0xDF50); //push EAX
goto endfxld; //fild ss[bp-4]/[esp]
case tk_word:
CheckInitBP();
op66(r16);
outword(0x6A); //push 0
op66(r16);
outword(0xDB50); //push AX
goto endfxld; //fild ss[bp-4]/[esp]
case tk_int:
CheckInitBP();
op66(r32);
outword(0xDF50); //push eax
goto endfxld; //fild ss[bp-4]/[esp]
case tk_dword:
CheckInitBP();
op66(r32); //push 0L
outword(0x6A);
op66(r32);
op(0x50); //push EAX
fildq_stack();
RestoreBP();
op66(r32);
op(0x58); //pop eax
op66(r32);
op(0x58); //pop eax
break;
case tk_long:
CheckInitBP();
op66(r32);
outword(0xDB50); //push EAX
goto endfxld; //fild ss[bp-4]/[esp]
case tk_float:
CheckInitBP();
op66(r32);
outword(0xd950); //push EAX
endfxld:
fld_stack(4+localsize);
RestoreBP();
op66(r32);
op(0x58); //pop eax
break;
case tk_qword:
// case tk_double:
CheckInitBP();
op66(r32);
op(0x50+EDX); //push EDX
op66(r32);
op(0x50); //push EAX
/* if(actualreturn==tk_double){
op(0xDD);
fld_stack(8+localsize);
}
else*/ fildq_stack();
RestoreBP();
op66(r32);
op(0x58); //pop eax
op66(r32);
op(0x58); //pop eax
break;
}
if(cpu<3)cpu=3;
break;
default:
// printf("expectedreturn=%d %s %d\n",expectedreturn,(startfileinfo+currentfileinfo)->filename,linenumber);
break;
}
}
int procdo(int expectedreturn)
{
int actualreturn;
char idflag=0;
switch(tok){
case tk_ID: idflag++;
case tk_id:
actualreturn=doid(idflag,expectedreturn);
break;
case tk_proc:
actualreturn=doanyproc();
break;
case tk_apiproc:
case tk_undefproc:
case tk_declare:
// if((actualreturn=doanyundefproc())==tk_void)actualreturn=expectedreturn;
actualreturn=doanyundefproc(); //17.09.05 17:56
break;
default: internalerror("Bad tok in procdo();"); break;
}
convert_returnvalue(expectedreturn,actualreturn);
return actualreturn;
}
/* +++++++++++++++++++++++ loops and ifs start ++++++++++++++++++++++++ */
void endcmpfloat()
{
fwait3();
outword(0xE0DF);//fstsw ax
op(0x9E);
RestoreBP();
}
int outcmp(int swapped,int ctok,ITOK *cstok,char *&cbuf,SINFO *cstr,int ctok2,ITOK *cstok2,char *&cbuf2,SINFO *cstr2,int typet)
{
unsigned char err=0;
int typef=0;
int vop=0;
long long lnumber;
unsigned int ofs;
int i,reg,reg1;
if(typet<r16)typet=r16;
switch(ctok){
case tk_reg64:
reg=cstok->number/256;
switch(ctok2){
case tk_reg64:
reg1=cstok2->number/256;
for(i=0;i<2;i++){
op66(r32);
op(0x39); //cmp reg,reg
op(0xC0+reg+reg1*8);
if(i==1)break;
outword(0x75);
ofs=outptr;
reg=cstok->number&255;
reg1=cstok2->number&255;
}
output[ofs-1]=outptr-ofs;
break;
case tk_number:
case tk_postnumber:
case tk_undefofs:
lnumber=cstok2->lnumber>>32;
for(i=0;i<2;i++){
op66(r32);
//ïðîâåðêà íà âîçìîæíîñòü áîëåå êîðîòêîãî êîäà
if((cstok2->flag&f_reloc)==0&&ctok2!=tk_postnumber&&ctok2!=tk_undefofs&&
short_ok(lnumber,TRUE)){
if(!lnumber){
op(0x85); //test reg,reg
op(0xc0+reg*9);
}
else{
op(0x83); //cmp reg,
op(0xF8+reg);
op(lnumber);
}
}
else{
if(reg==AX)op(0x3D);
else{
op(0x81);
op(0xF8+reg);
}
if(i==1){
if(ctok2==tk_postnumber)(cstok2->flag&f_extern)==0?setwordpost(cstok2):setwordext(&cstok2->number);
else if((cstok2->flag&f_reloc)!=0)AddReloc(cstok2->segm);
if(ctok2==tk_undefofs)AddUndefOff(2,cstok2->name);
}
outdword(cstok2->number);
}
if(i==1)break;
outword(0x75);
ofs=outptr;
reg=cstok->number&255;
}
output[ofs-1]=outptr-ofs;
break;
default:
if(swapped)err=1;
else return(outcmp(1,ctok2,cstok2,cbuf2,cstr2,ctok,cstok,cbuf,cstr,typet));
break;
}
break;
case tk_reg32:
case tk_reg:
switch(ctok2){
case tk_reg:
case tk_reg32:
if(ctok!=ctok2)err=1;
else{
op66(typet);
op(0x39); //cmp reg,reg
op(0xC0+(unsigned int)cstok->number+(unsigned int)cstok2->number*8);
}
break;
case tk_number:
if(cstok2->number==0&&(cstok2->flag&f_reloc)==0){
op66(typet);
op(0x85); //test reg,reg
op(0xc0+(unsigned int)cstok->number*9);
break;
}
case tk_postnumber:
case tk_undefofs:
op66(typet);
//ïðîâåðêà íà âîçìîæíîñòü áîëåå êîðîòêîãî êîäà
if((cstok2->flag&f_reloc)==0&&ctok2!=tk_postnumber&&ctok2!=tk_undefofs&&
short_ok(cstok2->number,ctok==tk_reg?FALSE:TRUE)){
op(0x83); //cmp reg,
op(0xF8+(unsigned int)cstok->number);
op(cstok2->number);
break;
}
if(cstok->number==AX)op(0x3D);
else{
op(0x81);
op(0xF8+(unsigned int)cstok->number);
}
if(ctok2==tk_postnumber)(cstok2->flag&f_extern)==0?setwordpost(cstok2):setwordext(&cstok2->number);
else if((cstok2->flag&f_reloc)!=0)AddReloc(cstok2->segm);
if(ctok2==tk_undefofs)AddUndefOff(2,cstok2->name);
if(ctok==tk_reg)outword((unsigned int)cstok2->number);
else outdword(cstok2->number);
break;
default:
if(swapped)err=1;
else return(outcmp(1,ctok2,cstok2,cbuf2,cstr2,ctok,cstok,cbuf,cstr,typet));
break;
}
break;
case tk_qwordvar:
cstok->number+=4;
compressoffset(cstok);
switch(ctok2){
case tk_postnumber:
case tk_number:
case tk_undefofs:
lnumber=cstok2->lnumber>>32;
CheckAllMassiv(cbuf,8,cstr,cstok);
for(i=0;i<2;i++){
op66(r32);
outseg(cstok,2);
//ïðîâåðêà íà âîçìîæíîñòü áîëåå êîðîòêîãî êîäà
if((cstok2->flag&f_reloc)==0&&ctok2!=tk_postnumber&&ctok2!=tk_undefofs&&
short_ok(lnumber,1)){
op(0x83);
op(0x38+cstok->rm);
outaddress(cstok);
op(lnumber);
}
else{
op(0x81);
op(0x38+cstok->rm);
outaddress(cstok);
if(i==1){
if(ctok2==tk_postnumber)(cstok2->flag&f_extern)==0?setwordpost(cstok2):setwordext(&cstok2->number);
else if((cstok2->flag&f_reloc)!=0)AddReloc(cstok2->segm);
if(ctok2==tk_undefofs)AddUndefOff(2,cstok2->name);
}
outdword(lnumber);
}
if(i==1)break;
outword(0x75);
ofs=outptr;
cstok->number-=4;
compressoffset(cstok);
lnumber=cstok2->lnumber;
}
output[ofs-1]=outptr-ofs;
break;
case tk_reg64:
CheckAllMassiv(cbuf,8,cstr,cstok);
reg=cstok2->number/256;
for(i=0;i<2;i++){
op66(r32);
outseg(cstok,2);
op(0x39); /* CMP [word],AX */
op(cstok->rm+reg*8);
outaddress(cstok);
if(i==1)break;
reg=cstok2->number&255;
outword(0x75);
ofs=outptr;
cstok->number-=4;
compressoffset(cstok);
}
output[ofs-1]=outptr-ofs;
break;
default:
i=EAX|(EDX*256);
getintoreg64(i);
doregmath64(i);
CheckAllMassiv(cbuf,8,cstr,cstok);
reg=EDX;
for(i=0;i<2;i++){
op66(r32);
outseg(cstok,2);
op(0x39); /* CMP [word],AX */
op(cstok->rm+reg*8);
outaddress(cstok);
if(i==1)break;
reg=EAX;
outword(0x75);
ofs=outptr;
cstok->number-=4;
compressoffset(cstok);
}
output[ofs-1]=outptr-ofs;
break;
}
break;
case tk_intvar:
case tk_wordvar:
if(swapped&&typet==r32)typet=r16;
case tk_longvar:
case tk_dwordvar:
switch(ctok2){
case tk_reg32:
case tk_reg:
CheckAllMassiv(cbuf,typet,cstr,cstok);
op66(typet);
outseg(cstok,2);
op(0x39);
op((unsigned int)cstok2->number*8+cstok->rm);
outaddress(cstok);
break;
case tk_postnumber:
case tk_number:
case tk_undefofs:
CheckAllMassiv(cbuf,typet,cstr,cstok);
op66(typet);
outseg(cstok,2);
//ïðîâåðêà íà âîçìîæíîñòü áîëåå êîðîòêîãî êîäà
if((cstok2->flag&f_reloc)==0&&ctok2!=tk_postnumber&&ctok2!=tk_undefofs&&
short_ok(cstok2->number,typet/2-1)){
op(0x83);
op(0x38+cstok->rm);
outaddress(cstok);
op(cstok2->number);
break;
}
op(0x81);
op(0x38+cstok->rm);
outaddress(cstok);
if(ctok2==tk_postnumber)(cstok2->flag&f_extern)==0?setwordpost(cstok2):setwordext(&cstok2->number);
else if((cstok2->flag&f_reloc)!=0)AddReloc(cstok2->segm);
if(ctok2==tk_undefofs)AddUndefOff(2,cstok2->name);
if(typet==r16)outword((unsigned int)cstok2->number);
else outdword(cstok2->number);
break;
case tk_charvar:
case tk_intvar:
getinto_e_ax(1,ctok2,cstok2,cbuf2,cstr2,typet);
CheckAllMassiv(cbuf,typet,cstr,cstok);
op66(typet);
outseg(cstok,2);
op(0x39); /* CMP [word],AX */
op(cstok->rm);
outaddress(cstok);
break;
default:
getinto_e_ax(0,ctok2,cstok2,cbuf2,cstr2,typet);
// ClearReg(AX);
CheckAllMassiv(cbuf,typet,cstr,cstok);
op66(typet);
outseg(cstok,2);
op(0x39); /* CMP [word],AX */
op(cstok->rm);
outaddress(cstok);
break;
}
break;
case tk_number:
if(ctok2==tk_postnumber){
op(0xB8); /* MOV AX,# */
if((cstok->flag&f_reloc)!=0)AddReloc(cstok->segm);
if(am32==FALSE)outword((unsigned int)cstok->number);
else outdword(cstok->number);
op(0x3D); /* CMP AX,# */
(cstok2->flag&f_extern)==0?setwordpost(cstok2):setwordext(&cstok2->number);
if(am32==FALSE)outword((unsigned int)cstok2->number);
else outdword(cstok2->number);
}
if(ctok2==tk_number){
if(cstok2->rm!=tk_float&&cstok->rm!=tk_float){
if((unsigned long)cstok2->number<256&&(unsigned long)cstok->number<256){
op(0xB0); //mov al,number
op(cstok->number);
op(0x3C); //cmp Al,number
op(cstok2->number);
}
else if((unsigned long)cstok2->number<65536&& cstok->number<65536){
op66(r16);
op(0xB8); /* MOV AX,# */
if((cstok->flag&f_reloc)!=0)AddReloc(cstok->segm);
outword((unsigned int)cstok->number);
op66(r16);
op(0x3D); /* CMP AX,# */
if((cstok2->flag&f_reloc)!=0)AddReloc(cstok2->segm);
outword((unsigned int)cstok2->number);
}
else{
op66(r32);
op(0xB8); /* MOV AX,# */
if((cstok->flag&f_reloc)!=0)AddReloc(cstok->segm);
outdword(cstok->number);
op66(r32);
op(0x3D); /* CMP AX,# */
if((cstok2->flag&f_reloc)!=0)AddReloc(cstok2->segm);
outdword(cstok2->number);
}
}
else{
op(0x55); //push bp
outword(0xe589);//mov bp,sp
op66(r32);
if(short_ok(cstok->number,TRUE)){ //push num
op(0x6A);
op(cstok->number);
}
else{
op(0x68);
outdword(cstok->number);
}
op66(r32);
if(short_ok(cstok2->number,TRUE)){ //push num
op(0x6A);
op(cstok2->number);
}
else{
op(0x68);
outdword(cstok2->number);
}
outword(am32==FALSE?0x46d9:0x45d9);
op(0xfC);//fld ssdword[bp-4]
op(0xD8);
outword(0xF85e - am32); //fcomp [bp-8]
endcmpfloat();
}
}
else{
if(swapped)err=1;
else return(outcmp(1,ctok2,cstok2,cbuf2,cstr2,ctok,cstok,cbuf,cstr,typet));
}
break;
case tk_postnumber:
if(ctok2==tk_number||ctok2==tk_postnumber){
op(0xB8); /* MOV AX,# */
(cstok->flag&f_extern)==0?setwordpost(cstok):setwordext(&cstok->number);
if(am32==FALSE)outword((unsigned int)cstok->number);
else outdword(cstok->number);
op(0x3D); /* CMP AX,# */
if(ctok2==tk_postnumber)(cstok2->flag&f_extern)==0?setwordpost(cstok2):setwordext(&cstok2->number);
else if((cstok2->flag&f_reloc)!=0)AddReloc(cstok2->segm);
if(am32==FALSE)outword((unsigned int)cstok2->number);
else outdword(cstok2->number);
}
else{
if(swapped)err=1;
else return(outcmp(1,ctok2,cstok2,cbuf2,cstr2,ctok,cstok,cbuf,cstr,typet));
}
break;
case tk_charvar:
case tk_bytevar:
switch(ctok2){
case tk_number:
CheckAllMassiv(cbuf,1,cstr,cstok);
outseg(cstok,2);
op(0x80); /* CMP [byte],# */
op(0x38+cstok->rm);
outaddress(cstok);
op((unsigned int)cstok2->number);
break;
case tk_reg:
case tk_reg32:
if(cstok2->number>3)goto defchar;
case tk_beg:
CheckAllMassiv(cbuf,1,cstr,cstok);
outseg(cstok,2);
op(0x38); /* CMP [byte],beg */
op((unsigned int)cstok2->number*8+cstok->rm);
outaddress(cstok);
break;
default:
defchar:
getintoal(ctok2,cstok2,cbuf2,cstr2);
CheckAllMassiv(cbuf,1,cstr,cstok);
outseg(cstok,2);
op(0x38); /* CMP [byte],AL */
op(cstok->rm);
outaddress(cstok);
break;
}
break;
case tk_beg:
switch(ctok2){
case tk_number:
if(cstok2->number==0){
op(0x84); //test beg,beg
op(0xc0+(unsigned int)cstok->number*9);
break;
}
if((unsigned int)cstok->number==AL)op(0x3C);
else{
op(0x80);
op(0xF8+(unsigned int)cstok->number);
}
op((unsigned int)cstok2->number);
break;
case tk_beg:
op(0x38);
op(0xC0+(unsigned int)cstok->number+(unsigned int)cstok2->number*8);
break;
case tk_reg:
if((unsigned int)cstok2->number<=BX){ /* CMP beg,beg */
op(0x38);
op(0xC0+(unsigned int)cstok->number+(unsigned int)cstok2->number*8);
}
else{
op66(r16);
op(0x89); /* MOV AX,reg */
op(0xC0+(unsigned int)cstok2->number*8);
op(0x38); /* CMP beg,AL */
op(0xC0+(unsigned int)cstok->number);
}
break;
default:
if(swapped)err=1;
else return(outcmp(1,ctok2,cstok2,cbuf2,cstr2,ctok,cstok,cbuf,cstr,typet));
break;
}
break;
case tk_doublevar:
vop=4;
goto cont_float;
case tk_fpust:
typef++;
if(cstok->type==tp_modif)typef++;
else{
if(cstok->number!=0){
op(0xd9); //fld st(x)
op(0xC0+cstok->number);
typef++;
}
}
case tk_floatvar:
cont_float:
switch(ctok2){
case tk_beg:
CheckInitBP();
switch(cstok2->rm){
case tk_char:
case tk_int:
case tk_long:
outword(0xBE0F); /* MOVSX AX,beg */
op(0xC0+(unsigned int)cstok2->number);
break;
default:
if((optimizespeed&&chip>3&&chip<7)||cstok2->number==AL){
xorAHAH();
if(cstok2->number!=AL){
op(0x88);
op(0xC0+cstok2->number*8); //mov al,beg
}
}
else{
outword(0xB60F); // MOVZX AX,beg
op(0xC0+(unsigned int)cstok2->number);
}
break;
}
outword(0xDF50); //push AX
fld_stack(2+localsize);
if(typef==2)outword(0xD9DE); //FCOMPP
else if(typef==1)outword(0xD9D8); //FCOMP
else{
if(ESPloc&&am32&&cstok->segm==SS)cstok->number+=4;
CheckAllMassiv(cbuf,4+vop,cstr,cstok);
outseg(cstok,2); //fcomp var
op(0xd8+vop);
op(cstok->rm+0x18);
outaddress(cstok);
}
op(0x58); // pop EAX
endcmpfloat();
swapped=1;
break;
case tk_reg:
CheckInitBP();
op66(r32);
switch(cstok2->rm){
case tk_char:
case tk_int:
case tk_long:
outword(0xBF0F); /* MOVSX EAX,reg */
break;
default:
if(optimizespeed&&chip>3&&chip<7&&cstok2->number!=AX){
outword(0xC031); // xor EAX,EAX
op66(r16);
op(0x8B);
}
else outword(0xB70F); // MOVZX EAX,reg
break;
}
op(0xC0+(unsigned int)cstok2->number);
op66(r32);
outword(0xDB50); //push EAX
fld_stack(4+localsize);
if(typef==2)outword(0xD9DE); //FCOMPP
else if(typef==1)outword(0xD9D8); //FCOMP
else{
if(ESPloc&&am32&&cstok->segm==SS)cstok->number+=4;
CheckAllMassiv(cbuf,4+vop,cstr,cstok);
outseg(cstok,2); //fcomp var
op(0xd8+vop);
op(cstok->rm+0x18);
outaddress(cstok);
}
op66(r32);
op(0x58); // pop EAX
endcmpfloat();
swapped=1;
break;
case tk_reg32:
CheckInitBP();
if(cstok2->rm==tk_float){
op66(r32);
op(0x50+(unsigned int)cstok2->number); //push reg32
op(0xd9);
fld_stack(4+localsize);
if(typef==2)outword(0xD9DE); //FCOMPP
else if(typef==1)outword(0xD9D8); //FCOMP
else{
if(ESPloc&&am32&&cstok->segm==SS)cstok->number+=4;
CheckAllMassiv(cbuf,4+vop,cstr,cstok);
outseg(cstok,2); //fcomp var
op(0xd8+vop);
op(cstok->rm+0x18);
outaddress(cstok);
}
op66(r32);
op(0x58); // pop EAX
}
else{
if(cstok2->rm!=tk_char&&cstok2->rm!=tk_int&&cstok2->rm!=tk_long){
typet=tk_word;
op66(r32);
outword(0x6a); //$push 0
if(ESPloc&&am32&&cstok->segm==SS)cstok->number+=4;
}
op66(r32);
op(0x50+cstok2->number); //push reg32
if(typet!=r16)fildq_stack();
else{
op(0xdb);
fld_stack(4+localsize);
}
if(typef==2)outword(0xD9DE); //FCOMPP
else if(typef==1)outword(0xD9D8); //FCOMP
else{
if(ESPloc&&am32&&cstok->segm==SS)cstok->number+=4;
CheckAllMassiv(cbuf,4+vop,cstr,cstok);
outseg(cstok,2); //fcomp var
op(0xd8+vop);
op(cstok->rm+0x18);
outaddress(cstok);
}
if(typet!=r16){
if(optimizespeed||am32==FALSE){
outword(0xC483);
op(8);
}
else{
op(0x58); // pop EAX
op(0x58); // pop EAX
}
}
else{
op66(r32);
op(0x58); // pop EAX
}
}
endcmpfloat();
swapped=1;
break;
case tk_charvar:
CheckAllMassiv(cbuf2,1,cstr2,cstok2);
outseg(cstok2,3); /* MOVSX AX,[charvar] */
outword(0xBE0F); op(cstok2->rm);
outaddress(cstok2);
CheckInitBP();
outword(0xdf50); //push ax
fld_stack(2+localsize);
if(typef==2)outword(0xD9DE); //FCOMPP
else if(typef==1)outword(0xD9D8); //FCOMP
else{
if(ESPloc&&am32&&cstok->segm==SS)cstok->number+=4;
CheckAllMassiv(cbuf,4+vop,cstr,cstok);
outseg(cstok,2); //fcomp var
op(0xd8+vop);
op(cstok->rm+0x18);
outaddress(cstok);
}
op(0x58); // pop EAX
endcmpfloat();
swapped=1;
break;
case tk_intvar:
CheckAllMassiv(cbuf2,2,cstr2,cstok2);
outseg(cstok2,2);
if(typef){
op(0xDE); //ficomp var2
op(cstok2->rm+0x08+typef*8);
outaddress(cstok2);
}
else{
op(0xdf); //fild var
op(cstok2->rm);
outaddress(cstok2);
CheckAllMassiv(cbuf,4+vop,cstr,cstok);
outseg(cstok,2); //fcomp var
op(0xd8+vop);
op(cstok->rm+0x18);
outaddress(cstok);
swapped=1;
}
fwait3_4();
outword(0xE0DF);//fstsw ax
op(0x9E);
break;
case tk_bytevar:
CheckAllMassiv(cbuf2,1,cstr2,cstok2);
if(optimizespeed&&chip>3&&chip<7){
outword(0xC031);
outseg(cstok2,2);
op(0x8A);
}
else{
outseg(cstok2,3);
outword(0xB60F);
}
op(cstok2->rm); // MOVZX regL,[byte]
outaddress(cstok2);
CheckInitBP();
outword(0xDF50); //push ax
fld_stack(2+localsize);
if(typef==2)outword(0xD9DE); //FCOMPP
else if(typef==1)outword(0xD9D8); //FCOMP
else{
if(ESPloc&&am32&&cstok->segm==SS)cstok->number+=4;
CheckAllMassiv(cbuf,4+vop,cstr,cstok);
outseg(cstok,2); //fcomp var
op(0xd8+vop);
op(cstok->rm+0x18);
outaddress(cstok);
}
op(0x58); // pop EAX
endcmpfloat();
swapped=1;
break;
case tk_wordvar:
CheckInitBP();
op66(r16);
outword(0x6a); //push 0
CheckAllMassiv(cbuf2,2,cstr2,cstok2);
op66(r16);
outseg(cstok2,2); //push var
op(0xFF);
op(cstok2->rm+0x30);
outaddress(cstok2);
op(0xDB);
fld_stack(4+localsize);
if(typef==2)outword(0xD9DE); //FCOMPP
else if(typef==1)outword(0xD9D8); //FCOMP
else{
if(ESPloc&&am32&&cstok->segm==SS)cstok->number+=4;
CheckAllMassiv(cbuf,4+vop,cstr,cstok);
outseg(cstok,2); //fcomp var
op(0xd8+vop);
op(cstok->rm+0x18);
outaddress(cstok);
}
op66(r32);
op(0x58); // pop EAX
endcmpfloat();
swapped=1;
break;
case tk_dwordvar:
CheckInitBP();
op66(r32); //push 0L
outword(0x6a);
CheckAllMassiv(cbuf2,4,cstr2,cstok2);
op66(r32); //push var
outseg(cstok2,2);
op(0xFF);
op(cstok2->rm+0x30);
outaddress(cstok2);
fildq_stack();
if(typef==2)outword(0xD9DE); //FCOMPP
else if(typef==1)outword(0xD9D8); //FCOMP
else{
if(ESPloc&&am32&&cstok->segm==SS)cstok->number+=8;
CheckAllMassiv(cbuf,4+vop,cstr,cstok);
outseg(cstok,2); //fcomp var
op(0xd8+vop);
op(cstok->rm+0x18);
outaddress(cstok);
}
if(optimizespeed||am32==FALSE){
outword(0xC483);
op(8);
}
else{
op(0x58); // pop EAX
op(0x58); // pop EAX
}
endcmpfloat();
swapped=1;
break;
case tk_longvar:
CheckAllMassiv(cbuf2,4,cstr2,cstok2);
outseg(cstok2,2);
if(typef){
op(0xDA); //ficomp var2
op(cstok2->rm+0x08+typef*8);
outaddress(cstok2);
}
else{
op(0xdb); //fild var
op(cstok2->rm);
outaddress(cstok2);
CheckAllMassiv(cbuf,4+vop,cstr,cstok);
outseg(cstok,2); //fcomp var
op(0xd8+vop);
op(cstok->rm+0x18);
outaddress(cstok);
swapped=1;
}
endcmpfloat();
break;
case tk_number:
if(!typef){
CheckAllMassiv(cbuf,4,cstr,cstok);
outseg(cstok,2); //fld val
op(0xd9);
op(cstok->rm);
outaddress(cstok);
}
if(cstok2->rm!=tk_double&&cstok2->rm!=tk_float){
cstok2->dnumber=cstok2->lnumber;
cstok2->rm=tk_double;
}
else if(vop==4&&cstok2->rm==tk_float){
cstok2->dnumber=cstok2->fnumber;
cstok2->rm=tk_double;
}
if(am32&&(cstok2->rm==tk_float&&cstok2->fnumber==0.0)||
(cstok2->rm==tk_double&&cstok2->dnumber==0.0)||cstok2->lnumber==0){
outword(0xe4d9); //ftst
if(typef!=1)outword(0xC0DD); //ffree
}
else{
op66(r32);
int rm;
rm=(am32==FALSE?0x1eD8:0x1DD8);
if(typef==1)rm-=0x800;
if(cstok2->rm==tk_double||vop==4)rm+=4;
outword(rm); //fcom(p)
AddFloatConst(cstok2->lnumber,cstok2->rm);
outword(0);
if(am32)outword(0);
}
endcmpfloat();
break;
case tk_floatvar:
if(!typef){
CheckAllMassiv(cbuf,4+vop,cstr,cstok);
outseg(cstok,2); //fld val
op(0xd9+vop);
op(cstok->rm);
outaddress(cstok);
}
CheckAllMassiv(cbuf2,4,cstr2,cstok2);
outseg(cstok2,2); //fcomp var
op(0xd8);
op(cstok2->rm+(typef==1?0x10:0x18));
outaddress(cstok2);
endcmpfloat();
break;
case tk_doublevar:
if(!typef){
CheckAllMassiv(cbuf,4+vop,cstr,cstok);
outseg(cstok,2); //fld val
op(0xd9+vop);
op(cstok->rm);
outaddress(cstok);
}
CheckAllMassiv(cbuf2,8,cstr2,cstok2);
outseg(cstok2,2); //fcomp var
op(0xd8+4);
op(cstok2->rm+(typef==1?0x10:0x18));
outaddress(cstok2);
endcmpfloat();
break;
case tk_fpust:
if(typef==2){ //fcomp
if(chip>=7){ //fcomip
op(0xDF);
op(0xF0+cstok2->number+1);
swapped=1;
break;
}
op(0xD8);
op(0xD8+cstok2->number+1);
}
else if(typef==1){ //fcom
if(chip>=7){ //fcomi
op(0xDB);
op(0xF0+cstok2->number);
swapped=1;
break;
}
op(0xD8);
op(0xD0+cstok2->number);
}
else{
if(cstok2->type!=tp_modif){
op(0xd9); //fld st(x)
op(0xC0+cstok2->number);
}
CheckAllMassiv(cbuf,4+vop,cstr,cstok);
outseg(cstok,2); //fcomp var
op(0xd8+vop);
op(cstok->rm+0x18);
outaddress(cstok);
}
endcmpfloat();
swapped=1;
break;
default:
err=1;
break;
}
break;
default: err=1; break;
}
if(err)preerror("unable to create comparison, check restrictions");
return(swapped);
}
int CheckCompareTok(int reg)
{
int comparetok=tk_equalto;
if(itok.type==tp_compare)comparetok=tok;
else unknowncompop();
getoperand(reg);
return comparetok;
}
int typenumber(int vtok)
{
switch(vtok){
case tk_char:
case tk_beg:
case tk_byte:
return tk_byte;
case tk_int:
case tk_reg:
case tk_word:
return tk_word;
case tk_reg64:
case tk_qword:
return tk_qword;
case tk_floatvar:
case tk_float:
return tk_float;
case tk_doublevar:
case tk_double:
return tk_double;
}
return tk_dword;
}
#ifdef OPTVARCONST
int constructcompare(int invertflag,unsigned int startloc,LVIC *comconst)
#else
int constructcompare(int invertflag,unsigned int startloc)
#endif
/* build cmp for IF, if and do {} while */
{
int comparetok=0,jumptype,vartype=tokens,notflag=FALSE;
int ittok,ittok2=tokens,type2=tokens;//,retcompare=tokens;
int razr=r_undef;
char *ibuf,*ibuf2;
ITOK htok,htok2;
SINFO hstr,hstr2;
int preg=(am32==TRUE?EAX:SI);
int use_cxz=0;
char *ofsstr=NULL,*ofsstr2=NULL;
int usereg=-1;
int usereg2=-1;
//////04.10.04 13:45
int bracket=0;
unsigned char oinline=useinline;
useinline=0;
do{
nexttok();
// printf("tok=%d tok2=%d\n",tok,tok2);
if(tok==tk_openbracket)bracket++;
if(tok==tk_not)notflag=(notflag+1)%2;
}while(tok2==tk_openbracket||tok2==tk_not);
if(bracket==0)expected('(');
/////////////////
setzeroflag=FALSE;
ofsstr=GetLecsem(tk_closebracket,tk_eof,tp_compare);
getoperand(); //NEW 04.10.04 13:45
if(tok==tk_openbracket){
bracket++;
getoperand();
}
if(tok==tk_not){
notflag=(notflag+1)%2;
getoperand();
}
switch(tok){
case tk_closebracket:
useinline=oinline;
getoperand();
return voidcompr;
case tk_asm:
if(tok2==tk_openbrace){
nexttok();
type2=tok;
}
case tk_dollar:
nexttok();
case tk_idasm:
if(stricmp(itok.name,"test")==0){
if(iTest(1)==FALSE)InvOperComp();
ittok=0x75;
if(type2==tk_openbrace)expecting(tk_closebrace);
goto endcomp;
}
else preerror("Only 'TEST' possible use in compare");
break;
case tk_qword:
case tk_double:
razr+=4;
case tk_beg:
case tk_reg32:
case tk_reg: vartype=tok; break;
case tk_float:
case tk_long:
case tk_dword:
razr+=2;
case tk_int:
case tk_word:
razr++;
case tk_char:
case tk_byte:
razr++;
vartype=tok;
getoperand();
if(tok==tk_closebracket&&bracket>1){
bracket--;
getoperand();
}
break;
case tk_undefproc:
case tk_declare:
// if(itok.rm==tk_void)itok.rm=(am32==FALSE?tk_word:tk_dword);
case tk_proc:
case tk_apiproc:
vartype=itok.rm;
if(vartype==tokens)vartype=(am32==FALSE?tk_word:tk_dword);
else if(vartype==tk_void&&(itok.flag&f_retproc)==0){
retvoid();
vartype=itok.rm=(am32==FALSE?tk_word:tk_dword);
}
if(ofsstr){
free(ofsstr);
ofsstr=NULL;
}
break;
case tk_bytevar: vartype=tk_byte; break;
case tk_charvar: vartype=tk_char; break;
case tk_intvar: vartype=tk_int; break;
case tk_wordvar: vartype=tk_word; break;
case tk_dwordvar: vartype=tk_dword; break;
case tk_longvar: vartype=tk_long; break;
case tk_floatvar: vartype=tk_float; break;
case tk_qwordvar: vartype=tk_qword; break;
case tk_fpust:
case tk_doublevar: vartype=tk_double; break;
case tk_bits:
int i;
i=itok.bit.ofs+itok.bit.siz;
if(i<=64){
vartype=tk_dword;
razr=r64;
}
if(i<=32){
vartype=tk_dword;
razr=r32;
}
if(i<=16){
vartype=tk_word;
razr=r16;
}
if(i<=8){
vartype=tk_byte;
razr=r8;
}
break;
case tk_at:
if(ofsstr){
free(ofsstr);
ofsstr=NULL;
}
nexttok();
if(itok.flag&f_retproc){
comparetok=(itok.flag&f_retproc)/256+tk_overflowflag-1;
// notflag=(notflag==FALSE?TRUE:FALSE);
vartype=tk_ID;
ittok2=macros(vartype);
if(tok2==tk_closebracket){
nexttok();
ittok=0x70+comparetok-tk_overflowflag;
goto endcomp;
}
if(ittok2==0){
vartype=itok.rm;
break;
}
goto mac1;
}
if((itok.flag&f_typeproc)==tp_fastcall&&itok.segm!=NOT_DYNAMIC)vartype=itok.rm;
else vartype=tk_ID;
if((ittok2=macros(vartype))==0){
vartype=itok.rm;
break;
}
mac1:
vartype=ittok2;
switch(vartype){
case tk_byte:
case tk_char: tok=tk_beg; break;
case tk_int:
case tk_word: tok=tk_reg; break;
case tk_float:
case tk_dword:
case tk_long: tok=tk_reg32; break;
case tk_double:
case tk_qword: tok=tk_reg64; break;
default:
preerror("Macro has a return type of void");
tok=tk_reg;
vartype=tk_word;
break;
}
itok.number=AX; // or AL or EAX
break;
default:
if((tok>=tk_overflowflag)&&(tok<=tk_plusflag)){
ittok=0x70+tok-tk_overflowflag;
nexttok();
if(tok!=tk_closebracket&&(tok==tk_oror||tok==tk_andand||tok==tk_notequal||tok==tk_equalto)){
int oper;
int oper2;
oper=tok;
nexttok();
ittok^=notflag;
notflag=0;
if(tok==tk_not){
notflag=TRUE;
nexttok();
}
if((tok>=tk_overflowflag)&&(tok<=tk_plusflag)){
ittok-=0x70;
ittok2=tok-tk_overflowflag;
ittok2^=notflag;
notflag=0;
nexttok();
switch(oper){
case tk_oror:
if((ittok==2&&ittok2==4)||(ittok==4&&ittok2==2))ittok=6;
else if(ittok==4&&(ittok2==8||ittok2==0))ittok=(ittok|ittok2)+1;
else unknowncompop();
break;
case tk_andand:
if((ittok==3&&ittok2==5)||(ittok==5&&ittok2==3))ittok=7;
else if(ittok==5&&(ittok2==8||ittok2==0))ittok=(ittok|ittok2)+1;
else unknowncompop();
break;
case tk_notequal:
if((ittok==8&&ittok2==0)||(ittok==0&&ittok2==8))ittok=12;
else unknowncompop();
break;
case tk_equalto:
if((ittok==8&&ittok2==0)||(ittok==0&&ittok2==8))ittok=13;
else unknowncompop();
break;
}
if(tok!=tk_closebracket&&(tok==tk_notequal||tok==tk_equalto)){
oper2=tok;
nexttok();
if(tok==tk_not){
notflag=TRUE;
nexttok();
}
if((tok>=tk_overflowflag)&&(tok<=tk_plusflag)){
ittok2=tok-tk_overflowflag;
ittok2^=notflag;
notflag=0;
nexttok();
if(oper2==tk_notequal){
if(oper==tk_oror&&((ittok==5&&ittok2==8)||(ittok==13&&ittok2==0)))ittok=14;
else unknowncompop();
}
else{
if(oper==tk_andand&&((ittok==6&&ittok2==8)||(ittok==14&&ittok2==0)))ittok=15;
else unknowncompop();
}
}
else unknowncompop();
}
}
else unknowncompop();
ittok+=0x70;
}
goto endcomp;
}
vartype=(am32==FALSE?tk_word:tk_dword);
break;
}
CheckMinusNum();
if(itok2.type!=tp_compare&&tok2!=tk_closebracket){ //ñëîæíûé îïåðàíä
if(ofsstr){
int retreg;
razr=getrazr(vartype);
if((retreg=CheckIDZReg(ofsstr,AX,razr))!=NOINREG){
GetEndLex(tk_closebracket,tk_semicolon,tp_compare);
nexttok();
if(razr==r16)ittok=tk_reg;
else if(razr==r32)ittok=tk_reg32;
else ittok=tk_beg;
usereg=htok.number=retreg==SKIPREG?AX:retreg;
goto nn1;
}
}
comparetok=0;//èñïîëüçóåòñÿ âðåìåííî íå ïîñìûñëó
ittok=tok;
htok=itok;
ibuf=NULL;
hstr.bufstr=NULL;
ittok2=tok2;
preg=BX;
switch(tok2){
case tk_assign:
case tk_plusplus:
case tk_minusminus:
case tk_divequals:
case tk_minusequals:
case tk_multequals:
case tk_plusequals:
switch(tok){
case tk_charvar: comparetok=1;
case tk_bytevar:
if((comparetok=dobytevar(comparetok,0))==tk_reg||comparetok==tk_beg){
usereg=htok.number=AX;
ittok=tk_beg;
}
break;
case tk_intvar: comparetok=1;
case tk_wordvar:
if((comparetok=do_d_wordvar(comparetok,r16,0))==tk_reg){
usereg=htok.number=AX;
ittok=tk_reg;
}
break;
case tk_longvar: comparetok=1;
case tk_dwordvar:
if((comparetok=do_d_wordvar(comparetok,r32,0))==tk_reg32){
usereg=htok.number=AX;
ittok=tk_reg32;
}
break;
case tk_floatvar:
if(dofloatvar(0,tk_fpust,0)==tk_fpust){
ittok=tk_fpust;
htok.type=tp_modif;
}
break;
case tk_qwordvar:
if((comparetok=doqwordvar(0))==tk_reg64){
ittok=tk_reg64;
usereg=htok.number=EAX|(EDX*256);
}
break;
case tk_reg64:
usereg=itok.number;
getintoreg64(itok.number);
doregmath64(itok.number);
comparetok=tk_reg64;
break;
case tk_reg32:
usereg=itok.number;
comparetok=doreg_32((unsigned int)itok.number,r32,0);
// printf("comparetok=%d\n",comparetok);
break;
case tk_reg:
usereg=itok.number;
comparetok=doreg_32((unsigned int)itok.number,r16,0);
break;
case tk_beg:
usereg=itok.number;
comparetok=dobeg((unsigned int)itok.number,0);
break;
default: InvOperComp(); break;
}
if(ittok<tk_floatvar&&(!(comparetok>=tk_overflowflag&&comparetok<=tk_plusflag))){
if(ittok2!=tk_assign&&ittok2!=tk_divequals&&ittok2!=tk_multequals){
if(tok==tk_closebracket){
ittok=0x75;
goto endcomp;
}
if(tok2==tk_number&&itok2.number==0){
if((ittok2==tk_plusplus||ittok2==tk_minusminus)&&
tok!=tk_notequal&&tok!=tk_equalto)break;
comparetok=CheckCompareTok(BX);
nexttok();
goto createopcode;
}
}
}
break;
default:
switch(vartype){
case tk_int: comparetok=do_e_axmath(1,r16,&ofsstr); ittok=tk_reg; break;
case tk_reg:
case tk_word: comparetok=do_e_axmath(0,r16,&ofsstr); ittok=tk_reg; break;
case tk_char: comparetok=doalmath(1,&ofsstr); ittok=tk_beg; break;
case tk_beg:
case tk_byte: comparetok=doalmath(0,&ofsstr); ittok=tk_beg; break;
case tk_long: comparetok=do_e_axmath(1,r32,&ofsstr); ittok=tk_reg32; break;
case tk_reg32:
case tk_dword:
comparetok=do_e_axmath(0,r32,&ofsstr);
ittok=tk_reg32;
break;
case tk_qword:
usereg=htok.number=EAX|(EDX*256);
getintoreg64(usereg);
doregmath64(usereg);
comparetok=ittok=tk_reg64;
break;
case tk_float:
doeaxfloatmath(tk_fpust);
ittok=tk_fpust;
htok.type=tp_modif;
break;
default:
if(itok.flag&f_retproc){
comparetok=(itok.flag&f_retproc)/256+tk_overflowflag-1;
// printf("tok=%d flag=%08X comparetok=%u %s\n",tok,itok.flag,comparetok,itok.name);
// notflag=(notflag==FALSE?TRUE:FALSE);
switch(tok){
case tk_undefproc:
case tk_declare:
case tk_apiproc:
doanyundefproc();
break;
case tk_proc:
doanyproc();
break;
}
nexttok();
if(tok!=tk_closebracket){
retvoid();
do{
nexttok();
}while(tok!=tk_closebracket);
}
}
else{
internalerror("Bad vartype value in constructcompare();");
tok=tk_reg; break;
}
}
if(ittok!=tk_reg64)usereg=htok.number=AX; // same value as AL and EAX
}
RestoreStack();
}
else{
#ifdef OPTVARCONST
CheckConstVar3(&tok,&itok,razr);
#endif
if(tok>=tk_charvar&&tok<=tk_doublevar){
switch(vartype){
case tk_int: tok=tk_intvar; break;
case tk_word: tok=tk_wordvar; break;
case tk_char: tok=tk_charvar; break;
case tk_byte: tok=tk_bytevar; break;
case tk_long: tok=tk_longvar; break;
case tk_dword: tok=tk_dwordvar; break;
case tk_float: tok=tk_floatvar; break;
case tk_qword: tok=tk_qwordvar; break;
case tk_double: tok=tk_doublevar; break;
}
}
else if(tok==tk_number){
if(tok2==tk_closebracket){
invertflag=(itok.number==0?zerocompr:voidcompr);
nexttok();
getoperand();
useinline=oinline;
return invertflag;
}
if(itok.rm==tk_float)vartype=tk_float;
}
else if(tok==tk_bits){
bits2reg(AX,razr);
switch(razr){
case r64:
case r32:
tok=tk_reg32;
break;
case r16:
tok=tk_reg;
break;
case r8:
tok=tk_beg;
break;
}
itok.number=0;
}
if(tok==tk_beg||tok==tk_reg||tok==tk_reg32)itok.rm=vartype; //òèï ñîäåðæèìîãî â reg32
ittok=tok;
htok=itok;
ibuf=bufrm;
bufrm=NULL;
hstr=strinf;
strinf.bufstr=NULL;
nexttok();
}
nn1:
if(razr==r_undef){
switch(vartype){
case tk_qword:
case tk_double:
razr+=4;
case tk_long:
case tk_dword:
case tk_float:
case tk_reg32:
razr+=2;
case tk_int:
case tk_word:
case tk_reg:
razr++;
case tk_char:
case tk_byte:
case tk_beg:
razr++;
}
}
if(tok!=tk_closebracket){ //ñðàâíåíèå
ofsstr2=GetLecsem(tk_closebracket);
comparetok=CheckCompareTok(preg);
if(tok>=tk_char&&tok<=tk_double){
type2=tok;
if(ofsstr2)free(ofsstr2);
ofsstr2=GetLecsem(tk_closebracket);
getoperand(preg);
}
if(tok==tk_minus){
if(CheckMinusNum()==FALSE){
preerror("only negative of constants valid within compairsons");
nexttok();
}
}
#ifdef OPTVARCONST
CheckConstVar3(&tok,&itok,razr);
#endif
if(tok==tk_number){
switch(vartype){
case tk_long:
case tk_int:
case tk_char:
htok2.number=doconstlongmath();
itok.flag=(unsigned char)postnumflag;
break;
case tk_dword:
case tk_reg32:
case tk_beg:
case tk_reg:
case tk_word:
case tk_byte:
htok2.number=doconstdwordmath();
itok.flag=(unsigned char)postnumflag;
break;
case tk_float:
htok2.number=doconstfloatmath();
break;
case tk_reg64:
case tk_qword:
htok2.lnumber=doconstqwordmath();
itok.flag=(unsigned char)postnumflag;
break;
case tk_double:
htok2.lnumber=doconstdoublemath();
break;
}
htok2.rm=typenumber(vartype);
ittok2=tk_number;
htok2.flag=itok.flag;
}
else{
if(ittok>=tk_charvar&&ittok<=tk_doublevar&&(tok==tk_proc||tok==tk_id||
tok==tk_undefproc||tok==tk_declare||tok==tk_apiproc||tok==tk_ID||
itok2.type==tp_opperand||(tok>=tk_charvar&&tok<=tk_doublevar))){
if(ofsstr2){
int retreg;
razr=getrazr(vartype);
if((retreg=CheckIDZReg(ofsstr2,AX,razr))!=NOINREG){
GetEndLex(tk_closebracket);
usereg2=retreg==SKIPREG?AX:retreg;
if(razr==r16)ittok2=tk_reg;
else if(razr==r32)ittok2=tk_reg32;
else ittok2=tk_beg;
htok2.number=usereg2;
nexttok();
goto en2;
}
}
int sign=0;
switch(ittok){
case tk_charvar: sign=1;
case tk_bytevar:
doalmath(sign,&ofsstr2);
usereg2=htok2.number=AX;
ittok2=tk_beg;
break;
case tk_intvar: sign=1;
case tk_wordvar:
do_e_axmath(sign,r16,&ofsstr2);
usereg2=htok2.number=AX;
ittok2=tk_reg;
break;
case tk_longvar: sign=1;
case tk_dwordvar:
do_e_axmath(sign,r32,&ofsstr2);
usereg2=htok2.number=AX;
ittok2=tk_reg32;
break;
case tk_floatvar:
doeaxfloatmath(tk_fpust);
ittok2=tk_fpust;
htok2.type=tp_modif;
htok2.number=0;
ClearReg(AX);
break;
case tk_doublevar:
doeaxfloatmath(tk_fpust,0,4);
ittok2=tk_fpust;
htok2.type=tp_modif;
htok2.number=0;
ClearReg(AX);
break;
case tk_qwordvar:
usereg2=htok2.number=EAX|(EDX*256);
getintoreg64(usereg2);
doregmath64(usereg2);
ittok2=tk_reg64;
ClearReg(AX);
ClearReg(DX);
break;
}
}
else{
if(tok==tk_bits){
int i=itok.bit.ofs+itok.bit.siz;
int vops;
if(i<=64)vops=r64;
if(i<=32)vops=r32;
if(i<=16)vops=r16;
if(i<=8)vops=r8;
if(vops<razr)vops=razr;
i=AX;
if((ittok==tk_reg32||ittok==tk_reg||ittok==tk_beg)&&htok.number==0)i=CX;
bits2reg(i,vops);
switch(razr){
case r64:
case r32:
tok=tk_reg32;
break;
case r16:
tok=tk_reg;
break;
case r8:
tok=tk_beg;
break;
}
itok.number=i;
ClearReg(i);
}
switch(tok){
case tk_beg:
case tk_reg:
case tk_reg32:
itok.rm=type2; //òèï ñîäåðæèìîãî â reg32
if((ittok==tk_reg32||ittok==tk_reg||ittok==tk_beg)&&
htok.number==itok.number)preerror("Comparison two identical registers");
break;
}
int next=TRUE;
int sign=0;
if(ittok==tk_reg32){
if(ofsstr2){
int retreg;
int treg;
treg=(htok.number==0?DX:AX);
razr=r32;
if((retreg=CheckIDZReg(ofsstr2,treg,r32))!=NOINREG){
if(retreg==SKIPREG)retreg=treg;
if(retreg!=htok.number){
GetEndLex(tk_closebracket);
ittok2=tk_reg32;
htok2.number=usereg2=retreg;
nexttok();
goto en2;
}
}
}
switch(tok){
case tk_intvar:
sign=1;
case tk_wordvar:
if(htok.number!=0){
do_e_axmath(sign,r32,&ofsstr2);
usereg2=itok.number=0;
}
else{
getintoreg_32(DX,r32,sign,&ofsstr2);
usereg2=itok.number=DX;
}
warningreg(regs[1][itok.number]);
next=FALSE;
ittok2=tk_reg32;
htok2=itok;
}
}
if(next){
ittok2=tok;
htok2=itok;
ibuf2=bufrm;
bufrm=NULL;
hstr2=strinf;
strinf.bufstr=NULL;
nexttok();
}
}
RestoreStack();
}
}
else{ // !=0
if((comparetok>=tk_overflowflag)&&(comparetok<=tk_plusflag)){
ittok=0x70+comparetok-tk_overflowflag;
goto endcomp;
}
htok2.rm=typenumber(vartype);
comparetok=tk_notequal;
ittok2=tk_number;
htok2.number=0;
htok2.flag=0;
}
if(ittok2==tk_number&&htok2.number==0&&(htok2.flag&f_reloc)==0){
if(setzeroflag){
if(comparetok==tk_notequal){
ittok=0x75;
goto endcomp;
}
if(comparetok==tk_equalto){
ittok=0x74;
goto endcomp;
}
}
if(htok.number==CX&&optimizespeed==0){
if(ittok==tk_reg||ittok==tk_reg32){
if(comparetok==tk_notequal)use_cxz=notflag==0?cxnzcompr:cxzcompr;
else if(comparetok==tk_equalto)use_cxz=notflag==TRUE?cxnzcompr:cxzcompr;
}
}
}
en2:
if(ittok>=tk_charvar&&ittok<=tk_floatvar){
if(ofsstr){
int retreg;
razr=getrazr(vartype);
if((retreg=CheckIDZReg(ofsstr,AX,razr))!=NOINREG){
usereg=retreg==SKIPREG?AX:retreg;
if(!((ittok2==tk_reg||ittok2==tk_reg32||ittok2==tk_beg)&&usereg==htok2.number)){
if(razr==r16)ittok=tk_reg;
else if(razr==r32)ittok=tk_reg32;
else ittok=tk_beg;
htok.number=usereg;
if(ibuf){
free(ibuf);
ibuf=NULL;
}
if(hstr.bufstr){
free(hstr.bufstr);
hstr.bufstr=NULL;
}
}
else{
usereg=-1;
}
}
else{
if(ittok==tk_floatvar)ClearReg(AX);
else if(ittok>=tk_intvar&&ittok<tk_floatvar){
switch(ittok2){
case tk_reg:
case tk_reg32:
case tk_number:
case tk_postnumber:
case tk_undefofs:
break;
default:
usereg2=0;
break;
}
}
else{
switch(ittok2){
case tk_reg:
case tk_reg32:
ClearReg(AX);
case tk_number:
case tk_beg:
break;
default:
usereg2=0;
break;
}
}
}
}
}
if(ittok==tk_number&&htok.flag==0&&ittok2==tk_number&&htok2.flag==0){
invertflag=(htok.number!=htok2.number?zerocompr:voidcompr);
useinline=oinline;
return invertflag;
}
if((ittok==tk_number||ittok==tk_postnumber)&&(ittok2==tk_number||ittok2==tk_postnumber))usereg=0;
#ifdef OPTVARCONST
if(comconst){
if(comparetok==tk_equalto||comparetok==tk_notequal){
if(ittok>=tk_charvar&&ittok<=tk_doublevar&&ittok2==tk_number&&
(htok2.flag&f_reloc)==0&&htok.rec&&(htok.flag&f_useidx)==0){
comconst->rec=htok.rec;
comconst->lnumber=htok2.lnumber;
comconst->contype=htok2.rm;
}
else if(ittok2>=tk_charvar&&ittok2<=tk_doublevar&&ittok==tk_number&&
(htok.flag&f_reloc)==0&&htok2.rec&&(htok2.flag&f_useidx)==0){
comconst->rec=htok2.rec;
comconst->lnumber=htok.lnumber;
comconst->contype=htok.rm;
}
comconst->typevar=comparetok;
if(notflag)comconst->typevar=(comparetok==tk_equalto?tk_notequal:tk_equalto);
}
}
#endif
if(outcmp(0,ittok,&htok,ibuf,&hstr,ittok2,&htok2,ibuf2,&hstr2,razr)){
switch(comparetok){
case tk_less: comparetok=tk_greater; break;
case tk_lessequal: comparetok=tk_greaterequal; break;
case tk_greater: comparetok=tk_less; break;
case tk_greaterequal: comparetok=tk_lessequal; break;
}
}
createopcode:
jumptype=0;
if(vartype==tk_char||vartype==tk_int||vartype==tk_long)jumptype=1;
switch(comparetok){
case tk_equalto: ittok=0x74; break;
case tk_notequal: ittok=0x75; break;
case tk_greater:
ittok=(jumptype==0?0x77:0x7F);
break;
case tk_less:
ittok=(jumptype==0?0x72:0x7C);
break;
case tk_greaterequal:
ittok=(jumptype==0?0x73:0x7D);
break;
case tk_lessequal:
ittok=(jumptype==0?0x76:0x7E);
break;
default: unknowncompop(); break;
}
endcomp:
if(ofsstr){
if(usereg!=-1)IDZToReg(ofsstr,usereg,razr);
free(ofsstr);
}
if(ofsstr2){
// printf("usereg2=%08X %s\n",usereg2,ofsstr2);
if(usereg2!=-1)IDZToReg(ofsstr2,usereg2,razr);
free(ofsstr2);
}
if(invertflag==2)invertflag=((outptr+2-startloc)>128?1:0);
ittok^=invertflag;
ittok^=notflag;
op(ittok); /* output instruction code */
expecting(tk_closebracket);
useinline=oinline;
return invertflag|use_cxz;
}
#ifdef OPTVARCONST
ICOMP *compare(int type,unsigned int *numcomp,REGISTERSTAT **bakreg,REGISTERSTAT **changereg,LVIC *comconst)
#else
ICOMP *compare(int type,unsigned int *numcomp,REGISTERSTAT **bakreg,REGISTERSTAT **changereg)
#endif
{
unsigned int i;
ICOMP *icomp;
int j=0;
int ifline=linenumber;
int ptok=tk_oror;
int rcompr;
int useor=FALSE;
REGISTERSTAT *bakregstat=NULL,*changeregstat=NULL;
if(am32)j=2;
icomp=(ICOMP *)MALLOC(sizeof(ICOMP)*MAXIF); //áëîê äëÿ èíôî î ñðàâíåíèÿõ
i=0;
do{
#ifdef OPTVARCONST
if((rcompr=constructcompare(0,outptr,comconst))==voidcompr||rcompr==zerocompr)i=1;
#else
if((rcompr=constructcompare(0,outptr))==voidcompr||rcompr==zerocompr)i=1;
#endif
if(i){
if(rcompr==voidcompr&&ptok==tk_andand){
i=0;
ptok=tok;
}
continue;
}
op(0x03+j);
if(tok!=tk_oror){
JXorJMP();
if(am32!=FALSE)outword(0);
outword(0);
}
(icomp+*numcomp)->loc=outptr;
(icomp+*numcomp)->type=tok;
// (icomp+*numcomp)->use_cxz=rcompr&0xFC;
(*numcomp)++ ;
if(*numcomp==MAXIF){
ManyLogicCompare();
free(icomp);
return NULL;
}
ptok=tok;
/* if(tok!=tk_andand&&tok!=tk_oror&&bakregstat==NULL){
bakregstat=BakRegStat();
changeregstat=BakRegStat();
}*/
}while(tok==tk_oror||tok==tk_andand);
if(tok==tk_closebracket)nexttok();
for(i=0;i<*numcomp;i++){
unsigned long temp=outptr-(icomp+i)->loc;
if((icomp+i)->type==tk_oror){
#ifdef OPTVARCONST
if(comconst)comconst->rec=NULL;
#endif
if(temp>127)CompareOr();
output[(icomp+i)->loc-1]=(unsigned char)temp;
clearregstat();
useor=TRUE;
}
else if(chip>2){
if(am32==FALSE)*(unsigned short *)&output[(icomp+i)->loc-2]=(unsigned short)temp;
else *(unsigned long *)&output[(icomp+i)->loc-4]=(unsigned long)temp;
}
}
if(bakregstat==NULL){
bakregstat=BakRegStat();
changeregstat=BakRegStat();
}
if(type==tk_if&&rcompr!=zerocompr){
if(rcompr==voidcompr)warcompeqconst();
if(tok==tk_return||tok==tk_RETURN){
if(tok2==tk_semicolon||(tok2==tk_openbracket&&ScanTok3()==tk_closebracket)){
if(insertmode||(!optimizespeed)){
if(tok==tk_return||tok==tk_RETURN)goto merge_if;
}
}
startblock();
doreturn(tok);
endblock();
int di;
if(rcompr==voidcompr)di=0;
else di=am32==FALSE?2:4;
for(unsigned int i=0;i<*numcomp;i++){
if((icomp+i)->type!=tk_oror){
if(am32==FALSE)*(unsigned short *)&output[(icomp+i)->loc-di]=(unsigned short)(outptr-(icomp+i)->loc);
else *(unsigned long *)&output[(icomp+i)->loc-di]=(unsigned long)(outptr-(icomp+i)->loc);
}
}
if((outptr-icomp->loc)<=127)warningjmp(mesIF,ifline);
if(tok==tk_else||tok==tk_ELSE){
notunreach=TRUE;
nexttok();
docommand();
}
free(icomp);
return NULL;
}
if(tok==tk_break||tok==tk_BREAK||tok==tk_continue||tok==tk_CONTINUE||tok==tk_goto||tok==tk_GOTO){
merge_if:
if(rcompr==voidcompr)goto endp;
if(chip<3){
for(i=0;i<*numcomp;i++){
if((icomp+i)->type==tk_oror)output[(icomp+i)->loc-1]=(unsigned char)(output[(icomp+i)->loc-1]-3-j);
else{
if((icomp+i)->type!=tk_andand)output[(icomp+i)->loc-5-j]=(unsigned char)(output[(icomp+i)->loc-5-j]^1);
else{
if(am32==FALSE)*(unsigned short *)&output[(icomp+i)->loc-2]=(unsigned short)(outptr-(icomp+i)->loc);
else *(unsigned long *)&output[(icomp+i)->loc-4]=(unsigned long)(outptr-(icomp+i)->loc);
}
}
}
outptr-=3+j;
}
else{
for(i=0;i<*numcomp;i++){
if((icomp+i)->type==tk_oror)output[(icomp+i)->loc-1]=(unsigned char)(output[(icomp+i)->loc-1]-2-j);
else{
if((icomp+i)->type!=tk_andand){
output[(icomp+i)->loc-4-j]=(unsigned char)(output[(icomp+i)->loc-3-j]-0x10);
output[(icomp+i)->loc-3-j]=(unsigned char)(3+j);
}
else{
if(am32==FALSE)*(unsigned short *)&output[(icomp+i)->loc-2]=(unsigned short)(outptr-(icomp+i)->loc+1);
else *(unsigned long *)&output[(icomp+i)->loc-4]=(unsigned long)(outptr-(icomp+i)->loc+1);
}
}
}
outptr-=2+j;
if(cpu<3)cpu=3;
}
int delta=0; //new 07.06.06 20:27
if(tok==tk_break||tok==tk_BREAK){
if(useor==FALSE){
int ooutptr=outptr-2;
int otok=tok;
i=(unsigned char)(output[ooutptr]^1);
outptr--;
if(tok==tk_break)i+=0x10;
else outptr--;
doBREAK((unsigned char)(tok==tk_BREAK?BREAK_SHORT:(am32==FALSE?BREAK_NEAR:BREAK_32)));
if(otok==tk_break){
output[ooutptr]=0x0f;
output[ooutptr+1]=i;
delta=-1;
}
else{
output[ooutptr]=i;
delta=(am32==TRUE?-5:-3);
}
}
else{
if(tok==tk_BREAK){
output[outptr-1]-=(am32==TRUE?3:1);
}
doBREAK((unsigned char)(tok==tk_BREAK?BREAK_SHORT:(am32==FALSE?BREAK_NEAR:BREAK_32)));
}
}
else if(tok==tk_return||tok==tk_RETURN){
//new 07.06.06 21:12
if(useor==FALSE){
int ooutptr=outptr-2;
int otok=tok;
i=(unsigned char)(output[ooutptr]^1);
outptr--;
if(tok==tk_return){
i+=0x10;
}
else outptr--;
AddRetList(outptr+1,linenumber,tok);
if(tok2==tk_openbracket){
nexttok();
nexttok();
}
if(otok==tk_return){
output[ooutptr]=0x0f;
output[ooutptr+1]=i;
delta=-1;
}
else{
output[ooutptr]=i;
delta=(am32==TRUE?-5:-3);
}
}
else{
if(tok==tk_RETURN)output[outptr-1]-=(am32==TRUE?3:1);
AddRetList(outptr+1,linenumber,tok);
if(tok==tk_return&&tok2==tk_openbracket){
nexttok();
nexttok();
}
}
nextseminext();
clearregstat();
#ifdef OPTVARCONST
ClearLVIC();
#endif
}
else if(tok==tk_goto||tok==tk_GOTO){
int ooutptr=outptr;
if(useor==FALSE){
if(tok==tk_GOTO){
outptr-=2;
i=(unsigned char)(output[outptr]^1);
GOTOdo();
output[outptr-2]=i;
delta=(am32==0?-3:-5);
}
else{
int otok2=tok2;
gotodo();
if(output[ooutptr]==0xEB){ //áûë êîðîòêèé ïåðåõîä
outptr=ooutptr-2;
op(output[outptr]^1);
op(output[ooutptr+1]+2);
delta=(am32==0?-3:-5);
}
else if(am32&&otok2==tk_number){
outptr=ooutptr-2;
i=(unsigned char)((output[outptr]^1)+0x10);
op(0x0f);
op(i);
if(output[outptr]==0xE9)outdword(*(unsigned long *)&output[ooutptr+1]+1);
else outdword(*(unsigned short *)&output[ooutptr+2]);
delta=-1;
}
}
}
else{ // useor
if(tok==tk_goto)gotodo();
else GOTOdo();
if(output[ooutptr]==0xEB){ //áûë êîðîòêèé ïåðåõîä
output[ooutptr-1]-=(am32==TRUE?3:1);
}
}
}
else{
if(useor==FALSE){
int ooutptr=outptr-2;
int otok=tok;
i=(unsigned char)(output[ooutptr]^1);
outptr--;
if(tok==tk_continue)i+=0x10;
else outptr--;
doCONTINUE((unsigned char)(tok==tk_CONTINUE?CONTINUE_SHORT:(am32==FALSE?CONTINUE_NEAR:CONTINUE_32)));
if(otok==tk_continue){
output[ooutptr]=0x0f;
output[ooutptr+1]=i;
delta=-1;
}
else{
output[ooutptr]=i;
delta=(am32==TRUE?-5:-3);
}
}
else{
if(tok==tk_CONTINUE){
output[outptr-1]-=(am32==TRUE?3:1);
}
doCONTINUE((unsigned char)(tok==tk_CONTINUE?CONTINUE_SHORT:(am32==FALSE?CONTINUE_NEAR:CONTINUE_32)));
}
}
for(i=0;i<*numcomp;i++){
// if((icomp+i)->type==tk_oror)output[(icomp+i)->loc-1]+=delta;
// else
if((icomp+i)->type==tk_andand){
if(am32==FALSE)*(signed short *)&output[(icomp+i)->loc-2]+=delta;
else *(signed long *)&output[(icomp+i)->loc-4]+=delta;
}
}
if(tok==tk_else||tok==tk_ELSE){
notunreach=TRUE;
nexttok();
docommand();
}
free(icomp);
return NULL;
}
}
endp:
if(type!=tk_for){
startblock();
if(rcompr==zerocompr)warcompneqconst();
if(tok==tk_openbrace){
if(rcompr==zerocompr){
cha=cha2;
inptr=inptr2;
SkipBlock();
inptr2=inptr;
cha2=cha;
linenum2=linenumber;
nexttok();
}
else{
#ifdef OPTVARCONST
if(comconst&&comconst->rec&&comconst->typevar==tk_equalto){
Const2VarRec(comconst);
}
#endif
doblock();
nexttok();
}
}
else{
if(rcompr==zerocompr){
do{
nexttok();
}while(tok!=tk_semicolon&&tok!=tk_eof);
}
else{
#ifdef OPTVARCONST
if(comconst&&comconst->rec&&comconst->typevar==tk_equalto){
Const2VarRec(comconst);
}
#endif
docommand();
}
}
endblock();
RestoreStack();
}
if(bakreg)*bakreg=bakregstat;
if(changereg)*changereg=changeregstat;
return icomp;
}
void opt_if_else_stop(unsigned int newptr)
{
unsigned int ooutptr,ooutptrdata;
unsigned char instr;
dbgact++;
ooutptr=outptr;
ooutptrdata=outptrdata;
outptr=newptr;
instr=output[outptr];
docommand();
if(output[newptr]==0xEB){
signed char ofs=output[newptr+1];
if(output[newptr-1]==0x0F&&instr>=0x80&&instr<0x90){
ofs--;
if(am32)ofs-=(signed char)2;
}
if(am32)*(long *)&output[newptr+1]=ofs;
else*(short *)&output[newptr+1]=ofs;
}
if(am32&&output[newptr]==0x66&&output[newptr+1]==0xE9){
signed short ofs=(signed short)(*(short *)&output[newptr+2]-1);
*(long *)&output[newptr+1]=ofs;
}
output[newptr]=instr;
outptr=ooutptr;
outptrdata=ooutptrdata;
dbgact--;
}
void doif()
{
unsigned int startloc,elseline,numcomp=0,ifline;
ICOMP *icomp;
REGISTERSTAT *bakregstat=NULL,*changeregstat=NULL;
unsigned int oaddESP=addESP;
ifline=linenumber;
#ifdef OPTVARCONST
LVIC comconst;
comconst.rec=NULL;
icomp=compare(tk_if,&numcomp,&bakregstat,&changeregstat,&comconst);
#else
icomp=compare(tk_if,&numcomp,&bakregstat,&changeregstat);
#endif
// i=CheckStopBlock();
/*-----------------19.08.99 22:35-------------------
Óáèðàòü else ìîæíî òîëüêî ïîñëå ïåðâîãî if
Ïîñëå else if â ñëåäóþùèé else óáèðàòü íåëüçÿ
--------------------------------------------------*/
if(icomp!=NULL){
elseline=linenumber;
unsigned long temp;
unsigned int j=0;
unsigned int otok=tok;
unsigned int oinptr=inptr2;
unsigned char ocha=cha2;
unsigned int oline=linenumber;
if(tok==tk_else||tok==tk_ELSE){
if(dbg)AddLine();
j=(am32==FALSE?3:5);
if(tok2==tk_goto||tok2==tk_break||tok2==tk_continue||//ïîãëîòèòü èõ
tok2==tk_RETURN||tok2==tk_return||tok2==tk_GOTO||tok2==tk_BREAK||tok2==tk_CONTINUE){
nexttok();
switch(tok){
case tk_GOTO: otok=tk_goto; break;
case tk_BREAK: otok=tk_break; break;
case tk_CONTINUE: otok=tk_continue; break;
case tk_return:
case tk_RETURN:
if(tok2==tk_semicolon||(tok2==tk_openbracket&&
ScanTok3()==tk_closebracket)){
startblock();
otok=tk_return;
break;
}
tok=otok; //íåâîçìîæíî îïòèìèçèðîâàòü
inptr2=oinptr;
cha2=ocha;
linenumber=oline;
goto nooptim;
default:otok=tok; break;
}
oinptr=inptr2;
ocha=cha2;
oline=linenumber;
for(unsigned int i=0;i<numcomp;i++){
if((icomp+i)->type!=tk_oror){
notunreach=TRUE;
tok=otok;
inptr2=oinptr;
cha2=ocha;
linenumber=oline;
opt_if_else_stop((icomp+i)->loc-j);
}
}
if(otok==tk_return)endblock();
if((outptr+j-icomp->loc)<=127)warningjmp(mesIF,ifline);
free(icomp);
retproc=FALSE;
lastcommand=tk_if;
return;
}
nooptim:
if(tok==tk_ELSE)j=2;
}
notunreach=TRUE;
for(unsigned int i=0;i<numcomp;i++){
if((icomp+i)->type!=tk_oror){
if(am32==FALSE)*(unsigned short *)&output[(icomp+i)->loc-2]=(unsigned short)(outptr+j-(icomp+i)->loc);
else *(unsigned long *)&output[(icomp+i)->loc-4]=(unsigned long)(outptr+j-(icomp+i)->loc);
}
}
if((outptr+j-icomp->loc)<=127)warningjmp(mesIF,ifline);
switch(lastcommand){
case tk_return:
case tk_RETURN:
case tk_goto:
case tk_GOTO:
case tk_break:
case tk_BREAK:
case tk_continue:
case tk_CONTINUE:
addESP=oaddESP;
break;
}
if(retproc)CopyRegStat(bakregstat);
else{
switch(lastcommand){
case tk_return:
case tk_RETURN:
case tk_goto:
case tk_GOTO:
case tk_break:
case tk_BREAK:
case tk_continue:
case tk_CONTINUE:
CopyRegStat(bakregstat);
break;
default:
CompareRegStat(changeregstat);
break;
}
}
// printf("lastcommand=%d\n",lastcommand);
// CompareRegStat(changeregstat);
if(tok==tk_else/*&&i==FALSE*/){
addESP=oaddESP;
RestoreStack();
CopyRegStat(bakregstat);
jumploc0();
startloc=outptr;
getoperand();
#ifdef OPTVARCONST
if(tok!=tk_if&&tok!=tk_IF&&comconst.rec&&comconst.typevar==tk_notequal){
Const2VarRec(&comconst);
}
#endif
startblock();
if(tok==tk_return||tok==tk_RETURN){
if(dbg)AddLine();
doreturn(tok);
}
else docommand();
endblock();
RestoreStack();
temp=outptr-startloc;
if(temp<=127)warningjmp(mesELSE,elseline);
if(am32==FALSE)*(unsigned short *)&output[startloc-2]=(unsigned short)temp;
else *(unsigned long *)&output[startloc-4]=temp;
CompareRegStat(changeregstat);
}
else if(tok==tk_ELSE/*&&i==FALSE*/){
addESP=oaddESP;
RestoreStack();
CopyRegStat(bakregstat);
outword(0x00EB);
startloc=outptr;
getoperand();
#ifdef OPTVARCONST
if(tok!=tk_if&&tok!=tk_IF&&comconst.rec&&comconst.typevar==tk_notequal){
Const2VarRec(&comconst);
}
#endif
startblock();
if(tok==tk_return||tok==tk_RETURN){
if(dbg)AddLine();
doreturn(tok);
}
else docommand();
endblock();
RestoreStack();
temp=outptr-startloc;
if(temp>127)jumperror(elseline,mesELSE);
output[startloc-1]=(unsigned char)temp;
CompareRegStat(changeregstat);
}
/* else{
if(i!=FALSE&&(tok==tk_else||tok==tk_ELSE))nexttok();
}*/
free(icomp);
CopyRegStat(changeregstat);
}
FreeStat(bakregstat);
FreeStat(changeregstat);
retproc=FALSE;
lastcommand=tk_if;
}
#ifdef OPTVARCONST
ICOMP *bigcompare(int type,unsigned int *numcomp,REGISTERSTAT **bakreg,REGISTERSTAT **changereg,LVIC *comconst)
#else
ICOMP *bigcompare(int type,unsigned int *numcomp,REGISTERSTAT **bakreg,REGISTERSTAT **changereg)
#endif
{
unsigned int ifline;
ICOMP *icomp;
unsigned int i=0;
int j=0;
int ptok=tk_oror;
int rcompr;
int useor=FALSE;
REGISTERSTAT *bakregstat=NULL,*changeregstat=NULL;
if(am32!=FALSE)j=2;
icomp=(ICOMP *)MALLOC(sizeof(ICOMP)*MAXIF); //áëîê äëÿ èíôî î ñðàâíåíèÿõ
ifline=linenumber;
do{
#ifdef OPTVARCONST
if((rcompr=constructcompare(1,outptr,comconst))==voidcompr||rcompr==zerocompr)i=1;
#else
if((rcompr=constructcompare(1,outptr))==voidcompr||rcompr==zerocompr)i=1;
#endif
(icomp+*numcomp)->use_cxz=rcompr&0xFC;
if(i){
if(rcompr==voidcompr&&ptok==tk_andand){
i=0;
ptok=tok;
}
continue;
}
op(0x00);
(icomp+*numcomp)->loc=outptr;
(icomp+*numcomp)->type=tok;
(*numcomp)++;
if(*numcomp==MAXIF){
ManyLogicCompare();
free(icomp);
return NULL;
}
ptok=tok;
/* if(tok==tk_andand&&bakregstat==NULL){
bakregstat=BakRegStat();
changeregstat=BakRegStat();
}*/
}while(tok==tk_oror||tok==tk_andand);
if(tok==tk_closebracket)nexttok();
for(i=0;i<*numcomp;i++){
if(outptr-(icomp+i)->loc>127)CompareOr();
output[(icomp+i)->loc-1]=(unsigned char)(outptr-(icomp+i)->loc);
if((icomp+i)->type==tk_oror){
#ifdef OPTVARCONST
if(comconst)comconst->rec=NULL;
#endif
output[(icomp+i)->loc-2]=(unsigned char)(output[(icomp+i)->loc-2]^1);
clearregstat();
useor=TRUE;
}
}
if(bakregstat==NULL){
bakregstat=BakRegStat();
changeregstat=BakRegStat();
}
if(type==tk_IF&&rcompr!=zerocompr){
if(rcompr==voidcompr)warcompeqconst();
if(tok==tk_return||tok==tk_RETURN){
if(tok2==tk_semicolon||(tok2==tk_openbracket&&ScanTok3()==tk_closebracket)){
if(insertmode||(!optimizespeed)){
if(tok==tk_RETURN)goto merge_if;
else if(chip>2&&(insertmode||(paramsize&&
(current_proc_type&f_typeproc)!=tp_cdecl)))goto merge_if2;
}
}
startblock();
doreturn(tok);
endblock();
for(unsigned int i=0;i<*numcomp;i++){
if((icomp+i)->type!=tk_oror){
if((outptr-(icomp+i)->loc)>127)jumperror(ifline,mesIF);
output[(icomp+i)->loc-1]=(unsigned char)(outptr-(icomp+i)->loc);
}
}
if(tok==tk_else||tok==tk_ELSE){
notunreach=TRUE;
getoperand();
docommand();
}
free(icomp);
return NULL;
}
if(tok==tk_BREAK||tok==tk_CONTINUE||tok==tk_GOTO){
merge_if:
int otok=tok;
for(i=0;i<*numcomp;i++){
unsigned char oldcode;
if(((icomp+i)->type==tk_oror)||((i+1)==*numcomp)){
outptr=(icomp+i)->loc-2;
oldcode=output[outptr];
if(tok==tk_BREAK)MakeBreak(BREAK_SHORT);
else if(tok==tk_RETURN){
AddRetList(outptr+1,ifline,tk_RETURN);
clearregstat();
#ifdef OPTVARCONST
ClearLVIC();
#endif
}
else if(tok==tk_GOTO){
if((i+1)!=*numcomp){
int optr,ocha,oline;
optr=inptr2;
ocha=cha2;
oline=linenum2;
GOTOdo();
if(outptr!=(icomp+i)->loc)jumperror(oline,"GOTO");
inptr2=optr;
cha2=(unsigned char)ocha;
linenum2=oline;
tok=tk_GOTO;
}
else{
getoperand();
CheckIP();
if(tok==tk_number||tok==tk_interruptproc||tok==tk_proc){
long hnumber;
if(tok==tk_number)hnumber=doconstdwordmath();
else{
hnumber=itok.number;
nexttok();
}
long loc=hnumber-outptr-2;
if(loc>-129&&loc<128){
op((unsigned char)(oldcode^1));
op(loc);
}
else{
loc-=3;
outptr++;
op(am32==0?3:5);
op(0xE9);
if(am32==FALSE)outword(loc);
else{
loc-=2;
outdword(loc);
}
}
seminext();
break;
}
else if(GOTO())nexttok();
seminext();
}
}
else MakeContinue(CONTINUE_SHORT);
if((i+1)==*numcomp)oldcode^=1;
output[outptr-2]=oldcode;
}
}
if(tok==tk_RETURN&&tok2==tk_openbracket){
nexttok();
nexttok();
}
if(otok!=tk_GOTO&&rcompr!=voidcompr)nextseminext();
if(tok==tk_else||tok==tk_ELSE){
notunreach=TRUE;
getoperand();
docommand();
}
free(icomp);
return NULL;
}
if((tok==tk_break||tok==tk_continue||tok==tk_goto)&&chip>2){
merge_if2:
// printf("%s (%u) %s %s tok=%d\n",(startfileinfo+currentfileinfo)->filename,linenumber,itok.name,string,tok);
if(*numcomp==1&&(!(tok==tk_goto&&(tok2==tk_reg||tok2==tk_reg32)))){
outptr-=2;
i=(output[outptr]^1)+0x10;
op(0x0F);
}
if(tok==tk_break)doBREAK((unsigned char)(am32==FALSE?BREAK_NEAR:BREAK_32));
else if(tok==tk_return){
AddRetList(outptr+1,ifline,tk_return);
if(tok2==tk_openbracket){
nexttok();
nexttok();
}
nextseminext();
clearregstat();
#ifdef OPTVARCONST
ClearLVIC();
#endif
}
else if(tok==tk_goto){
nexttok();
CheckIP();
if((tok==tk_number&&*numcomp==1)||tok==tk_interruptproc||tok==tk_proc){
if(tok==tk_proc&&tok2==tk_openbracket)doanyproc(TRUE);
else{
long hnumber;
if(tok==tk_number)hnumber=doconstdwordmath();
else{
hnumber=itok.number;
nexttok();
}
long loc=hnumber-outptr-2;
if(loc>-130&&loc<127){
outptr--;
op((unsigned char)(i-0x10));
op(loc+1);
seminext();
goto c1;
}
else{
loc--;
op(0xE9);
if(am32==FALSE)outword(loc);
else{
loc-=2;
outdword(loc);
}
}
}
}
else{
if(tok==tk_reg||tok==tk_reg32){
i=outptr;
if(gotol(0))nexttok();
i=outptr-i;
output[outptr-i-1]=(unsigned char)i;
goto c1;
}
if(gotol(0))nexttok();
}
seminext();
}
else doCONTINUE((unsigned char)(am32==FALSE?CONTINUE_NEAR:CONTINUE_32));
if(*numcomp==1)output[outptr-3-j]=(unsigned char)i;
c1:
if(cpu<3)cpu=3;
if(tok==tk_else||tok==tk_ELSE){
notunreach=TRUE;
getoperand();
docommand();
}
if(*numcomp!=1){
for(unsigned int i=0;i<*numcomp;i++){
if((icomp+i)->type!=tk_oror){
if((outptr-(icomp+i)->loc)>127)jumperror(ifline,mesIF);
output[(icomp+i)->loc-1]=(unsigned char)(outptr-(icomp+i)->loc);
}
}
}
free(icomp);
return NULL;
}
}
if((icomp+(*numcomp-1))->use_cxz==cxnzcompr){
outptr-=4;
outword(0xE3);
(icomp+(*numcomp-1))->loc=outptr;
for(i=(*numcomp-1);i!=0;i--){
if((icomp+i-1)->type==tk_oror)output[(icomp+i-1)->loc-1]-=(unsigned char)2;
}
}
if(type!=tk_FOR){
startblock();
if(rcompr==zerocompr)warcompneqconst();
if(tok==tk_openbrace){
if(rcompr==zerocompr){
cha=cha2;
inptr=inptr2;
SkipBlock();
inptr2=inptr;
cha2=cha;
linenum2=linenumber;
nexttok();
}
else{
#ifdef OPTVARCONST
if(comconst&&comconst->rec&&comconst->typevar==tk_equalto)Const2VarRec(comconst);
#endif
doblock();
nexttok();
}
}
else{
if(rcompr==zerocompr){
do{
nexttok();
}while(tok!=tk_semicolon&&tok!=tk_eof);
}
else{
#ifdef OPTVARCONST
if(comconst&&comconst->rec&&comconst->typevar==tk_equalto)Const2VarRec(comconst);
#endif
docommand();
}
}
endblock();
RestoreStack();
}
if(bakreg)*bakreg=bakregstat;
if(changereg)*changereg=changeregstat;
return icomp;
}
void dobigif()
{
unsigned int ifline,numcomp=0,j=0;
ICOMP *icomp;
int ic;
unsigned int oaddESP=addESP;
REGISTERSTAT *bakregstat=NULL,*changeregstat=NULL;
ifline=linenumber;
#ifdef OPTVARCONST
LVIC comconst;
comconst.rec=NULL;
icomp=bigcompare(tk_IF,&numcomp,&bakregstat,&changeregstat,&comconst);
#else
icomp=bigcompare(tk_IF,&numcomp,&bakregstat,&changeregstat);
#endif
if(icomp!=NULL){
unsigned int elseline;
elseline=linenumber;
if(tok==tk_else)j=(am32==FALSE?3:5);
else if(tok==tk_ELSE)j=2;
notunreach=TRUE;
if(dbg)AddLine();
for(unsigned int i=0;i<numcomp;i++){
if((icomp+i)->type!=tk_oror){
if((outptr+j-(icomp+i)->loc)>127)jumperror(ifline,mesIF);
output[(icomp+i)->loc-1]=(unsigned char)(outptr+j-(icomp+i)->loc);
}
}
switch(lastcommand){
case tk_return:
case tk_RETURN:
case tk_goto:
case tk_GOTO:
case tk_break:
case tk_BREAK:
case tk_continue:
case tk_CONTINUE:
addESP=oaddESP;
break;
}
if(retproc)CopyRegStat(bakregstat);
else{
switch(lastcommand){
case tk_return:
case tk_RETURN:
case tk_goto:
case tk_GOTO:
case tk_break:
case tk_BREAK:
case tk_continue:
case tk_CONTINUE:
CopyRegStat(bakregstat);
break;
default:
CompareRegStat(changeregstat);
break;
}
// CompareRegStat(changeregstat);
}
if(tok==tk_else/*&&i==FALSE*/){
addESP=oaddESP;
RestoreStack();
CopyRegStat(bakregstat);
jumploc0();
ic = outptr;
getoperand();
#ifdef OPTVARCONST
if(tok!=tk_if&&tok!=tk_IF&&comconst.rec&&comconst.typevar==tk_notequal)Const2VarRec(&comconst);
#endif
startblock();
if(tok==tk_return||tok==tk_RETURN){
if(dbg)AddLine();
doreturn(tok);
}
else docommand();
endblock();
RestoreStack();
if((outptr-ic)<=127)warningjmp(mesELSE,elseline);
if(am32==FALSE)*(unsigned short *)&output[ic-2]=(unsigned short)(outptr-ic);
else *(unsigned long *)&output[ic-4]=(unsigned long)(outptr-ic);
CompareRegStat(changeregstat);
}
else if(tok==tk_ELSE/*&&ic==FALSE*/){
addESP=oaddESP;
RestoreStack();
CopyRegStat(bakregstat);
outword(0x00EB);
ic=outptr;
getoperand();
#ifdef OPTVARCONST
if(tok!=tk_if&&tok!=tk_IF&&comconst.rec&&comconst.typevar==tk_notequal)Const2VarRec(&comconst);
#endif
startblock();
if(tok==tk_return||tok==tk_RETURN){
if(dbg)AddLine();
doreturn(tok);
}
else docommand();
endblock();
RestoreStack();
if((outptr-ic)>127)jumperror(elseline,mesELSE);
output[ic-1]=(unsigned char)(outptr-ic);
CompareRegStat(changeregstat);
}
free(icomp);
CopyRegStat(changeregstat);
}
FreeStat(bakregstat);
FreeStat(changeregstat);
retproc=FALSE;
lastcommand=tk_IF;
}
void JXorJMP()
{
if(chip<3){
op(0xE9);
}
else{
unsigned char i;
outptr-=2;
i=(unsigned char)((output[outptr]^1)+0x10);
op(0x0F); op(i);
if(cpu<3)cpu=3;
}
}
void dowhile(unsigned int typeb)
{
unsigned int ifline,conloc,numcomp=0;
ICOMP *icomp;
REGISTERSTAT *bakregstat=NULL,*changeregstat=NULL;
uptdbr();
if(AlignCycle)AlignCD(CS,aligncycle);
conloc=outptr;
ifline=linenumber;
if(typeb==tk_while)
#ifdef OPTVARCONST
icomp=compare(typeb,&numcomp,&bakregstat,&changeregstat,NULL);
#else
icomp=compare(typeb,&numcomp,&bakregstat,&changeregstat);
#endif
else
#ifdef OPTVARCONST
icomp=bigcompare(typeb,&numcomp,&bakregstat,&changeregstat,NULL);
#else
icomp=bigcompare(typeb,&numcomp,&bakregstat,&changeregstat);
#endif
SetContinueLabel();
jumploc(conloc);
if(icomp!=NULL){
if(typeb==tk_WHILE){
for(unsigned int i=0;i<numcomp;i++){
if((icomp+i)->type!=tk_oror){
if((outptr-(icomp+i)->loc)>127)jumperror(ifline,mesWHILE);
output[(icomp+i)->loc-1]=(unsigned char)(outptr-(icomp+i)->loc);
}
}
}
else{
for(unsigned int i=0;i<numcomp;i++){
if((icomp+i)->type!=tk_oror){
if(am32==FALSE)*(unsigned short *)&output[(icomp+i)->loc-2]=(unsigned short)(outptr-(icomp+i)->loc);
else *(unsigned long *)&output[(icomp+i)->loc-4]=(unsigned long)(outptr-(icomp+i)->loc);
}
}
if((outptr-icomp->loc)<=127)warningjmp(mesWHILE,ifline);
}
free(icomp);
}
if(retproc){
if(bakregstat)CopyRegStat(bakregstat);
}
else if(changeregstat)CompareRegStat(changeregstat);
if(changeregstat)CopyRegStat(changeregstat);
SetBreakLabel();
if(usebr[curbr]!=0)clearregstat();
FreeStat(bakregstat);
FreeStat(changeregstat);
#ifdef OPTVARCONST
ClearLVIC();
#endif
lastcommand=tk_do;
}
void dowhilefast(unsigned int typeb)
{
unsigned int numcomp=0;
unsigned int startloc,i;
ICOMP *icomp;
ITOK oitok,ostructadr;
SINFO ostr;
unsigned int oldinptr;
int otok,otok2;
char *ostring,*obufrm;
int blinenum,olinenum,oinptr;
char *ostartline,*bstartline;
char ocha,bcha;
int jmptocompr=0;
int rcompr;
unsigned char *oinput;
unsigned int oaddESP=addESP;
ocha=cha2;
oinptr=inptr2;
olinenum=linenumber;
ostartline=startline;
clearregstat();
#ifdef OPTVARCONST
ClearLVIC();
#endif
do{
nexttok();
if(tok2==tk_openbracket)nexttok();
if(tok2==tk_closebracket){
nexttok();
jmptocompr=1;
break;
}
if(tok2==tk_number){
nexttok();
if(tok2==tk_closebracket){
if(itok.number!=0)jmptocompr=1;
else jmptocompr=2;
nexttok();
break;
}
}
nexttok(); //íåîáõîäèìî äëÿ èçáåæàíèÿ ïðåäóïðåæäåíèÿ î íåèíèöèàëèçèðîâàííîé ïåðåìåííîé
cha=cha2;
inptr=inptr2;
SkipParam();
inptr2=inptr;
cha2=cha;
linenum2=linenumber;
nexttok();
if(typeb==tk_while&&tok==tk_oror&&optimizespeed==0){
cha2=ocha;
inptr2=oinptr;
linenumber=linenum2=olinenum;
startline=ostartline;
dowhile(typeb);
if(ESPloc&&am32&&oaddESP!=addESP)warESP();
return;
}
if(bufrm){
free(bufrm);
bufrm=NULL;
}
if(strinf.bufstr){
free(strinf.bufstr);
strinf.bufstr=NULL;
}
}while(tok==tk_andand||tok==tk_oror);
while(tok==tk_closebracket)nexttok();
if(!jmptocompr){
if(typeb==tk_WHILE)outword(0x00EB); // JMP SHORT
else jumploc0();
}
i=outptr;
if(AlignCycle)AlignCD(CS,aligncycle);
startloc=outptr;
uptdbr();
if(tok!=tk_openbrace){
if(jmptocompr==2){
do{
nexttok();
}while(tok!=tk_semicolon&&tok!=tk_eof);
}
else docommand();
}
else{
if(jmptocompr==2){
cha=cha2;
inptr=inptr2;
SkipBlock();
inptr2=inptr;
cha2=cha;
linenum2=linenumber;
nexttok();
}
else{
startblock();
doblock();
nexttok();
endblock();
}
}
RestoreStack();
if(!jmptocompr){
if(typeb==tk_WHILE){
if(i!=outptr){
if((outptr-i)>127)jumperror(olinenum,mesWHILE);
output[i-1]=(unsigned char)(outptr-i);
}
else{
if(dbg&1)KillLastLine();
outptr-=2;
startloc-=2;
}
}
else{
if(i!=outptr){
if((outptr-i)<=127)warningjmp(mesWHILE,olinenum);
if(am32) *(unsigned long *)&output[i-4]=(unsigned long)(outptr-i);
else *(unsigned short *)&output[i-2]=(unsigned short)(outptr-i);
}
else{
i=3;
if(am32)i+=2;
if(dbg){
KillLastLine();
KillLastLine();
}
outptr-=i;
startloc-=i;
}
}
}
SetContinueLabel();
clearregstat(); //06.09.04 21:56
#ifdef OPTVARCONST
ClearLVIC();
#endif
icomp=(ICOMP *)MALLOC(sizeof(ICOMP)*MAXIF); //áëîê äëÿ èíôî î ñðàâíåíèÿõ
// oitok2=itok2;
ostring=BackString((char *)string);
oldinptr=inptr2;
oinput=input;
bcha=cha2;
otok=tok;
otok2=tok2;
oitok=itok;
ostructadr=structadr;
ostr=strinf;
strinf.bufstr=NULL;
obufrm=bufrm;
int oldendinptr=endinptr;
COM_MOD *tempcurmod=cur_mod;
if(cur_mod)BackMod();
bufrm=NULL;
blinenum=linenum2;
inptr2=oinptr;
cha2=ocha;
linenumber=linenum2=olinenum;
bstartline=startline;
startline=ostartline;
if(dbg)AddLine();
int ptok=tk_oror;
do{
i=0;
#ifdef OPTVARCONST
if((rcompr=constructcompare(2,startloc,NULL))==voidcompr||rcompr==zerocompr)i=1;
#else
if((rcompr=constructcompare(2,startloc))==voidcompr||rcompr==zerocompr)i=1;
#endif
if(i){
if(ptok==tk_andand){
// i=0;
ptok=tok;
}
continue;
}
if((rcompr&1)){;
op(0x03);
if(tok!=tk_andand){
JXorJMP();
if(am32==FALSE)outword(startloc-(outptr+2));
else outdword(startloc-(outptr+4));
}
}
else{
op(startloc-(outptr+1)); /* the small jump */
if(tok==tk_andand)output[outptr-2]=(unsigned char)(output[outptr-2]^1);
}
(icomp+numcomp)->loc=outptr;
(icomp+numcomp)->type=tok;
numcomp++;
if(numcomp==MAXIF){
ManyLogicCompare();
break;
}
ptok=tok;
}while(tok==tk_oror||tok==tk_andand);
if(jmptocompr==1)jumploc(startloc);
startline=bstartline;
strinf=ostr;
inptr2=oldinptr;
input=oinput;
endinptr=oldendinptr;
cha2=bcha;
tok=otok;
itok=oitok;
structadr=ostructadr;
bufrm=obufrm;
tok2=otok2;
cur_mod=tempcurmod;
strcpy((char *)string,ostring);
free(ostring);
linenumber=linenum2=blinenum;
itok2=oitok;
for(i=0;i<numcomp;i++){
if((icomp+i)->type==tk_andand){
if(outptr-(icomp+i)->loc>127)CompareOr();
output[(icomp+i)->loc-1]=(unsigned char)(outptr-(icomp+i)->loc);
}
}
if(rcompr==cxzcompr){
outptr-=4;
op(0xE3);
op(startloc-outptr-1);
for(i=(numcomp-1);i!=0;i--){
if((icomp+i-1)->type==tk_andand)output[(icomp+i-1)->loc-1]-=(unsigned char)2;
}
}
SetBreakLabel();
clearregstat();
#ifdef OPTVARCONST
ClearLVIC();
#endif
free(icomp);
if(ESPloc&&am32&&oaddESP!=addESP)warESP();
lastcommand=tk_do;
}
void dodo()
{
unsigned int startloc,numcomp=0,i=0;
ICOMP *icomp;
int ptok=tk_oror;
int rcompr;
unsigned int oaddESP=addESP;
nexttok();
if(AlignCycle)AlignCD(CS,aligncycle);
startloc=outptr;
uptdbr();
if(dbg&1)KillLastLine();
clearregstat();
#ifdef OPTVARCONST
ClearLVIC();
#endif
docommand();
SetContinueLabel();
if(dbg)AddLine();
if(tok!=tk_while)preerror("'while' expected following 'do'");
icomp=(ICOMP *)MALLOC(sizeof(ICOMP)*MAXIF); //áëîê äëÿ èíôî î ñðàâíåíèÿõ
do{
#ifdef OPTVARCONST
if((rcompr=constructcompare(2,startloc,NULL))==voidcompr||rcompr==zerocompr)i=1;
#else
if((rcompr=constructcompare(2,startloc))==voidcompr||rcompr==zerocompr)i=1;
#endif
if(i){
if(ptok==tk_andand){
i=0;
ptok=tok;
}
continue;
}
if((rcompr&1)){;
op(0x03);
if(tok!=tk_andand){
JXorJMP();
if(am32==FALSE)outword(startloc-(outptr+2));
else outdword(startloc-(outptr+4));
}
}
else{
op(startloc-(outptr+1)); /* the small jump */
if(tok==tk_andand)output[outptr-2]=(unsigned char)(output[outptr-2]^1);
}
(icomp+numcomp)->loc=outptr;
(icomp+numcomp)->type=tok;
numcomp++;
if(numcomp==MAXIF){
ManyLogicCompare();
goto end;
}
ptok=tok;
}while(tok==tk_oror||tok==tk_andand);
if(i)jumploc(startloc);
if(tok==tk_closebracket)nexttok();
for(i=0;i<numcomp;i++){
if((icomp+i)->type==tk_andand){
if(outptr-(icomp+i)->loc>127)CompareOr();
output[(icomp+i)->loc-1]=(unsigned char)(outptr-(icomp+i)->loc);
}
}
if(rcompr==cxzcompr){
outptr-=4;
op(0xE3);
op(startloc-outptr-1);
for(i=(numcomp-1);i!=0;i--){
if((icomp+i-1)->type==tk_andand)output[(icomp+i-1)->loc-1]-=(unsigned char)2;
}
}
seminext();
SetBreakLabel();
if(usebr[curbr]!=0||useco[curco]!=0)clearregstat();
end:
#ifdef OPTVARCONST
ClearLVIC();
#endif
free(icomp);
if(ESPloc&&am32&&oaddESP!=addESP)warESP();
lastcommand=tk_do;
}
void dofor(unsigned int typeb)
{
unsigned int ifline,conloc,blinenum,numcomp=0;
unsigned char bcha;
unsigned char COMPARE=FALSE,modif=FALSE;
int i;
unsigned char *buf;
unsigned int oaddESP=addESP;
ICOMP *icomp=NULL;
REGISTERSTAT *bakregstat=NULL,*changeregstat=NULL;
ifline=linenumber;
// printf("start for, curco=%u curbr=%u\n",curco,curbr);
uptdbr();
nexttok();
i=inptr2;
bcha=cha2;
expecting(tk_openbracket); //ïðîâ íà îòêð ñêîáêó
if(tok!=tk_semicolon){ //ÅÑÒÜ ÏÐÅÄÂÀÐÈÒÅËÜÍÛÅ ÓÑÒÀÍÎÂÊÈ
for(;;){ //çàïèñàòü èõ â áóôåð
AddBackBuf(i,bcha);
if(tok==tk_semicolon)break;
if(tok!=tk_camma){
expecting(tk_semicolon);
break;
}
i=inptr2;
bcha=cha2;
nexttok();
}
if(bufrm){
free(bufrm);
bufrm=NULL;
}
if(strinf.bufstr){
free(strinf.bufstr);
strinf.bufstr=NULL;
}
CharToBackBuf('}');
CharToBackBuf(0);
RunBackText(); //âûïîëíèòü åãî
}
clearregstat();
#ifdef OPTVARCONST
ClearLVIC();
#endif
bcha=cha2;
i=inptr2;
nexttok();
if(AlignCycle)AlignCD(CS,aligncycle);
conloc=outptr; //çàïîìíèòü òî÷êó íà÷àëà öèêëà
if(tok!=tk_semicolon){ //åñëè åñòü óñëîâèå
if(tok!=tk_openbracket){ //åñëè óñëîâèå íà÷èíàåòñÿ íå ñ (
CharToBackBuf('('); //äîáàâèòü åå
COMPARE=TRUE; //è ôëàã óñòàíîâèòü
}
AddBackBuf(i,bcha); //çàïîìíèòü óñëîâèå
if(tok!=tk_semicolon)expected(';');
SizeBackBuf--;
if(COMPARE)CharToBackBuf(')'); //åñëè íàäî, çàêðûòü ñêîáêó
CharToBackBuf(0);
int oendinptr=endinptr;
endinptr=SizeBackBuf-1;//strlen(BackTextBlock);
i=inptr2;
buf=input;
bcha=cha2;
input=(unsigned char *)BackTextBlock;
SizeBackBuf=0;
inptr2=1;
cha2='(';
if(typeb==tk_for)
#ifdef OPTVARCONST
icomp=compare(typeb,&numcomp,&bakregstat,&changeregstat,NULL);
#else
icomp=compare(typeb,&numcomp,&bakregstat,&changeregstat);
#endif
else
#ifdef OPTVARCONST
icomp=bigcompare(typeb,&numcomp,&bakregstat,&changeregstat,NULL);
#else
icomp=bigcompare(typeb,&numcomp,&bakregstat,&changeregstat);
#endif
free(input);
input=buf;
inptr2=i;
cha2=bcha;
endinptr=oendinptr;
COMPARE=TRUE;
nexttok();
}
else{
i=inptr2;
bcha=cha2;
nexttok();
}
if(tok!=tk_closebracket){ //åñòü ìîäèôèêàöèÿ
modif=TRUE;
while(tok!=tk_closebracket){
AddBackBuf(i,bcha);
if(cha==')'||cha==26){
CharToBackBuf(';');
nextchar();
cha2=cha;
inptr2=inptr;
break;
}
if(bufrm){
free(bufrm);
bufrm=NULL;
}
if(strinf.bufstr){
free(strinf.bufstr);
strinf.bufstr=NULL;
}
i=inptr2;
bcha=cha2;
nexttok();
}
CharToBackBuf('}');
CharToBackBuf(0);
buf=(unsigned char *)REALLOC(BackTextBlock,SizeBackBuf);
SizeBackBuf=0;
}
blinenum=linenumber;
nexttok();
///////////////////
if(tok==tk_openbrace){
if(COMPARE&&(icomp+numcomp)->use_cxz==zerocompr){
warcompneqconst();
cha=cha2;
inptr=inptr2;
SkipBlock();
inptr2=inptr;
cha2=cha;
linenum2=linenumber;
nexttok();
}
else{
startblock();
doblock();
nexttok();
endblock();
}
}
else{
if(COMPARE&&(icomp+numcomp)->use_cxz==zerocompr){
warcompneqconst();
do{
nexttok();
}while(tok!=tk_semicolon&&tok!=tk_eof);
}
else docommand();
}
RestoreStack();
SetContinueLabel();
// puts((char *)string2);
// printf("end for, curco=%u curbr=%u\n",curco,curbr);
if(modif){
unsigned int oldlinenum=linenum2;
ITOK oitok;
oitok=itok2;
BackTextBlock=(char *)buf;
linenum2=blinenum;
RunBackText();
linenumber=linenum2=oldlinenum;
itok2=oitok;
}
if(COMPARE==FALSE||(COMPARE&&(icomp+numcomp)->use_cxz!=zerocompr)){
if(COMPARE&&(icomp+numcomp)->use_cxz==voidcompr)warcompeqconst();
jumploc(conloc);//JMP íà íà÷àëî öèêëà
}
if(COMPARE){
for(unsigned int i=0;i<numcomp;i++){
if((icomp+i)->type!=tk_oror){
if(typeb==tk_FOR){
if((outptr-(icomp+i)->loc)>127)jumperror(ifline,mesFOR);
output[(icomp+i)->loc-1]=(unsigned char)(outptr-(icomp+i)->loc);
}
else{
if((outptr-(icomp+i)->loc)<=127)warningjmp(mesFOR,ifline);
if(am32==FALSE)*(unsigned short *)&output[(icomp+i)->loc-2]=(unsigned short)(outptr-(icomp+i)->loc);
else *(unsigned long *)&output[(icomp+i)->loc-4]=(unsigned long)(outptr-(icomp+i)->loc);
}
}
}
free(icomp);
}
if(retproc){
if(bakregstat)CopyRegStat(bakregstat);
}
else if(changeregstat)CompareRegStat(changeregstat);
if(changeregstat)CopyRegStat(changeregstat);
SetBreakLabel();
if(usebr[curbr]!=0||useco[curco]!=0)clearregstat();
FreeStat(bakregstat);
FreeStat(changeregstat);
#ifdef OPTVARCONST
ClearLVIC();
#endif
if(ESPloc&&am32&&oaddESP!=addESP)warESP();
lastcommand=tk_for;
}
void decit(int dectok,ITOK *detok,char *&decbuf,SINFO *dstr)
// outputs code to decrement the given variable one.
{
int vop=0,i=0,razr=r16;
switch(dectok){
case tk_dwordvar:
case tk_longvar:
CheckAllMassiv(decbuf,4,dstr,detok);
op66(r32);
if(cpu<3)cpu=3;
vop=1;
goto l2;
case tk_wordvar:
case tk_intvar: vop=1;
op66(r16);
i=1;
case tk_bytevar:
case tk_charvar:
i++;
CheckAllMassiv(decbuf,i,dstr,detok);
if(vop!=0)op66(r16);
l2:
outseg(detok,2);
op(0xFE + vop);
op(0x08+detok->rm);
outaddress(detok);
break;
case tk_reg32:
if(cpu<3)cpu=3;
razr=r32;
case tk_reg:
op66(razr);
op(0x48+detok->number);
break;
case tk_beg:
op(0xFE);
op(0xC8+detok->number);
break;
default:
preerror(invaliddecrem);
break;
}
}
void uptdbr(/*int usesw*/)
{
listbr[curbr]=numbr; //íîìåð ýòîãî öèêëà
usebr[curbr]=0;
curbr++; //÷èñëî âëîæåíèé
numbr++; //âñåãî öèêëîâ
// if(!usesw){
useco[curco]=0;
curco++;
// }
if(curbr==MAXIN)preerror("to many inside bloks");
}
void doloop(unsigned int typeb) // both short and long loops
{
unsigned int startloc,startloc2;
int looptok;
ITOK lootok;
char *loopbuf;
signed char delta;
SINFO lstr;
int j=0,sline=linenumber;
unsigned int oaddESP=addESP;
nexttok();
// printf("tok=%u name=%s bufrm=%s\n",tok,itok.name,bufrm);
expecting(tk_openbracket);
looptok=tok;
lootok=itok;
loopbuf=bufrm;
bufrm=NULL;
lstr=strinf;
strinf.bufstr=NULL;
// printf("bufrm=%s strinf=%s\n",loopbuf,lstr.bufstr);
clearregstat();
#ifdef OPTVARCONST
ClearLVIC();
#endif
uptdbr();
if(dbg&1)KillLastLine();
if((tok<tk_charvar||tok>tk_dwordvar)&&tok!=tk_reg&&tok!=tk_reg32
&&tok!=tk_beg&&tok!=tk_closebracket)
preerror(invaliddecrem);
if(tok!=tk_closebracket){
if(typeb!=tk_loop){
if(dbg)AddLine();
int vop=tok==tk_reg?r16:r32;
if(typeb==tk_LOOPNZ&&((tok==tk_reg&&itok.number==CX)||
(tok==tk_reg32&&itok.number==ECX))&&(!(optimizespeed&&chip>3&&chip<7))){
op67(vop);
outword(0xE3);
}
else{
if(tok==tk_reg||tok==tk_reg32||tok==tk_beg){
if(tok==tk_beg)op(0x84);
else{
op66(vop);
op(0x85);
}
op(0xc0+(unsigned int)itok.number*9);
}
else{
ITOK htok2;
htok2.number=0;
htok2.rm=(am32==FALSE?rm_d16:rm_d32);
htok2.segm=DS;
htok2.post=0;
htok2.sib=(am32==FALSE?CODE16:CODE32);
htok2.flag=0;
int razr=r_undef;
switch(tok){
case tk_longvar:
case tk_dwordvar:
razr=2;
case tk_intvar:
case tk_wordvar:
razr++;
case tk_charvar:
case tk_bytevar:
razr++;
}
outcmp(0,tok,&itok,bufrm,&strinf,tk_number,&htok2,loopbuf,&lstr,razr);
}
if(typeb==tk_LOOPNZ)outword(0x74);
else{
if(chip<3){
outword(0x0375); // JNZ past jump up
op(0xE9);
}
else{
outword(0x840F);
}
outword(0);
if(am32!=FALSE)outword(0);
}
}
}
nexttok(); //òî ÷òî óìåíüøàåòñÿ
}
expecting(tk_closebracket);
startloc2=outptr;
if(AlignCycle)AlignCD(CS,aligncycle);
startloc=outptr;
docommand();
RestoreStack();
SetContinueLabel();
if(looptok!=tk_closebracket){
if(((outptr-startloc)<=(127-3))&&(chip<3||optimizespeed==0)&&
((looptok==tk_reg&&lootok.number==CX)||(looptok==tk_reg32&&lootok.number==ECX))){
delta=(char)(startloc-(outptr+2));
if(op67(looptok==tk_reg?r16:r32)!=FALSE)delta--;
op(0xE2);
op(delta); /* LOOP 'delta' */
}
else{
decit(looptok,&lootok,loopbuf,&lstr);
if((outptr-startloc)>(unsigned int)(127-2-j)){ /* long jump */
if(chip<3){
outword(0x0374); // JZ past jump up
op(0xE9);
} /* JMP top of loop */
else{
outword(0x850F);
if(cpu<3)cpu=3;
}
if(am32==FALSE)outword(startloc-(outptr+2));
else outdword(startloc-(outptr+4));
}
else{
op(0x75); // short jump
op(startloc-(outptr+1));
} /* JNZ 'delta' */
}
}
else jumploc(startloc);//JMP íà íà÷àëî öèêëà
if(typeb!=tk_loop){
looptok=outptr-startloc2;
if(typeb==tk_LOOPNZ){
if(looptok>127)jumperror(sline,mesLOOPNZ);
output[startloc2-1]=(unsigned char)looptok;
}
else{
if(looptok<=127)warningjmp(mesLOOPNZ,sline);
if(am32==FALSE)*(unsigned short *)&output[startloc2-2]=(unsigned short)looptok;
else *(unsigned long *)&output[startloc2-4]=(unsigned long)looptok;
}
}
SetBreakLabel();
if(usebr[curbr]!=0||useco[curco]!=0||typeb!=tk_loop)clearregstat();
#ifdef OPTVARCONST
ClearLVIC();
#endif
if(ESPloc&&am32&&oaddESP!=addESP)warESP();
lastcommand=tk_loop;
}
void GetNameLabel(int type,int num)
{
sprintf((char *)string2,type==tk_break?"BREAK%04X":"CONTINUE%04X",listbr[num]);
}
void SetBreakLabel()
{
curbr--;
if(usebr[curbr]!=0){
GetNameLabel(tk_break,curbr);
updatecall((unsigned int)updatelocalvar((char *)string2,tk_number,outptr),outptr,procedure_start);
// clearregstat();
}
}
void SetContinueLabel()
{
curco--;
if(useco[curco]!=0){
GetNameLabel(tk_continue,curco);
updatecall((unsigned int)updatelocalvar((char *)string2,tk_number,outptr),outptr,procedure_start);
}
}
/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
void SaveDataVal(unsigned int ssize,unsigned long long val)
{
switch(ssize){
case 1: opd(val); break;
case 2: outwordd(val); break;
case 4: outdwordd(val); break;
case 8: outqwordd(val); break;
}
}
long AddVarString()
{
long loop=0;
int term;
do{
term=itok.flag;
for(int i=0;i<itok.number;i++){ //ââåñòè ñòðîêó
opd(string[i]);
loop++;
}
nexttok();
}while(tok==tk_string);
switch(term&3){
case zero_term:
if(term&s_unicod)opd(0);
opd(0);
loop++;
break;
case dos_term:
if(term&s_unicod)opd(0);
opd('$');
loop++;
break;
}
return loop;
}
long initglobalvar(int type,long elements,long ssize,char typev)
{
long loop;
long long i=0;
int htok;
char name[IDLENGTH];
nexttok();
loop=0;
if(dbg&2)AddDataLine((tok==tk_string&&typev!=pointer?(char)3:(char)ssize));
loopsw:
htok=tok;
switch(tok){ //çàïîëíèòü âåëè÷èíàìè
case tk_apioffset: AddApiToPost(itok.number); nexttok(); break;
case tk_postnumber:
(itok.flag&f_extern)==0?setwordpost(&itok):setwordext(&itok.number);
itok.flag=0;
goto cn1;
case tk_undefofs:
strcpy(name,itok.name);
// AddUndefOff(1,itok.name);
cn1:
tok=tk_number;
case tk_minus:
case tk_number:
if(type==tk_byte||type==tk_word||type==tk_dword)i+=doconstdwordmath();
else if(type==tk_float)i=doconstfloatmath();
else if(type==tk_double)i=doconstdoublemath();
else if(type==tk_qword)i+=doconstqwordmath();
else i+=doconstlongmath();
if(tok==tk_plus&&tok2==tk_postnumber&&htok!=tk_undefofs){
nexttok();
goto loopsw;
}
if(elements!=0){
for(;loop<elements;loop++){
if(postnumflag&f_reloc)AddReloc();
if(htok==tk_undefofs)AddUndefOff(3,name);
SaveDataVal(ssize,i);
}
}
loop=loop*ssize;
break;
case tk_string:
if(typev==pointer){
loop=(am32==FALSE?2:4);
i=addpoststring(DS);
if(am32==FALSE)outwordd(i);
else outdwordd(i);
nexttok();
}
else{
loop=AddVarString();
if(elements!=0){
for(;loop<ssize*elements;loop++){//äîïîëíèòü 0 åñëè êîðîòêàÿ
opd(aligner);
}
}
}
break;
case tk_from: //ñ÷èòàòü ôàéë ñ äàííûìè
nexttok();
loop=dofrom();
if(elements!=0){
for(;loop<ssize*elements;loop++)opd(aligner);
}
nexttok();
break;
case tk_extract: //ñ÷èòàòü ôðàãìåíò ôàéëà ñ äàííûìè
nexttok();
loop=doextract();
if(elements!=0){
for(;loop<ssize*elements;loop++)opd(aligner);
}
break;
case tk_openbrace: //ìàññèâ äàííûõ
nexttok();
while(tok!=tk_closebrace){
htok=tok;
if(typev==pointer){
if(tok==tk_string){
i=addpoststring(DS);
nexttok();
}
else if(tok==tk_number||tok==tk_minus||tok==tk_undefofs){
if(tok==tk_undefofs){
tok=tk_number;
strcpy(name,itok.name);
// AddUndefOff(1,itok.name);
}
// else if((itok.flag&f_reloc)!=0)AddReloc();
i=doconstdwordmath();
}
else{
numexpected();
nexttok();
}
if(postnumflag&f_reloc)AddReloc();
if(htok==tk_undefofs)AddUndefOff(3,name);
if(am32==FALSE)outwordd(i);
else outdwordd(i);
}
else{
switch(tok){
case tk_apioffset: AddApiToPost(itok.number); nexttok(); break;
case tk_string:
loop+=AddVarString()/ssize-1;
break;
case tk_postnumber:
(itok.flag&f_extern)==0?setwordpost(&itok):setwordext(&itok.number);
itok.flag=0;
goto cn2;
case tk_undefofs:
strcpy(name,itok.name);
// AddUndefOff(1,itok.name);
cn2:
tok=tk_number;
case tk_number:
case tk_minus:
if(type==tk_byte||type==tk_word||type==tk_dword)i=doconstdwordmath();
else if(type==tk_float)i=doconstfloatmath();
else if(type==tk_double)i=doconstdoublemath();
else if(type==tk_qword)i=doconstqwordmath();
else i=doconstlongmath();
// if((postnumflag&f_reloc)!=0)AddReloc();
if((postnumflag&f_reloc)!=0)AddReloc();
if(htok==tk_undefofs)AddUndefOff(3,name);
SaveDataVal(ssize,i);
break;
default:
numexpected();
nexttok();
break;
}
}
loop++;
if(tok==tk_closebrace)break;
expecting(tk_camma);
}
if(elements!=0){
for(;loop<elements;loop++)SaveDataVal(ssize,aligner);
}
loop=loop*ssize;
nexttok();
break;
default:
// printf("tok=%d\n",tok);
numexpected(); nexttok(); break;
}
return loop;
}
void AddPostData(unsigned int loop)
{
if(dynamic_flag==0){
unsigned int longpostsize=loop+postsize;
if(am32==FALSE&&longpostsize>0xFFFFL)tobigpost();
else postsize=longpostsize;
}
}
void labelindata()
{
//idrec *varrec;
FindOff((unsigned char *)itok.name,DS);
tok=tk_number;
itok.number=outptrdata;
itok.segm=DS;
string[0]=0;
if(FixUp)itok.flag=f_reloc;
/*varrec=*/addtotree(itok.name);
/*varrec->count=*/FindOff((unsigned char *)itok.name,DS);
nexttok();
nexttok();
}
void globalvar() /* both initialized and unitialized combined */
{
long size,loop,i,elements,ssize;
char done=0,typev;
char var_name[IDLENGTH];
int type=itok.rm,typebak; //òèï ïåðåìåííîé
unsigned int flag,fflag=itok.flag,dynamic;
unsigned int npointr=itok.npointr;
int count;
idrec *varrec;
size=typesize(type); //ðàçìåð ïåðåìåííîé
if(FixUp)fflag|=f_reloc;
typebak=type;
while(tok!=tk_eof&&done==0){
int nnpointr=0;
typev=variable;
ssize=size;
flag=fflag;
type=typebak;
// printf("type=%d\n",type);
if(tok==tk_far){
flag|=f_far;
nexttok();
}
while(tok==tk_mult){ //óêàçàòåëü
npointr++;
nexttok();
}
if(tok==tk_openbracket){
nexttok();
while(tok==tk_mult){ //óêàçàòåëü íà ïðîöåäóðó
nnpointr++;
nexttok();
}
}
if(npointr){
if((flag&f_far)!=0||am32!=FALSE)ssize=4;
else ssize=2;
typev=pointer;
type=am32==FALSE?tk_word:tk_dword;
}
// printf("tok=%d %s\n",tok,itok.name);
switch(tok){
case tk_id:
case tk_ID:
if(tok2==tk_openbracket||nnpointr){
if(npointr)type=am32==FALSE?tk_word:tk_dword;
declare_procedure(flag,type,nnpointr);
break;
}
strcpy(var_name,itok.name); //èìÿ ïåðåìåííîé
elements=1;
nexttok();
if(tok==tk_openblock){ //[
nexttok();
if(tok==tk_closeblock){//íåèçâåñòíîå ÷èñëî ýëåìåíòîâ
elements=0;
nexttok();
}
else{
CheckMinusNum();
if(tok!=tk_number){
numexpected();
nexttok();
}
else{
elements=doconstlongmath(); //÷èñëî ýëåìåíòîâ
expecting(tk_closeblock);
}
}
}
if(type==tk_void){
preerror("type 'void' not use for declare variables");
break;
}
dynamic=FALSE;
if(tok==tk_assign||(notpost==TRUE&&dynamic_flag==0)){ //= èíèöèàëèçèðîâàíàÿ ïåðåìåííàÿ
if((flag&f_extern))preerror("extern variable do not initialize at declare");
i=tok;
itok.type=tp_gvar;// 11.07.05 21:56 tp_ucnovn;
SetNewTok(type,typev);
if(useStartup==TRUE&&i!=tk_assign&&SaveStartUp(size*elements,var_name)!=FALSE){
if(elements==0)ZeroMassiv(); //îøèáêà
tok=i;
break;
}
if(alignword&&ssize&&(!dynamic_flag))alignersize+=AlignCD(DS,ssize);
itok.number=dynamic_flag==0?outptrdata:0;
itok.segm=(comfile==file_rom&&modelmem==TINY?CS:DS);
itok.flag=flag;
// itok.post=dynamic;
itok.size=elements*ssize;
itok.rm=(am32==FALSE?rm_d16:rm_d32);
itok.npointr=(unsigned short)npointr;
varrec=addtotree(var_name);
if((count=FindOff((unsigned char *)var_name,DS))==0){
if(dynamic_flag)dynamic=DYNAMIC_VAR;
}
else if(dynamic_flag)dynamic=USED_DIN_VAR;
if(i!=tk_assign){
if(elements==0)ZeroMassiv();
else if(notpost==TRUE){
for(loop=0;loop<elements;loop++)SaveDataVal(ssize,aligner);
loop=loop*ssize;
varrec->recsize=loop;
datasize+=loop;
}
tok=i;
break;
}
if(dynamic){
varrec->sbuf=dynamic_var();
varrec->recpost=dynamic;
}
else{
loop=initglobalvar(type,elements,ssize,typev);
varrec->recsize=loop;
datasize+=loop;
}
varrec->count=count;
}
else{
if(elements==0){
ZeroMassiv();
break;
}
if(CheckUseAsUndef((unsigned char *)var_name)==0&&dynamic_flag)dynamic=TRUE;
switch(tok){ //íåèíèöèàëèçèðîâàííûå
default: expected(';');
case tk_semicolon: done=1;// ;
case tk_camma: //, post global type
itok.type=tp_postvar;//11.07.05 21:57 tp_ucnovn;
SetNewTok(type,typev);
if((flag&f_extern)==0&&useStartup==TRUE&&dynamic==0){
if(SaveStartUp(ssize*elements,var_name)!=FALSE){
nexttok();
break;
}
}
if((flag&f_extern)==0&&alignword&&dynamic==0){ //âûðîâíÿòü íà ÷åòíûé àäðåñ
if(ssize==2){
if(postsize%2==1)postsize++;
}
else if(ssize==4&&postsize%4!=0)postsize+=4-(postsize%4);
}
count=FindOff((unsigned char *)var_name,VARPOST);
itok.post=dynamic+1;
itok.segm=DS;
loop=elements*ssize;
itok.number=(flag&f_extern)==0?postsize:externnum++;
itok.flag=flag;
itok.size=loop;
itok.rm=(am32==FALSE?rm_d16:rm_d32);
itok.npointr=(unsigned short)npointr;
varrec=addtotree(var_name);
varrec->count=count;
if((flag&f_extern)==0)AddPostData(loop);
nexttok();
break;
}
}
break;
case tk_undefproc:
if(tok2==tk_openbracket||nnpointr){
if(npointr)type=am32==FALSE?tk_word:tk_dword;
declare_procedure(flag,type,nnpointr);
break;
}
case tk_proc:
case tk_floatvar:
case tk_dwordvar:
case tk_longvar:
case tk_charvar:
case tk_intvar:
case tk_bytevar:
case tk_pointer:
case tk_wordvar: idalreadydefined(); nexttok(); break;
default: expected(';');
case tk_semicolon: done=1;
case tk_camma: nexttok(); break;
}
npointr=0;
}
dopoststrings();
}
void SetNewTok(int type,int typev)
{
switch(typev){
case variable:
if(type>=tk_char&&type<=tk_double)tok=type+(tk_charvar-tk_char);
break;
case pointer:
// if(type>=tk_void&&type<=tk_float){
tok=tk_pointer;
itok.type=(unsigned short)type;
// }
break;
}
}
int SaveStartUp(int size,char *var_name)
{
int i=0;
if((startStartup+size)<=endStartup){
if(alignword){ //âûðîâíÿòü íà ÷åòíûé àäðåñ
if(size==2){
if(startStartup%2==1)i=1;
}
else if(size==4&&startStartup%4!=0)i=4-(startStartup%4);
}
if((startStartup+size+i)<=endStartup){
startStartup+=i;
itok.number=startStartup;
itok.segm=DS;
itok.flag=0;
itok.post=0;
itok.rm=(am32==FALSE?rm_d16:rm_d32);
itok.type=tp_ucnovn;
addtotree(var_name);
startStartup+=size;
return TRUE;
}
}
return FALSE;
}
/* ======= ñòàðò çàãîëîâêà ïðîöåäóðû ======== */
void setuprm()
{
itok.rm=returntype=(itok.rm==tokens?am32==FALSE?tk_word:tk_dword:itok.rm);
if(itok.npointr)itok.rm=returntype=(am32==FALSE?tk_word:tk_dword);
}
void eaxToFloat(int reg=AX)
{
int next=1;
CheckMinusNum();
if(itok2.type==tp_opperand){ //ñîñòàâíîå
doeaxfloatmath(tk_reg32,reg);
next=0;
}
else{
switch(tok){
case tk_number:
if(itok.rm==tk_double)itok.fnumber=itok.dnumber;
else if(itok.rm!=tk_float){
float temp=itok.number;
*(float *)&itok.number=temp;
}
op66(r32);
op(0xb8+reg); // MOV EAX,#
outdword(itok.number);
break;
case tk_floatvar:
if(reg==AX&&itok.rm==rm_d16&&itok.sib==CODE16){
op66(r32);
outseg(&itok,1);
op(0xA1);
outword((unsigned int)itok.number);
}
else{
CheckAllMassiv(bufrm,4,&strinf);
op66(r32);
outseg(&itok,2);
op(0x8B);
op(itok.rm+reg*8);
outaddress(&itok);
}
break;
default:
if(doeaxfloatmath(tk_reg32,reg)!=tk_reg32&&reg!=AX){
if(!am32)Leave();
op66(r32);
op(0x89);
op(0xc0+reg);
}
next=0;
}
}
if(next)nexttok();
}
void CalcRegPar(int reg,int def,char **ofsstr)
{
char signflag=0;
int razr;
unsigned char oinline=useinline;
useinline=0;
// if(*ofsstr)puts(*ofsstr);
if(tok!=tk_camma){
if(tok==tk_openbracket){
nexttok();
if(tok>=tk_char&&tok<=tk_double)def=tok;
nexttok();
expectingoperand(tk_closebracket);
}
if(tok>=tk_char&&tok<=tk_double){
def=tok;
getoperand();
}
if(tok==tk_string){
op(0xB8+reg);
if(am32==FALSE)outword(addpoststring());
else outdword(addpoststring());
nexttok();
razr=(am32==FALSE?r16:r32);
}
else if(tok==tk_floatvar)eaxToFloat(reg);
else{
switch(def){
case tk_int: signflag=1;
case tk_word:
if(reg==AX)do_e_axmath(signflag,r16,ofsstr);
else getintoreg(reg,r16,signflag,ofsstr);
razr=r16;
break;
case tk_char: signflag=1;
case tk_byte:
if(reg==AX)doalmath(signflag,ofsstr);
else{
getintobeg(reg,ofsstr);
dobegmath(reg);
}
razr=r8;
break;
case tk_long: signflag=1;
case tk_dword:
if(reg==AX)do_e_axmath(signflag,r32,ofsstr);
else getintoreg(reg,r32,signflag,ofsstr);
razr=r32;
break;
case tk_float:
eaxToFloat(reg);
razr=r32;
break;
case tk_qword:
getintoreg64(reg);
doregmath64(reg);
razr=r64;
break;
case tokens:
razr=(am32==FALSE?r16:r32);
if(reg==AX)do_e_axmath(0,razr,ofsstr);
else getintoreg(reg,razr,signflag,ofsstr);
break;
}
}
AddRegistr(razr,reg);
// printf("%08X\n",reg);
}
useinline=oinline;
}
int GetTypeParam(char c)
{
switch(c){
case 'B': return tk_byte;
case 'W': return tk_word;
case 'D': return tk_dword;
case 'C': return tk_char;
case 'I': return tk_int;
case 'L': return tk_long;
case 'F': return tk_float;
case 'A': return tk_multipoint;
case 'Q': return tk_qword;
case 'E': return tk_double;
case 'S': return tk_fpust;
case 'T': return tk_struct;
case 'U': return tokens;
default:
extraparam();
// printf("%c\n",c);
return 0;
}
}
void doregparams()
{
int i=0;
char *ofsstr=NULL;
int razr;
int retreg;
ClearRegister();
if(tok!=tk_openbracket)expected('(');
while(tok2==tk_camma){
nexttok();
i++;
}
ofsstr=GetLecsem(tk_camma,tk_closebracket);
getoperand();
if(tok!=tk_closebracket){
if(strlen(param)!=0){
int def;
char *oparam=BackString(param);
for(;;){
while(tok==tk_camma){
if(ofsstr)free(ofsstr);
ofsstr=GetLecsem(tk_camma,tk_closebracket);
getoperand();
}
if((def=GetTypeParam(oparam[i++]))==0){
nexttok();
break;
}
if(def==tk_qword){
int c1,c2;
c1=oparam[i++]-0x30;
c2=oparam[i++]-0x30;
retreg=c1|(c2*256);
// printf("%08X\n",retreg);
}
else retreg=oparam[i++]-0x30;
if(ofsstr){
if((razr=getrazr(def))!=r64){
int retr;
if((retr=CheckIDZReg(ofsstr,retreg,razr))!=NOINREG){
GetEndLex(tk_camma,tk_closebracket);
if(retr!=SKIPREG)GenRegToReg(retreg,retr,razr);
nexttok();
goto endparam;
}
}
}
if(def==tk_fpust)float2stack(retreg);
else CalcRegPar(retreg,def,&ofsstr);
endparam:
if(ofsstr&&razr!=r64){
IDZToReg(ofsstr,retreg,razr);
free(ofsstr);
ofsstr=NULL;
}
if(tok!=tk_camma){
if(tok!=tk_closebracket)expected(')');
if(oparam[i]!=0)missingpar();
break;
}
}
free(oparam);
}
else{
char regpar[6]={AX,BX,CX,DX,DI,SI};
for(;i<6;i++){
if(tok==tk_camma){
if(ofsstr)free(ofsstr);
ofsstr=GetLecsem(tk_camma,tk_closebracket);
getoperand();
if(tok==tk_camma)continue;
}
retreg=regpar[i];
if(ofsstr&&tok!=tk_camma){
razr=(am32==FALSE?r16:r32);
int retr;
if((retr=CheckIDZReg(ofsstr,retreg,razr))!=NOINREG){
GetEndLex(tk_camma,tk_closebracket);
if(retr!=SKIPREG)GenRegToReg(retreg,retr,razr);
nexttok();
goto endparam1;
}
}
CalcRegPar(retreg,tokens,&ofsstr);
endparam1:
if(ofsstr){
IDZToReg(ofsstr,retreg,razr);
free(ofsstr);
ofsstr=NULL;
}
if(tok!=tk_camma){
if(tok!=tk_closebracket)expected(')');
break;
}
}
}
setzeroflag=FALSE;
}
if(ofsstr)free(ofsstr);
}
int CheckUses()
{
int i;
int regs=0;
int bracket=FALSE;
memset((SAVEREG *)psavereg,0,sizeof(SAVEREG));
if(tok==tk_openbracket){
if(stricmp(itok2.name,"uses")==0){
bracket=TRUE;
nexttok();
}
else return 0;
}
if(stricmp(itok.name,"uses")==0){
nexttok();
while(tok==tk_reg32||tok==tk_reg||tok==tk_beg){
i=r32;
switch(tok){
case tk_beg:
if(itok.number>3)itok.number-=4;
i=(am32+1)*2;
break;
case tk_reg:
if(!am32)i=r16;
break;
}
regs=regs|(1<<itok.number);
psavereg->reg[itok.number]=i;
i=1;
if((am32&&i==r16)||(am32==0&&i==r32))i=2;
psavereg->size+=i;
nexttok();
if(tok==tk_camma)nexttok();
}
if(strcmp(itok.name,"allregs")==0){
psavereg->size=1;
psavereg->all=1;
regs=dEAX|dEBX|dECX|dEDX|dEBP|dEDI|dESI;
nexttok();
}
}
if(bracket)expecting(tk_closebracket);
return regs;
}
void Enter()
{
if(ESPloc==FALSE||am32==FALSE){
op(0x55); //push bp
outword(0xe589);//mov bp,sp
}
}
void setproc(int defflag)
{
char *bstring;
unsigned char oinline,ooptimizespeed;
ITOK otok;
unsigned int i;
int regs=0;
unsigned char oESPloc=ESPloc;
int startline=linenumber;
unsigned int oregidx;
clearregstat();
addESP=inlineflag=0;
oinline=useinline;
ooptimizespeed=optimizespeed;
oregidx=*(unsigned int *)&idxregs;
current_proc_type=itok.flag;
if(itok.flag&f_extern)notexternfun(); //new 18.04.07 12:20
// printf("%s tok=%d flag=%08X\n",itok.name,tok,itok.flag);
tok=lastcommand=tk_proc;
itok.number=outptr;
if(itok.segm<NOT_DYNAMIC)itok.segm=DYNAMIC_SET;
setuprm();
// printf("rm=%d %s\n",itok.rm,itok.name);
if(defflag){ //ðàíåå óæå áûëè âûçîâû
// updatecall(updatetree(),(unsigned int)itok.number,0);
regs=itok.post;
if(updatecall(updatetree(),(unsigned int)itok.number,0)==-1&&
strcmp(itok.name,mesmain)==0/*&&jumptomain!=CALL_NONE*/){
itok.number=outptr=outptr-(jumptomain==CALL_SHORT?2:am32==FALSE?3:5);
if(dbg){
KillLastLine();
KillLastLine();
AddLine();
}
updatetree();
}
}
else{ //èíà÷å äîáàâèòü â äåðåâî
string[0]=0;
itok.type=tp_ucnovn;
addtotree(itok.name);
}
// puts(itok.name);
if((i=FindOff((unsigned char *)itok.name,CS))!=0){
itok.rec->count=i;
}
bstring=BackString((char *)string);
otok=itok;
if(strcmp(mesmain,otok.name)==0){
if(startuptomain==TRUE&&comfile==file_com)doprestuff();
if(numdomain!=0){
for(i=0;i<numdomain;i++){
strcpy(itok.name,domain+i*IDLENGTH);
tok=tk_ID;
searchvar(itok.name,0);
switch(tok){
case tk_ID:
case tk_id:
tobedefined(am32==FALSE?CALL_NEAR:CALL_32,tk_void);
(postbuf+posts-1)->loc=outptr+1;
callloc0(); /* produce CALL [#] */
break;
case tk_declare:
tok=tk_undefproc;
updatetree();
case tk_undefproc:
addacall(itok.number,(unsigned char)((itok.flag&f_extern)!=0?CALL_EXT:(am32!=FALSE?CALL_32:CALL_NEAR)));
callloc0(); /* produce CALL [#] */
break;
case tk_proc:
if(itok.flag&f_far)op(0x0e); //push cs
if(itok.segm<NOT_DYNAMIC){
addacall(itok.number,(unsigned char)(am32!=FALSE?CALL_32:CALL_NEAR));
itok.number=0;
}
callloc(itok.number);
break;
default:
preerror("impossible type for startup function");
break;
}
}
numdomain=0;
free(domain);
}
}
nextexpecting2(tk_openbracket);
startblock();
if(searchteg&&(!(current_proc_type&f_static))&&(current_proc_type&f_typeproc)!=tp_pascal)AddThis();
if(tok!=tk_closebracket){
if((current_proc_type&f_typeproc)!=tp_fastcall){
declareparams();
if(otok.type==tp_declare&&defflag&&strcmp(bstring,param)!=0){
// printf("old=%s new=%s\n",bstring,param);
redeclare(otok.name);
}
// if(bstring[0]!=0&&bstring[0]!='A'&&strcmp(bstring,param)!=0)redeclare();
}
else{
declareparamreg();
}
if(bstring)free(bstring);
bstring=BackString((char *)param);
}
else if((current_proc_type&f_typeproc)!=tp_fastcall&&bstring[0]!=0){
if(bstring[0]!='V'&&bstring[0]!='A'){
redeclare(otok.name);
// puts(bstring);
}
}
strcpy((char *)string,bstring);
itok=otok;
tok=tk_proc;
updatetree();
if(searchteg&&(!(current_proc_type&f_static))&&(current_proc_type&f_typeproc)==tp_pascal)AddThis();
nexttok();
blockproc=TRUE;
// printf("tok=%d\n",tok);
if(tok==tk_inline){
inlineflag=1;
nexttok();
}
else if(paramsize)Enter(); // PUSH BP MOV BP,SP
if(tok==tk_colon&&(current_proc_type&fs_constructor)!=0){
do{
AddBackBuf(inptr2,cha2);
}while(tok==tk_camma);
nexttok();
}
regs|=CheckUses();
CorrectParamVar();
if(tok!=tk_openbrace)declarelocals(0,inlineflag);
#ifdef OPTVARCONST
ClearLVIC();
#endif
// numblocks++; //íà ýòîì ìåñòå äëÿ ðàíåãî îïðåäåëåíèÿ ::var
expecting(tk_openbrace);
declarelocals(1,inlineflag);
retproc=FALSE;
if(paramsize||localsize/*||(lstructlist!=NULL)*/){
initBP=1;
if(inlineflag)warninline();
}
#ifdef __NEWLEX__
doblockstart(otok.name);
#endif
doblock2(); // do proc
if(current_proc_type&fs_destructor){
elementteg *bazael=searchteg->baza;
for(i=0;i<searchteg->numoper;i++){
if((bazael+i)->tok==tk_baseclass)CallDestructor((structteg *)(bazael+i)->rec);
}
}
i=numreturn;
setreturn();
if(inlineflag==0&&retproc==FALSE&&(i||(lastcommand!=tk_goto&&lastcommand!=tk_GOTO)))leaveproc();
endblock();
initBP=0;
strcpy((char *)string,bstring);
itok=otok;
tok=tk_proc;
itok.size=outptr-procedure_start;
itok.rec->recpost=regs;
// printf("reg=%08X set=%s\n",regs,itok.name);
#ifdef OPTVARCONST
if(inlineflag)itok.flag|=f_useidx;
#endif
updatetree();
if(mapfile)mapfun(startline);
i=linenumber;
linenumber=startline;
killlocals();
linenumber=i;
free(bstring);
optimizespeed=ooptimizespeed;
useinline=oinline;
*(unsigned int *)&idxregs=oregidx;
if(searchteg)searchteg=NULL;
blockproc=FALSE;
ESPloc=oESPloc;
nexttok();
}
void insertproc(/*int sizepar*/)
{
unsigned char oinline,ooptimizespeed;
struct treelocalrec *otlr;
struct structteg *olteglist;
//struct idrec *olstructlist;
struct idrec *rec;
unsigned int oparamsize;
unsigned int olocalsize;
unsigned char oinsertmode;
unsigned int onumblocks; //íîìåð âëîæåííîãî áëîêà
unsigned int osizestack;
RETLIST *olistreturn;
unsigned int onumreturn;
int oinlineflag;
SAVEREG *osavr;
unsigned int oaddESP=addESP;
addESP=0;
clearregstat();
osavr=psavereg;
psavereg=(SAVEREG*)MALLOC(sizeof(SAVEREG));
oinsertmode=insertmode;
insertmode=TRUE; //ôëàã ðåæèìà âñòàâêè
oinline=useinline;
ooptimizespeed=optimizespeed;
current_proc_type=itok.flag;
rec=itok.rec;
otlr=tlr;
olteglist=ltegtree;
// olstructlist=lstructlist;
oinlineflag=inlineflag;
osizestack=sizestack;
sizestack=0;
tlr=NULL;
ltegtree=NULL;
// lstructlist=0;
oparamsize=paramsize;
olocalsize=localsize;
onumblocks=numblocks;
olistreturn=listreturn;
onumreturn=numreturn;
paramsize=0;
localsize=0;
numblocks=0; //íîìåð âëîæåííîãî áëîêà
listreturn=NULL;
numreturn=0;
inlineflag=0;
nextexpecting2(tk_openbracket);
if(tok!=tk_closebracket){
if((current_proc_type&f_typeproc)!=tp_fastcall)declareparams();
else declareparamreg();
}
CorrectParamVar();
nexttok();
if(tok==tk_inline){
nexttok();
inlineflag=1;
expecting(tk_openbrace);
}
else{
if((current_proc_type&f_typeproc)!=tp_fastcall&&paramsize>0)Enter(); // PUSH BP MOV BP,SP
rec->recpost|=CheckUses();
if(tok!=tk_openbrace)declarelocals(0);
expecting(tk_openbrace);
declarelocals(1);
}
retproc=FALSE;
#ifdef OPTVARCONST
ClearLVIC();
#endif
startblock();
doblock2();
sizestack=osizestack; // do proc
setreturn();
endblock();
RestoreSaveReg();
if(inlineflag==0&&(localsize||paramsize)&&(ESPloc==FALSE||am32==FALSE))Leave();
killlocals(/*0*/);
optimizespeed=ooptimizespeed;
useinline=oinline;
paramsize=oparamsize;
localsize=olocalsize;
tlr=otlr;
ltegtree=olteglist;
// lstructlist=olstructlist;
insertmode=oinsertmode;
numblocks=onumblocks;
listreturn=olistreturn;
numreturn=onumreturn;
inlineflag=oinlineflag;
free(psavereg);
psavereg=osavr;
addESP=oaddESP;
// nexttok();
// printf("tok=%d\n",tok);
}
void AddTypeVar(int type,int pos)
{
switch(type){
case tk_char:
param[pos]='C';
break;
case tk_byte:
param[pos]='B';
break;
case tk_int:
param[pos]='I';
break;
case tk_word:
param[pos]='W';
break;
case tk_long:
param[pos]='L';
break;
case tk_dword:
param[pos]='D';
break;
case tk_float:
param[pos]='F';
break;
case tk_qword:
param[pos]='Q';
break;
case tk_double:
param[pos]='E';
break;
}
}
void declareparamreg() /* declare procedure parameters */
{
int i=0,num=1;
unsigned char j=0;
do{
if(tok>=tk_char&&tok<=tk_double){
AddTypeVar(tok,i++);
nexttok();
j=1;
}
else{
switch(tok){
case tk_beg:
if(j==0)param[i++]='B';
param[i++]=(char)(itok.number+0x30);
j=0;
break;
case tk_reg:
if(j==0)param[i++]='W';
param[i++]=(char)(itok.number+0x30);
j=0;
break;
case tk_reg32:
if(j==0)param[i++]='D';
param[i++]=(char)(itok.number+0x30);
j=0;
break;
case tk_reg64:
param[i++]='Q';
param[i++]=(char)((itok.number&255)+0x30);
param[i++]=(char)((itok.number/256)+0x30);
j=0;
break;
case tk_fpust:
param[i++]='S';
param[i++]=(char)(itok.number+0x30);
j=0;
break;
case tk_closebracket:
if(j==0)goto endproc;
default: edpip(num);
}
nexttok();
if(tok==tk_camma){
if(j!=0){
edpip(num);
param[i++]='0';
j=0;
}
nexttok();
}
}
num++;
}while(tok!=tk_closebracket);
endproc:
if(j!=0){
edpip(num-1);
param[i++]='0';
}
param[i]=0;
}
void AddMultiPoint(int pos)
{
param[pos]='A';
nexttok();
if(tok!=tk_closebracket)SwTok(tk_closebracket);
}
void declareparamstack() /* declare procedure parameters */
{
int i=0,num=1;
unsigned char j=0;
/*
1 - îáúÿâëåí òèï
2 - áûëà çàïÿòàÿ
3 - áûëà òî÷êà ñ çàïÿòîé
4 -
5 - áûë èäåíòèôèêàòîð
6 - òèï void
*/
int typevar=tk_multipoint;
structteg *tteg=NULL;
int size;
do{
if(tok==tk_struct)nexttok();
if(tok>=tk_char&&tok<=tk_double){
if(j>3||j==1)edpip(num);
j=1;
typevar=tok;
nexttok();
}
else if((tteg=FindTeg(TRUE))!=NULL){
size=Align(tteg->size,(am32+1)*2);
// printf("%s size=%u\n",itok.name,size);
j=1;
typevar=tk_struct;
nexttok();
}
while(tok==tk_mult){
param[i++]='*';
nexttok();
}
if(tok==tk_camma){
if(j==1){
if(typevar==tk_struct)i+=sprintf(&param[i],"T%u",size);
else AddTypeVar(typevar,i++);
}
else if(j!=5)edpip(num);
j=2;
num++;
}
else if(tok==tk_semicolon){
if(j==1){
if(typevar==tk_struct)i+=sprintf(&param[i],"T%u",size);
else AddTypeVar(typevar,i++);
}
else if(j!=5)edpip(num);
j=3;
num++;
}
else if(tok==tk_multipoint){
AddMultiPoint(i++);
break;
}
else if(tok==tk_closebracket){
if(j==0)param[i++]='A';
else if(j==1){
if(typevar==tk_struct)i+=sprintf(&param[i],"T%u",size);
else AddTypeVar(typevar,i++);
}
else if(j<4)edpip(num);
break;
}
else if(tok==tk_void){
if(j!=0)edpip(num);
param[i++]='V';
j=6;
}
else if(tok==tk_beg||tok==tk_reg||tok==tk_reg32||tok==tk_reg64||tok==tk_fpust){
if(j==1){
if(typevar==tk_struct)i+=sprintf(&param[i],"T%u",size);
else AddTypeVar(typevar,i++);
}
else if(j<4){
switch(tok){
case tk_beg: param[i++]='B'; break;
case tk_reg: param[i++]='W'; break;
case tk_reg32: param[i++]='D'; break;
case tk_fpust: param[i++]='S'; break;
case tk_reg64:
param[i++]='Q';
param[i++]=(char)((itok.number&255)+0x30);
itok.number/=256;
break;
}
}
else edpip(num);
param[i++]=(char)(itok.number+0x30);
j=5;
}
else{
if(j==1||j==2){
if(typevar==tk_struct)i+=sprintf(&param[i],"T%u",size);
else AddTypeVar(typevar,i++);
}
else edpip(num);
j=5;
}
nexttok();
}while(tok!=tk_eof);
param[i]=0;
// puts(param);
}
void CorrectParamVar()
{
unsigned int addnum;
int fspin;
struct localrec *ptr;
if(paramsize==0)return;
if(insertmode)addnum=0; //ret-address
else addnum=2;
if(ESPloc==FALSE||am32==FALSE)addnum+=2; //EBP
if((current_proc_type&f_far))addnum+=2;// move over seg on stack
if(am32)addnum*=2;
if((current_proc_type&f_typeproc)==tp_cdecl||(current_proc_type&f_typeproc)==tp_stdcall)fspin=FALSE;
else fspin=TRUE;
treelocalrec *ntlr=tlr;
while(ntlr&&ntlr->level>1)ntlr=ntlr->next;
for(ptr=ntlr->lrec;;ptr=ptr->rec.next){
if(ptr->rec.type==tp_paramvar){
if(fspin)ptr->rec.recnumber=paramsize-ptr->rec.recnumber-Align(ptr->rec.recsize,am32==FALSE?2:4);
ptr->rec.recnumber+=addnum;
}
if(ptr->rec.next==NULL)break;
}
}
void declareparams() /* declare procedure parameters */
{
int paramtok,sparamtok,i=0,type;
char flag=33;
int numpointr;
localrec *lrec;
structteg *tteg=NULL,*nteg;
do{
if(flag!=33)nexttok();
flag=1;
if(tok==tk_multipoint){
AddMultiPoint(i++);
break;
}
if(tok==tk_void){
param[i++]='V';
nexttok();
if(tok!=tk_closebracket)SwTok(tk_closebracket);
break;
}
if(tok>=tk_char&&tok<=tk_double){
type=tok;
SetNewTok(tok,variable);
paramtok=tok;
}
else if(tok==tk_beg||tok==tk_reg||tok==tk_reg32||tok==tk_reg64||tok==tk_fpust)flag=3;
else{
if(tok==tk_struct)nexttok();
if((tteg=FindTeg(TRUE))!=NULL)paramtok=tk_struct;
else{
datatype_expected();
flag=0;
nexttok();
}
}
if(flag){
do{
numpointr=0;
skipfind=TRUE;
if(flag!=3)nexttok();
while(tok==tk_mult){
nexttok();
numpointr++;
param[i++]='*';
}
if(tok==tk_id||tok==tk_ID){ //ïðîâåðèòü íà òèïû îïðåäåëåííûå ÷åðåç define
skipfind=FALSE;
int otok=tok;
searchtree(&ptok,&otok,string);
if(otok>=tk_char&&otok<=tk_double){
tok=otok;
itok=ptok;
}
skipfind=TRUE;
}
if(tok==tk_struct){
nexttok();
if((tteg=FindTeg(TRUE))!=NULL){
paramtok=tk_struct;
nexttok();
}
else{
edpip();
nexttok();
goto endparam1;
}
}
else {
if((nteg=FindTeg(TRUE))!=NULL){
tteg=nteg;
paramtok=tk_struct;
nexttok();
}
else{
if(tok>=tk_char&&tok<=tk_double){
type=tok;
SetNewTok(tok,variable);
paramtok=tok;
nexttok();
while(tok==tk_mult){
nexttok();
numpointr++;
param[i++]='*';
}
flag=2;
}
skipfind=FALSE;
if(tok==tk_beg||tok==tk_reg||tok==tk_reg32||tok==tk_reg64||tok==tk_fpust){
if(flag==2)AddTypeVar(type,i++);
else{
switch(tok){
case tk_beg: param[i++]='B'; break;
case tk_reg: param[i++]='W'; break;
case tk_reg32: param[i++]='D'; break;
case tk_fpust: param[i++]='S'; break;
case tk_reg64:
param[i++]='Q';
param[i++]=(char)((itok.number&255)+0x30);
itok.number/=256;
break;
}
}
param[i++]=(unsigned char)(itok.number+0x30);
flag=1;
goto endparam1;
}
}
}
sparamtok=paramtok;
if(tok==tk_multipoint){
AddMultiPoint(i++);
break;
}
if(tok!=tk_ID&&tok!=tk_id){
idalreadydefined();
break;
}
int lsize;
if(am32)lsize=4;
else{
lsize=2;
if(sparamtok>=tk_longvar&&sparamtok<=tk_floatvar&&numpointr==0)
lsize+=2;//add 2 more bytes
}
if((sparamtok==tk_qwordvar||sparamtok==tk_doublevar)&&numpointr==0)lsize=8;
AddTypeVar(type,i++);
if(sparamtok==tk_struct){
//idrec *newrec,*trec;
lsize=Align(tteg->size,(am32+1)*2);
i+=sprintf(&param[i],"T%u",lsize);
// newrec=(struct idrec *)MALLOC(sizeof(struct idrec));
// if(lstructlist==NULL)lstructlist=newrec;
// else{
// trec=lstructlist;
// while(trec->left!=NULL)trec=trec->left;
// trec->left=newrec;
// }
// newrec->right=newrec->left=NULL;
lrec=addlocalvar(itok.name,tk_structvar,paramsize);
lrec->rec.newid=(char *)tteg;
lrec->rec.flag=tteg->flag;
lrec->rec.recrm=1;
lrec->rec.recpost=LOCAL;
goto endparam;
}
lrec=addlocalvar(itok.name,sparamtok,paramsize);
lrec->rec.npointr=(unsigned short)numpointr;
endparam:
lrec->rec.type=tp_paramvar;
lrec->rec.recsize=lsize;
paramsize+=lsize;
endparam1:
nexttok();
}while(tok==tk_camma);
}
}while(tok==tk_semicolon);
param[i]=0;
// puts(param);
}
void CharToBackBuf(char c)
{
if(SizeBackBuf==0){
MaxSizeBackBuf=STRLEN;
BackTextBlock=(char *)MALLOC(STRLEN);
}
else if(SizeBackBuf==MaxSizeBackBuf){
MaxSizeBackBuf+=STRLEN;
BackTextBlock=(char *)REALLOC(BackTextBlock,MaxSizeBackBuf);
}
BackTextBlock[SizeBackBuf++]=c;
}
void AddBackBuf(int oinptr,char ocha)
//ñîçäàòü ëèñòèíã íà÷àëüíîé èíèöèàëèçàöèè ëîñàëüíûõ ïåðåìåííûõ
{
int numblock=0;
unsigned char save;
char bcha;
inptr=oinptr;
cha=ocha;
for(;;){
save=TRUE;
switch(cha){
case '(':
case '{':
case '[':
numblock++;
break;
case ')':
case '}':
case ']':
numblock--;
if(numblock<0)return;
break;
case ',':
if(numblock>0)break;
tok=tk_camma;
goto endp;
case ';':
case 26:
tok=tk_semicolon;
endp:
CharToBackBuf(';');
nextchar();
inptr2=inptr;
cha2=cha;
return;
case '/': //îòñëåäèòü êîììåíòàðèè
nextchar();
if(cha=='*'){
do{
nextchar();
if(cha=='*'){
nextchar();
if(cha=='/'){
save=FALSE;
break;
}
}
}while(cha!=26);
}
else if(cha=='/'){
do{
nextchar();
}while(cha!=13&&cha!=26);
}
else CharToBackBuf('/');
break;
case '"':
case '\'':
bcha=cha;
do{
CharToBackBuf(cha);
nextchar();
if(cha=='\\'){
CharToBackBuf(cha);
nextchar();
CharToBackBuf(cha);
nextchar();
}
}while(cha!=bcha);
break;
}
if(save)CharToBackBuf(cha);
nextchar();
}
}
void RunBackText()
{
ITOK oitok,ostructadr;
SINFO ostr;
unsigned char *oldinput;
unsigned int oldinptr,oldendinptr;
unsigned char bcha;
int otok,otok2;
char *ostartline;
char *ostring,*obufrm;
COM_MOD *ocurmod;
ostring=BackString((char *)string);
oldinput=input; //ñîõð íåêîòîð ïåðåìåíûå
oldinptr=inptr2;
ostructadr=structadr;
bcha=cha2;
oldendinptr=endinptr;
otok=tok;
otok2=tok2;
oitok=itok;
ostr=strinf;
strinf.bufstr=NULL;
obufrm=bufrm;
bufrm=NULL;
ocurmod=cur_mod;
cur_mod=NULL;
input=(unsigned char *)BackTextBlock;
inptr2=1;
cha2=input[0];
tok=tk_openbrace;
SizeBackBuf=0;
ostartline=startline;
startline=(char*)input;
endinptr=strlen((char *)input);
endinput=startline+endinptr;
doblock();
endoffile=0;
startline=ostartline;
strinf=ostr;
free(input);
input=oldinput;
inptr2=oldinptr;
cha2=bcha;
endinptr=oldendinptr;
tok=otok;
itok=oitok;
if(bufrm)free(bufrm);
bufrm=obufrm;
tok2=otok2;
strcpy((char *)string,ostring);
if(strinf.bufstr)free(strinf.bufstr);
structadr=ostructadr;
free(ostring);
cur_mod=ocurmod;
}
int PushLocInit(int ofs)
{
ITOK oitok,ostructadr,wtok;
SINFO ostr;
unsigned char *oldinput;
unsigned int oldinptr,oldendinptr;
unsigned char bcha;
int otok,otok2;
char *ostartline;
char *ostring,*obufrm;
int retcode=FALSE;
// if(bufrm)puts(bufrm);
ostring=BackString((char *)string);
oldinput=input; //ñîõð íåêîòîð ïåðåìåíûå
oldinptr=inptr2;
ostructadr=structadr;
bcha=cha2;
oldendinptr=endinptr;
otok=tok;
otok2=tok2;
oitok=itok;
ostr=strinf;
strinf.bufstr=NULL;
obufrm=bufrm;
bufrm=NULL;
input=(unsigned char *)BackTextBlock;
inptr2=ofs;
ostartline=startline;
cha2=input[inptr2++];
endinptr=strlen((char *)input);
startline=(char *)input+ofs;
endinput=startline+endinptr;
nexttok();
wtok=itok;
nexttok();
nexttok();
if((retcode=Push(&wtok))!=FALSE){
retcode=TRUE;
for(inptr2=ofs;;inptr2++){
cha2=input[inptr2];
input[inptr2]=' ';
if(cha2==';'||cha2==0)break;
}
}
endoffile=0;
startline=ostartline;
strinf=ostr;
input=oldinput;
inptr2=oldinptr;
cha2=bcha;
endinptr=oldendinptr;
tok=otok;
itok=oitok;
if(bufrm)free(bufrm);
bufrm=obufrm;
tok2=otok2;
strcpy((char *)string,ostring);
if(strinf.bufstr)free(strinf.bufstr);
structadr=ostructadr;
free(ostring);
return retcode;
}
int pushinit(int localline,unsigned int ofs)
{
int oline=linenumber;
COM_MOD *bcur_mod;
int retcode;
linenum2=localline;
bcur_mod=cur_mod;
cur_mod=NULL;
retcode=PushLocInit(ofs);
cur_mod=bcur_mod;
linenumber=linenum2=oline;
return retcode;
}
int PossiblePush()
{
int retcode=FALSE;
nexttok();
switch(tok){
case tk_dwordvar:
case tk_longvar:
case tk_reg32:
if(am32==FALSE)break;
case tk_postnumber:
case tk_string:
case tk_intvar:
case tk_wordvar:
case tk_reg:
if(tok2==tk_semicolon||tok2==tk_camma)retcode=TRUE;
break;
case tk_undefofs:
tok=tk_number;
goto chnum;
case tk_minus:
if(tok2!=tk_number)break;
nexttok();
case tk_number:
chnum:
doconstlongmath();
if(tok==tk_semicolon||tok==tk_camma)retcode=TRUE;
break;
}
//// New 20.07.07 22:01
if(bufrm){
free(bufrm);
bufrm=NULL;
}
if(strinf.bufstr){
free(strinf.bufstr);
strinf.bufstr=NULL;
}
////////////////////////////
return retcode;
}
#define MAXLOCVAR 128
void declarelocals(int mode,int finline) /* declare locals */
/*-----------------01.06.02 15:12-------------------
mode = 0 if local vars prior {
mode = 1 if local vars after {
--------------------------------------------------*/
{
unsigned int size,ssize,localtok;
int binptr;
int flag=0;
char bcha;
int slocaltok;
int numpointr,type;
unsigned int loop;
static int localline;
static int numinit;
static int maxlocvar;
static LILV *lilv=NULL;
static int headerinit;
if(localsize==0)localline=0;
if(lilv==NULL){
numinit=0;
lilv=(LILV *)MALLOC(sizeof(LILV)*MAXLOCVAR);
maxlocvar=MAXLOCVAR;
if(paramsize&&(!finline))headerinit=TRUE;
else headerinit=FALSE;
}
dynamic_flag=0;
do{
while(tok==tk_semicolon)nexttok();
if(tok==tk_static){
flag|=f_static;
nexttok();
}
size=0;
switch(tok){
case tk_union:
loop=dounion(0,flag);
goto locstruct;
case tk_struct:
loop=LocalStruct(flag,&localline);
locstruct:
(lilv+numinit)->size=-loop;
break;
case tk_int: localtok=tk_intvar; size=2; break;
case tk_word: localtok=tk_wordvar; size=2; break;
case tk_char: localtok=tk_charvar; size=1; break;
case tk_byte: localtok=tk_bytevar; size=1; break;
case tk_long: localtok=tk_longvar; size=4; break;
case tk_dword: localtok=tk_dwordvar; size=4; break;
case tk_float: localtok=tk_floatvar; size=4; break;
case tk_qword: localtok=tk_qwordvar; size=8; break;
case tk_double: localtok=tk_doublevar; size=8; break;
default:
if((tok>=tk_bits&&tok<=tk_doublevar)||tok==tk_pointer||tok==tk_proc
||tok==tk_declare||tok==tk_undefproc||tok==tk_structvar||
(FindTeg(FALSE)==NULL&&FindTeg(TRUE)==NULL)){
if(mode==0){
(lilv+numinit)->size=0;
datatype_expected();
nexttok();
}
else{
if(localsize){
if(!finline){
numpointr=0;
if(SizeBackBuf){
BackTextBlock[SizeBackBuf]=0;
for(type=numinit-1,numpointr=0;type>=0;type--){//îïð ÷èñëî èíèö. ïåðåìåííûõ â êîíöå
if((lilv+type)->size<=0)break;
numpointr+=(lilv+type)->size;
}
type++; //÷èñëî îñòàâøèõñÿ ïåðåìåííûõ
ssize=type;
}
size=localsize;
if(lilv->size<=0&&optimizespeed==0&&chip>1){
size-=numpointr;
if(headerinit)outptr-=3; /* remove PUSH BP and MOV BP,SP */
op(0xC8); /* ENTER */
outword(size); /* # of locals */
op(0x00); /* level = 0 */
flag=0;
type=0;
headerinit=TRUE;
size=numpointr;
}
else{
if(headerinit==FALSE){
Enter();
headerinit=TRUE;
}
flag=1;
}
if(SizeBackBuf){
if(lilv->size>0){ //åñòü èíèö ïåðåìåííûå â íà÷àëå
for(loop=0;loop<numinit;loop++){
// printf("size%d=%d %s\n",loop,(lilv+loop)->size,BackTextBlock);
if((lilv+loop)->size<=0)break;
if(pushinit(localline,(lilv+loop)->ofs)==FALSE)break;
(lilv+loop)->rec->fuse|=INITVAR;
size-=Align((lilv+loop)->size,(am32==FALSE?2:4));
type--;
}
}
if(size){
binptr=size-numpointr;
if(binptr){
if(!optimizespeed&&type<3&&(type*(am32+1)*2)>=binptr)for(;type!=0;type--)op(0x50+ECX);
else{
if(binptr<128){
outword(0xEC83);
op(binptr);
}
else{
outword(0xEC81);
if(am32==FALSE)outword(binptr);
else outdword((unsigned long)binptr);
}
}
}
if(numpointr){
for(;ssize<numinit;ssize++){
// printf("size%d=%d %s\n",loop,(lilv+loop)->size,BackTextBlock);
if(pushinit(localline,(lilv+ssize)->ofs)==FALSE)break;
(lilv+ssize)->rec->fuse|=INITVAR;
}
}
}
}
else if(flag){
if(localsize<128){
outword(0xEC83);
op(localsize);
}
else{
outword(0xEC81);
if(am32==FALSE)outword(localsize);
else outdword((unsigned long)localsize);
}
}
}
else{ //finline
if(SizeBackBuf!=0){
free(BackTextBlock);
SizeBackBuf=0;
}
}
}
if(psavereg->size){
if(psavereg->all){
op(0x60);
addESP+=am32==FALSE?16:32;
}
else{
for(int i=0;i<8;i++){
if(psavereg->reg[i]){
op66(psavereg->reg[i]);
op(0x50+i);
addESP+=am32==FALSE?2:4;
}
}
}
if(ESPloc&&am32&&(itok.type==tp_localvar||itok.type==tp_paramvar))itok.number+=addESP;
}
// printf("numinit=%d firstinit=%d\n%s\n",numinit,firstinit,BackTextBlock);
if(SizeBackBuf!=0){
CharToBackBuf('}');
CharToBackBuf(0);
int oline=linenumber;
linenum2=localline;
COM_MOD *bcur_mod;
bcur_mod=cur_mod;
cur_mod=NULL;
RunBackText();
cur_mod=bcur_mod;
linenumber=linenum2=oline;
}
if(lilv){
free(lilv);
lilv=NULL;
}
return;
}
}
else{
loop=LocalStruct(flag,&localline);
(lilv+numinit)->size=-loop;
}
break;
}
if(size!=0){
do{
binptr=inptr2;
bcha=cha2;
skipfind=TRUE; //çàïðåòèòü èñêàòü â ãëîáàëüíîì äåðåâå
nexttok();
if(tok==tk_static){
flag|=f_static;
binptr=inptr2;
bcha=cha2;
nexttok();
}
slocaltok=localtok;
ssize=size;
numpointr=0;
type=tp_localvar;
while(tok==tk_mult){
binptr=inptr2;
bcha=cha2;
nexttok();
numpointr++;
}
if(tok!=tk_ID&&tok!=tk_id)idalreadydefined();
else{
long numcopyvar;
numcopyvar=1;
localrec *lrec=addlocalvar(itok.name,slocaltok,(flag&f_static)==0?localsize:postsize);
loop=ssize;
if(numpointr)loop=am32==TRUE?4:2;
skipfind=FALSE; //ðàçðåøèòü ïîèñê â ãëîáàëüíîì äåðåâå
if(tok2==tk_openblock){//[
nexttok();
nexttok();
CheckMinusNum();
if(tok!=tk_number){
numexpected();
nexttok();
}
else numcopyvar=doconstlongmath();
loop=numcopyvar*ssize;
if(tok!=tk_closeblock)expected(']');
}
lrec->rec.recsize=loop;
if(!mode){
nexttok();
}
if(flag&f_static){
if(tok==tk_assign||(mode&&tok2==tk_assign)){
if(mode)nexttok();
if(numpointr){
type=tk_char+slocaltok-tk_charvar;
slocaltok=tk_pointer;
}
lrec->rec.rectok=slocaltok;
lrec->rec.recnumber=0;
lrec->rec.recpost=DYNAMIC_VAR;
lrec->rec.line=linenumber;
lrec->rec.file=currentfileinfo;
lrec->rec.count=0;
// lptr->rec.type=(unsigned short)type;
lrec->rec.npointr=(unsigned short)numpointr;
lrec->rec.sbuf=dynamic_var();
lrec->rec.recsib=type;
lrec->rec.type=tp_gvar;
// if(strcmp(lrec->rec.recid,"nnil")==0)crec=&lrec->rec;
}
else{
lrec->rec.type=tp_postvar;
AddPostData(loop);
if(mode)nexttok();
}
}
else{
lrec->rec.type=tp_localvar;
lrec->rec.npointr=(unsigned short)numpointr;
localsize+=loop;
if(mode)nexttok();
(lilv+numinit)->size=-loop;
if(tok==tk_assign){
if(localline==0)localline=linenumber;
if(numcopyvar!=1){
int i=binptr;
while(input[i]!='[')i++;
i++;
input[i]='0';
i++;
for ( int j=1;j!=0;i++){
switch(input[i]){
case '[':
j++;
break;
case ']':
j--;
break;
}
if(j!=0)input[i]= ' ';
}
}
else{
switch(slocaltok){
case tk_floatvar:
case tk_doublevar:
case tk_qwordvar:
// (lilv+numinit)->ofs=-1;
break;
default:
if(PossiblePush()){
(lilv+numinit)->size=loop;
(lilv+numinit)->rec=lrec;
}
break;
}
}
(lilv+numinit)->ofs=SizeBackBuf;
AddBackBuf(binptr,bcha);
// if(bufrm)puts(bufrm);
}
numinit++;
if(numinit==maxlocvar){
maxlocvar+=MAXLOCVAR;
lilv=(LILV *)REALLOC(lilv,maxlocvar*sizeof(LILV));
}
lrec->rec.recnumber=-lrec->rec.recnumber-Align(loop,(am32==FALSE?2:4));
}
}
if(localsize)localsize=Align(localsize,(am32==FALSE?2:4));
}while(tok==tk_camma);
seminext();
}
else{
numinit++;
if(numinit==maxlocvar){
maxlocvar+=MAXLOCVAR;
lilv=(LILV *)REALLOC(lilv,maxlocvar*sizeof(LILV));
}
}
flag=0;
// printf("tok=%d %s\n",tok,BackTextBlock);
}while(tok!=tk_openbrace&&tok!=tk_eof);
}
int CheckDeclareProc()
{
unsigned int i=inptr2-1;
while(input[i]!='('){
i++;
if(i>=endinptr){
unexpectedeof();
break;
}
}
lab1:
i++;
for(int j=1;j!=0;i++){
char c=input[i];
if(c=='(')j++;
else if(c==')')j--;
if(i>=endinptr){
unexpectedeof();
break;
}
}
for(;;i++){
if(input[i]=='(')goto lab1;
if(input[i]>' ')break;
if(i>=endinptr){
unexpectedeof();
break;
}
}
for(;;i++){
if(input[i]==';'||input[i]==',')return TRUE; //îáúÿâëåíèå ïðîöåäóðû
if(input[i]>' ')break;
if(i>=endinptr){
unexpectedeof();
break;
}
}
return FALSE;
}
void IsUses(idrec *rec)
{
int i;
if(tok==tk_openbracket&&stricmp(itok2.name,"uses")==0){
nexttok();
i=0;
nexttok();
while(tok==tk_reg32||tok==tk_reg||tok==tk_beg){
if(tok==tk_beg&&itok.number>3)itok.number-=4;
i=i|(1<<itok.number);
nexttok();
if(tok==tk_camma)nexttok();
}
if(strcmp(itok.name,"allregs")==0){
i=256;
nexttok();
}
rec->recpost=0xFF^i;
expecting(tk_closebracket);
}
}
void declare_procedure(int oflag,int orm,int npointr)
{
int i,next=TRUE,j;
char pname[IDLENGTH];
idrec *rec;
strcpy(pname,itok.name);
param[0]=0;
nexttok();
if(npointr)expecting(tk_closebracket);
expecting(tk_openbracket);
if((oflag&f_typeproc)==tp_fastcall)declareparamreg();
else declareparamstack();
if(tok2==tk_assign)nexttok();
itok.post=1;
if(npointr){
itok.segm=DS;
itok.type=tk_proc;
itok.sib=am32==FALSE?rm_d16:rm_d32;
i=2;
if(am32||(oflag&f_far))i=4;
if(tok==tk_assign||(notpost==TRUE&&dynamic_flag==0)){ //= èíèöèàëèçèðîâàíàÿ ïåðåìåííàÿ
if((oflag&f_extern))preerror("extern variable do not initialize at declare");
if(alignword&&(!dynamic_flag))alignersize+=AlignCD(DS,i);
FindOff((unsigned char *)pname,DS);
itok.number=outptrdata;
if(tok!=tk_assign){
if(dbg&2)AddDataLine(i);
outword(0);
if(i==4)outword(0);
}
else{
ITOK oitok;
oitok=itok;
initglobalvar(tk_word,1,i,variable);
itok=oitok;
next=FALSE;
}
itok.post=0;
datasize+=i;
}
else{
if((oflag&f_extern)==0){
itok.number=postsize;
AddPostData(i);
}
else itok.number=externnum++;
}
j=tok;
tok=tk_pointer;
}
else{
tok=tk_declare;
itok.type=tp_declare;
itok.number=(oflag&f_extern)!=0?externnum++:secondcallnum++;
itok.segm=NOT_DYNAMIC;
itok.post=0;
}
itok.npointr=(unsigned short)npointr;
itok.rm=orm;
itok.flag=oflag;
if(itok.rm==tokens)itok.rm=(am32==0?tk_word:tk_dword);
// printf("rm=%d %s\n",itok.rm,itok.name);
strcpy((char *)string,param);
rec=addtotree(pname);
if(next)nexttok();
else tok=j;
IsUses(rec);
}
void define_procedure()
{
if(dynamic_flag)dynamic_proc();
else{
itok.segm=NOT_DYNAMIC;
if(AlignProc!=FALSE)AlignCD(CS,alignproc);
procedure_start=outptr;
if(dbg)AddLine();
// itok.flag&=~f_static; 26.08.05 00:09
setproc((tok==tk_id||tok==tk_ID)?0:1);
dopoststrings();
}
}
void interruptproc()
{
char *bstring;
ITOK otok;
inlineflag=0;
procedure_start=outptr;
returntype=tk_void;
current_proc_type=f_interrupt;
localsize=paramsize=0;
nexttok();
// FindOff((unsigned char *)itok.name,CS);
itok.number=outptr;
itok.segm=NOT_DYNAMIC;
itok.post=0;
itok.rm=tk_void;
itok.flag=0;
if(tok==tk_ID||tok==tk_id){
tok=tk_interruptproc;
itok.type=tp_ucnovn;
addtotree((char *)string);
}
else if(tok==tk_undefproc){
tok=tk_interruptproc;
long hold=updatetree();
updatecall((unsigned int)hold,(unsigned int)outptr,0);
}
else idalreadydefined();
itok.rec->count=FindOff((unsigned char *)itok.name,CS);
bstring=BackString((char *)string);
otok=itok;
nextexpecting2(tk_openbracket);
expecting(tk_closebracket);
if(tok==tk_inline){
inlineflag=1;
nexttok();
}
else if(tok!=tk_openbrace)declarelocals(0);
expecting(tk_openbrace);
declarelocals(1);
startblock();
doblock2(); /* do proc */
endblock();
if(retproc==FALSE){
if(inlineflag==0)leaveproc();
else if(localsize>0)Leave();
}
initBP=0;
strcpy((char *)string,bstring);
itok=otok;
tok=tk_interruptproc;
itok.size=outptr-procedure_start;
updatetree();
free(bstring);
killlocals();
nexttok();
dopoststrings();
}
int skipstring(int pos,unsigned char term)
{
unsigned char c;
do{
pos++;
c=input[pos];
if(c==0x5C){
pos++;
continue;
// c=input[pos+1];
}
}while(c!=term);
return pos;
}
int skipcomment(int pos)
{
if(input[pos+1]=='*'){
pos+=2;
for(;;pos++){
if(input[pos]==13){
linenumber++;
}
else if(input[pos]=='*'){
pos++;
if(input[pos]=='/')break;
}
if((unsigned int)pos>=endinptr){
unexpectedeof();
break;
}
}
}
else if(input[pos+1]=='/'){
pos+=2;
for(;;pos++){
if(input[pos]==13){
linenumber++;
break;
}
if(input[pos]==10)break;
}
}
return pos;
}
int swapparam()
{
int i,ns,j,lastofs;
int linep,linebak;
char c,ochar;
unsigned char *bufpar;
int numpar=0;
unsigned char *oldinput;
paraminfo *pi;
if(tok!=tk_openbracket){
expected('(');
do{
nexttok();
}while(tok2!=tk_semicolon&&tok!=tk_eof);
return 0;
}
pi=(paraminfo *)MALLOC(128*sizeof(paraminfo));
do{
inptr2--;
}while(input[inptr2]!='(');
inptr2++;
pi->ofspar=inptr2;
pi->type[0]=0;
linep=linenumber;
for(i=inptr2,ns=1;ns>0;i++){ //ïîèñê êîíöà ïàðàìåòðîâ
switch(input[i]){
case '(': ns++; break;
case ')': ns--; break;
case ',':
if(ns==1){
if(numpar==127)preerror("To many parametrs in function");
numpar++;
(pi+numpar)->ofspar=i+1;
(pi+numpar)->type[0]=0;
}
break;
case '/':
i=skipcomment(i);
break;
case '"':
case 0x27:
i=skipstring(i,input[i]);
break;
case 13:
linenumber++;
break;
}
if((unsigned int)i>=endinptr){
unexpectedeof();
break;
}
}
for(j=0,ns=0;param[j]!=0;j++,ns++){//ïåðåâåðíóòü çàäåêëàðèðóåìûå ïàðàìåòðû
lastofs=0;
ochar=c=param[j];
(pi+ns)->type[0]=c;
while(c=='*'){
j++;
ochar=c=param[j];
(pi+ns)->type[++lastofs]=c;
}
if(c=='A'){
if(ns){
while(ns<=numpar){
(pi+ns)->type[0]='U';
(pi+ns)->type[1]=0;
ns++;
}
break;
}
}
if(ochar=='T'){
do{
j++;
lastofs++;
c=param[j];
(pi+ns)->type[lastofs]=c;
}while(isdigit(c));
(pi+ns)->type[lastofs]=0;
j--;
continue;
}
c=param[j+1];
if(c>='0'&&c<='7'){
(pi+ns)->type[1]=c;
j++;
lastofs++;
if(ochar=='Q'){
(pi+ns)->type[2]=param[j+1];
j++;
lastofs++;
}
}
(pi+ns)->type[++lastofs]=0;
}
ns--;
for(j=0;ns>=0;ns--){
lastofs=0;
c=(pi+ns)->type[lastofs++];
while(c!=0){
param[j++]=c;
c=(pi+ns)->type[lastofs++];
}
}
param[j]=0;
// puts(param);
// if(crec)printf("start0 swapparams num=%08X\n",crec->recnumber);
bufpar=(unsigned char *)MALLOC(i-inptr2+2);
// printf("crec=%08X size=%d bufpar=%08X size=%d\n",crec,sizeof(idrec),bufpar,i-inptr2+2);
inptr2=i;
ochar=input[inptr2];
inptr2++;
i--;
lastofs=0;
for(;;){
j=(pi+numpar)->ofspar;//[numpar];
for(ns=0;(j+ns)!=i;ns++){
bufpar[lastofs++]=input[j+ns];
}
i=j-1;
numpar--;
if(numpar<0)break;
bufpar[lastofs++]=',';
}
bufpar[lastofs++]=')';
*(short *)&bufpar[lastofs++]=';';
free(pi);
oldinput=input; //ñîõð íåêîòîð ïåðåìåíûå
// puts((char *)(input+inptr));
// printf("cur_mod=%08X input=%08X\n",cur_mod,input);
ns=inptr2;
j=endinptr;
input=bufpar;
// puts((char *)bufpar);
inptr2=1;
cha2=input[0];
endinptr=lastofs;
tok=tk_openbracket;
if(bufrm!=NULL){
free(bufrm);
bufrm=NULL;
}
if(strinf.bufstr!=NULL){
free(strinf.bufstr);
strinf.bufstr=NULL;
}
linebak=linenumber;
linenumber=linep;
i=doparams();
endoffile=0;
input=oldinput;
inptr2=ns;
cha2=ochar;
endinptr=j;
linenumber=linebak;
// printf("cur_mod=%08X input=%08X\n",cur_mod,input);
free(bufpar);
// puts((char *)input);
return i;
}
int getrazr(int type)
{
switch(type){
case tk_char:
case tk_byte:
return r8;
case tk_word:
case tk_int:
return r16;
case tk_long:
case tk_dword:
case tk_float:
return r32;
case tk_qword:
case tk_double:
return r64;
}
if(am32)return r32;
return r16;
}
int doparams() /* do stack procedure parameter pushing */
{
char done=0,next;
int vartype;
int stackpar=0;
int i;
int jj=0;
char *bparam; //áóôåð äëÿ äåêëàðèðóåìûõ ïàðàìåòðîâ
int ip=-1; //íîìåð ïàðàìåòðà
char *ofsstr=NULL;
int useAX=FALSE;
int retreg=AX;
unsigned char oaddstack=addstack;
unsigned char oinline=useinline;
useinline=0;
int structsize;
struct idrec *ptrs;
addstack=FALSE;
if(am32!=FALSE)jj=2;
bparam=BackString(param);
if(param[0]!=0)ip=0;
ofsstr=GetLecsem(tk_camma,tk_closebracket);
expectingoperand(tk_openbracket);
ClearRegister();
if(tok!=tk_closebracket){
while(tok!=tk_eof&&done==0){
useAX=FALSE;
retreg=AX;
i=0;
next=1;
if(ip!=-1){
if(bparam[ip]=='*'){
while(bparam[ip]=='*')ip++;
ip++;
vartype=(am32==FALSE?tk_word:tk_dword);
}
else{
if((vartype=GetTypeParam(bparam[ip++]))==0)ip=-1;
else{
int c=bparam[ip];
if(vartype==tk_struct){
structsize=0;
while(isdigit(c)){
c-='0';
structsize=structsize*10+c;
ip++;
c=param[ip];
}
}
else if(c>='0'&&c<='7'){
ip++;
c-=0x30;
if(vartype==tk_fpust)float2stack(c);
else{
if(vartype==tk_qword){
c|=(bparam[ip]-0x30)*256;
ip++;
}
CalcRegPar(c,vartype,&ofsstr);
}
goto endparam;
}
}
}
if(vartype==tk_multipoint){
vartype=tokens;
ip--;
}
}
if(tok==tk_string){
if(chip<2||(optimizespeed&&(chip==5||chip==6))){
op(0xB8);
if(am32!=FALSE)outdword(addpoststring());
else outword(addpoststring()); // MOV AX,imm16
op(0x50);
useAX=TRUE;
ClearReg(EAX); //íàäî äîáàâèòü îïòèìèçàöèþ ðåãèñòðîâ à ïîêà òàê
} /* PUSH AX */
else{
op(0x68); /* PUSH imm16 */
if(am32!=FALSE)outdword(addpoststring());
else outword(addpoststring());
if(cpu<2)cpu=2;
}
stackpar+=2+jj;
addESP+=2+jj;
nexttok();
}
else{
if(tok>=tk_char&&tok<=tk_double){
vartype=tok;
getoperand();
}
else if(tok==tk_openbracket){
nexttok();
if(tok>=tk_char&&tok<=tk_double)vartype=tok;
nexttok();
expectingoperand(tk_closebracket);
}
else{
if(ip==-1||vartype==tokens){
switch(tok){
case tk_longvar: vartype=tk_long; break;
case tk_floatvar: vartype=tk_float; break;
case tk_dwordvar: vartype=tk_dword; break;
case tk_doublevar: vartype=tk_double; break;
case tk_qwordvar: vartype=tk_qword; break;
case tk_number:
vartype=(itok.rm==tk_float?tk_float:(am32==FALSE?tk_word:tk_dword));
break;
case tk_reg32: vartype=tk_dword; break;
case tk_reg64: vartype=tk_qword; break;
case tk_minus:
if(tok2==tk_number){
vartype=itok2.rm==tk_float?tk_float:(am32==FALSE?tk_word:tk_dword);
break;
}
default: vartype=(am32==FALSE?tk_word:tk_dword); break;
}
}
}
if(tok==tk_minus&&tok2==tk_number&&vartype!=tk_float){ //ïðîâåðêà îòðèöàòåëüíîãî ÷èñëà
nexttok();
itok.lnumber=-itok.lnumber;
}
int razr;
if(ofsstr){
razr=getrazr(vartype);
int retr;
if((retr=CheckIDZReg(ofsstr,AX,razr))!=NOINREG){
// printf("reg=%d\n",retr);
GetEndLex(tk_camma,tk_closebracket);
if(razr==r8)razr=am32==0?r16:r32;
if(retr==SKIPREG)retreg=AX;
else retreg=retr;
op66(razr);
op(0x50+retreg);
useAX=TRUE;
stackpar+=razr;
addESP+=razr;
goto endparam1;
}
// printf("reg=%d\n",retr);
}
razr=r32;
if(itok2.type==tp_opperand||tok==tk_minus){ //ñîñòàâíîå
switch(vartype){
case tk_struct:
i=structsize/((am32+1)*2);
do_e_axmath(0,r32,&ofsstr);
ClearReg(AX);
if(am32){
i--;
itok.number=structsize;
for(;i>0;i--){
itok.number-=4;
outword(0x70FF);
op(itok.number);
}
outword(0x30FF);
}
else{
ClearReg(BX);
warningreg(regs[1][BX]);
outword(0xC389);
i--;
itok.number=structsize;
for(;i>0;i--){
itok.number-=2;
outword(0x77FF);
op(itok.number);
}
outword(0x37FF);
}
stackpar+=structsize;
addESP+=structsize;
break;
case tk_char: i=1;
case tk_byte:
stackpar+=jj;
doalmath((char)i,&ofsstr);
addESP+=2+jj;
break;
case tk_int: i=1;
case tk_word:
if(am32==FALSE)razr=r16;
stackpar+=jj;
goto blokl;
case tk_long: i=1;
case tk_dword:
if(cpu<3)cpu=3;
stackpar+=2;
blokl:
if(chip>=2&&(!(optimizespeed&&(chip==5||chip==6)))&&(tok==tk_number
||tok==tk_undefofs||tok==tk_postnumber)){
int otok=tok;
ITOK oitok=itok;
tok=tk_number;
if(OnlyNumber(i)){
op66(razr);
if(otok==tk_number&&(postnumflag&f_reloc)==0&&short_ok(itok.number,razr==r16?FALSE:TRUE)!=0){
op(0x6A); // PUSH 8 extend to 32 bit
op((unsigned int)itok.number);
}
else{
op(0x68); // PUSH const
if(otok==tk_undefofs)AddUndefOff(0,oitok.name);
else if(otok==tk_postnumber)(oitok.flag&f_extern)==0?setwordpost(&oitok):setwordext(&oitok.number);
else if((postnumflag&f_reloc)!=0)AddReloc();
if(razr==r16)outword(itok.number);
else outdword(itok.number);
}
addESP+=razr==r16?2:4;
goto nopush;
}
tok=otok;
}
do_e_axmath(i,razr,&ofsstr);
addESP+=razr==r16?2:4;
op66(razr);
break;
case tk_double:
if(doeaxfloatmath(tk_stackstart,0,4)!=tk_stackstart){
op66(r32);
op(0x50+EDX); // PUSH EDX
op66(r32);
op(0x50); //push eax
useAX=TRUE;
}
if(cpu<3)cpu=3;
stackpar+=6;
addESP+=8;
goto nopush;
case tk_float:
if(doeaxfloatmath(tk_stackstart)!=tk_stackstart){
op66(r32);
if(!am32){
op(0x89); // mov ssdword[bp+2]=eax
op(0x46);
op(2);
Leave();
}
else{
op(0x50); //push eax
useAX=TRUE;
}
}
if(cpu<3)cpu=3;
stackpar+=2;
addESP+=4;
goto nopush;
case tk_qwordvar:
i=EAX|(EDX*256);
getintoreg64(i);
doregmath64(i);
op66(r32);
op(0x50+EDX); // PUSH EDX
op66(r32);
next=0;
if(cpu<3)cpu=3;
stackpar+=6;
addESP+=8;
break;
default: goto deflt;
}
op(0x50);/* PUSH AX or EAX */
useAX=TRUE;
nopush:
stackpar+=2;
}
else{ //îäèíî÷íîå
// next=1;
// printf("vartype=%d\n",vartype);
if(vartype==tk_struct){
// printf("tok=%d %s\n",tok,itok.name);
i=structsize/((am32+1)*2);
switch(tok){
case tk_structvar:
ptrs=itok.rec;
if(ptrs->recpost==LOCAL){
if(ESPloc&&am32){
itok.rm=rm_mod10|rm_sib;
itok.sib=0x24;
itok.number+=addESP;
}
else{
itok.rm=rm_mod10|(am32==FALSE?rm_BP:rm_EBP);
}
itok.segm=SS;
itok.post=0;
compressoffset(&itok);
}
else{
itok.segm=DS;
itok.rm=(am32==FALSE?rm_d16:rm_d32); //óñòàíîâêè ïî óìîë÷àíèþ
itok.post=ptrs->recpost;
if(i>1&&am32){
outseg(&itok,1);
op(0xB8);
outaddress(&itok);
ClearReg(AX);
i--;
itok.number=structsize;
for(;i>0;i--){
itok.number-=4;
outword(0x70FF);
op(itok.number);
}
outword(0x30FF);
break;
}
}
itok.sib=(am32==FALSE?CODE16:CODE32);
itok.flag=ptrs->flag;
itok.number+=structsize;
for(;i>0;i--){
itok.number-=(am32+1)*2;
outseg(&itok,2);
op(0xFF); // PUSH [dword]
op(0x30+itok.rm);
outaddress(&itok);
}
break;
case tk_rmnumber:
itok.number+=structsize;
for(;i>0;i--){
itok.number-=(am32+1)*2;
outseg(&itok,2);
op(0xFF); // PUSH [dword]
op(0x30+itok.rm);
outaddress(&itok);
}
break;
case tk_undefofs:
itok.rm=(am32==FALSE?rm_d16:rm_d32); //óñòàíîâêè ïî óìîë÷àíèþ
case tk_postnumber:
if(i>1&&am32){
if(tok!=tk_undefofs)outseg(&itok,1);
op(0xB8);
if(tok==tk_undefofs){
AddUndefOff(0,(char *)string);
outdword(itok.number);
}
else outaddress(&itok);
ClearReg(AX);
i--;
itok.number=structsize;
for(;i>0;i--){
itok.number-=4;
outword(0x70FF);
op(itok.number);
}
outword(0x30FF);
break;
}
itok.number+=structsize;
for(;i>0;i--){
itok.number-=(am32+1)*2;
if(tok!=tk_undefofs)outseg(&itok,2);
op(0xFF); // PUSH [dword]
op(0x30+itok.rm);
if(tok==tk_undefofs){
AddUndefOff(0,(char *)string);
outdword(itok.number);
}
else outaddress(&itok);
}
break;
case tk_reg32:
i--;
itok.rm=structsize;
for(;i>0;i--){
itok.rm-=4;
op(0xFF);
op(0x70+itok.number);
op(itok.rm);
}
op(0xFF);
op(0x30+itok.number);
break;
default:
// preerror("for parametr function required structure");
do_e_axmath(0,r32,&ofsstr);
ClearReg(AX);
if(am32){
i--;
itok.number=structsize;
for(;i>0;i--){
itok.number-=4;
outword(0x70FF);
op(itok.number);
}
outword(0x30FF);
}
else{
ClearReg(BX);
warningreg(regs[1][BX]);
outword(0xC389);
i--;
itok.number=structsize;
for(;i>0;i--){
itok.number-=2;
outword(0x77FF);
op(itok.number);
}
outword(0x37FF);
}
break;
}
stackpar+=structsize;
addESP+=structsize;
}
else if(vartype<tk_long){
#ifdef OPTVARCONST
CheckConstVar3(&tok,&itok,razr);
#endif
switch(tok){
case tk_reg:
op(0x50+(unsigned int)itok.number);
break;
case tk_beg:
if(vartype==tk_int||vartype==tk_word)goto deflt;
if(itok.number<AH){
op(0x50+(unsigned int)itok.number);
break;
}
op(0x88);
op(0xC0+(unsigned int)itok.number*8);
op(0x50);
useAX=TRUE;
break;
case tk_seg:
if(am32)goto deflt;
if((unsigned int)itok.number<FS)op(0x06+(unsigned int)itok.number*8);
else{
op(0xF); op(0x80+(unsigned int)itok.number*8);
if((unsigned int)itok.number<=GS)if(cpu<3)cpu=3;
}
break;
case tk_longvar:
case tk_dwordvar:
// if(am32==FALSE)goto deflt;
i=2;
case tk_intvar:
case tk_wordvar:
i+=2;
CheckAllMassiv(bufrm,i,&strinf);
outseg(&itok,2);
op(0xFF); /* PUSH [word] */
op(0x30+itok.rm);
outaddress(&itok);
break;
case tk_number:
if(chip>=2/*&&(!(optimizespeed&&(chip==5||chip==6)))*/){ //28.03.07 19:04
if((itok.flag&f_reloc)==0&&short_ok(itok.number)){
op(0x6A); /* PUSH const */
op((unsigned int)itok.number);
}
else{
op(0x68); /* PUSH const */
if((itok.flag&f_reloc)!=0)AddReloc();
if(am32==FALSE)outword((unsigned int)itok.number);
else outdword(itok.number);
}
if(cpu<2)cpu=2;
}
else{
MovRegNum(r16,itok.flag&f_reloc,itok.number,EAX);
op(0x50);
}
break;
case tk_apioffset:
op(0x68); // PUSH const
AddApiToPost(itok.number);
break;
case tk_postnumber:
case tk_undefofs:
if(chip>=2&&(!(optimizespeed&&(chip==5||chip==6)))){
op(0x68); // PUSH const
if(tok==tk_undefofs)AddUndefOff(0,(char *)string);
else (itok.flag&f_extern)==0?setwordpost(&itok):setwordext(&itok.number);
if(am32==FALSE)outword((unsigned int)itok.number);
else outdword(itok.number);
break;
}
default:
deflt:
//if(tok==tk_new)puts("monovar default");
switch(vartype){
case tk_int: i=1;
case tk_word: do_e_axmath(i,r16,&ofsstr); break;
case tk_char: i=1;
case tk_byte: doalmath((char)i,&ofsstr); break;
default: beep(); break;
}
op(0x50); /* PUSH AX */
useAX=TRUE;
next=0;
break;
}
stackpar+=2+jj;
addESP+=2+jj;
}
else if(vartype<tk_qword){
#ifdef OPTVARCONST
CheckConstVar3(&tok,&itok,razr);
#endif
// printf("tok=%d %s\n",tok,itok.name);
switch(tok){ // long or dword or float
case tk_reg32:
op66(r32);
op(0x50+(unsigned int)itok.number);
break;
case tk_floatvar:
if(vartype==tk_float)goto pushmem;
case tk_qwordvar:
case tk_dwordvar:
case tk_longvar:
if(optimizespeed&&(chip==5||chip==6))goto def;
pushmem:
CheckAllMassiv(bufrm,4,&strinf);
op66(r32);
outseg(&itok,2);
op(0xFF); // PUSH [dword]
op(0x30+itok.rm);
// printf("push rm=%08X sib=%08X post=%u num=%08X rec=%08X flag=%08X %s\n",itok.rm,itok.sib,itok.post,itok.number,itok.rec,itok.flag,itok.name);
outaddress(&itok);
break;
case tk_number:
if(optimizespeed&&(chip==5||chip==6))goto def;
if(vartype==tk_float){
itok.number=doconstfloatmath();
next=0;
}
else if(itok.rm==tk_double)itok.fnumber=itok.dnumber;
op66(r32);
if((itok.flag&f_reloc)==0&&short_ok(itok.number,TRUE)!=0){
op(0x6A); // PUSH 8 extend to 32 bit
op((unsigned int)itok.number);
}
else{
op(0x68); // PUSH const
if((itok.flag&f_reloc)!=0)AddReloc();
outdword(itok.number);
}
break;
case tk_apioffset:
op66(r32);
op(0x68); // PUSH const
AddApiToPost(itok.number);
break;
case tk_postnumber:
case tk_undefofs:
if(optimizespeed&&(chip==5||chip==6))goto def;
op66(r32);
op(0x68); // PUSH const
if(tok==tk_undefofs)AddUndefOff(0,(char *)string);
else (itok.flag&f_extern)==0?setwordpost(&itok):setwordext(&itok.number);
outdword(itok.number);
break;
default:
def:
if(vartype==tk_float)doeaxfloatmath(tk_stackstart);
else{
if(vartype==tk_long)i=1;
// printf("tok=%d rm=%08X %s\n",tok,itok.rm,itok.name);
if(tok==tk_rmnumber&&am32&&bufrm==NULL&&strinf.bufstr==NULL&&
((itok.rm&7)!=4)&&((itok.rm&7)!=5)&&
((itok.rm&rm_mod11)==rm_mod00)&&itok.number==0){
op66(r32);
op(0x50+(itok.rm&7)); // PUSH rm reg
break;
}
do_e_axmath(i,r32,&ofsstr);
op66(r32);
op(0x50); // PUSH EAX
useAX=TRUE;
}
next=0;
break;
}
stackpar+=4;
addESP+=4;
if(cpu<3)cpu=3;
}
else{ //qword or double
#ifdef OPTVARCONST
CheckConstVar3(&tok,&itok,razr);
#endif
switch(tok){
case tk_reg64:
op66(r32);
op(0x50+(unsigned int)itok.number/256);
op66(r32);
op(0x50+(unsigned int)itok.number&255);
break;
case tk_doublevar:
case tk_qwordvar:
itok.number+=4;
compressoffset(&itok);
CheckAllMassiv(bufrm,8,&strinf);
for(i=0;i<2;i++){
op66(r32);
outseg(&itok,2);
op(0xFF); // PUSH [dword]
op(0x30+itok.rm);
outaddress(&itok);
if(i==1)break;
itok.number-=4;
compressoffset(&itok);
}
break;
case tk_reg32:
op66(r32);
outword(0x6A); // PUSH 8 extend to 32 bit
op66(r32);
op(0x50+(unsigned int)itok.number);
break;
case tk_number:
long long lnumber;
lnumber=itok.lnumber;
itok.lnumber=lnumber>>32;
for(i=0;i<2;i++){
op66(r32);
if((i==0||(itok.flag&f_reloc)==0)&&short_ok(itok.number,TRUE)!=0){
op(0x6A); // PUSH 8 extend to 32 bit
op((unsigned int)itok.number);
}
else{
op(0x68); // PUSH const
if(i==1&&(itok.flag&f_reloc)!=0)AddReloc();
outdword(itok.number);
}
if(i==1)break;
itok.number=lnumber;
}
break;
case tk_postnumber:
case tk_undefofs:
op66(r32);
outword(0x6A); // PUSH 8 extend to 32 bit
op66(r32);
op(0x68); // PUSH const
if(tok==tk_undefofs)AddUndefOff(0,(char *)string);
else (itok.flag&f_extern)==0?setwordpost(&itok):setwordext(&itok.number);
outdword(itok.number);
break;
default:
if(vartype==tk_double)doeaxfloatmath(tk_stackstart,0,4);
else{
op66(r32);
outword(0x6A);
do_e_axmath(0,r32,&ofsstr);
op66(r32);
op(0x50); // PUSH EAX
useAX=TRUE;
}
next=0;
break;
}
stackpar+=8;
addESP+=8;
if(cpu<3)cpu=3;
}
endparam1:
if(next)nexttok();
}
}
endparam:
if(ofsstr){
if(useAX)IDZToReg(ofsstr,retreg,getrazr(vartype));
free(ofsstr);
ofsstr=NULL;
}
if(tok==tk_camma){
ofsstr=GetLecsem(tk_camma,tk_closebracket);
getoperand();
}
else if(tok==tk_closebracket)done=1;
else{
expected(')');
done=1;
}
}
}
if(ofsstr){
if(useAX)IDZToReg(ofsstr,retreg,getrazr(vartype));
free(ofsstr);
}
if(ip!=-1&&bparam[ip]!=0&&bparam[ip]!='A'&&bparam[ip]!='V')missingpar();
free(bparam);
setzeroflag=FALSE;
addstack=oaddstack;
useinline=oinline;
return stackpar;
}
void CheckDir()
{
do{
switch(itok.number){
case d_ifdef:
case d_ifndef:
case d_endif:
case d_else:
case d_if:
case d_elif:
inptr2=inptr;
cha2=cha;
linenum2=linenumber;
directive();
inptr=inptr2;
cha=cha2;
break;
default:
FastTok(0);
break;
}
if(tok==tk_eof)break;
}while(tok==tk_question);
}
char *dynamic_var()
{
int start,size;
char *bstring;
int use_extract=FALSE;
#define TBUFSIZE 2048
#define MTBUFSIZE TBUFSIZE-IDLENGTH
int curbsize;
COM_MOD *ocur_mod;
bstring=(char *)MALLOC(TBUFSIZE);
curbsize=TBUFSIZE;
size=0;
if(tok2==tk_extract)use_extract=TRUE;
do{
start=inptr2-1;
ocur_mod=cur_mod;
if(size>(curbsize-IDLENGTH)){
curbsize+=TBUFSIZE;
bstring=(char *)REALLOC(bstring,curbsize);
}
nexttok();
if(tok==tk_openbrace){
bstring[size]='{';
size++;
do{
start=inptr2-1;
ocur_mod=cur_mod;
if(size>(curbsize-IDLENGTH)){
curbsize+=TBUFSIZE;
bstring=(char *)REALLOC(bstring,curbsize);
}
nexttok();
if(tok==tk_number){
switch(itok.rm){
case tk_double:
case tk_float:
sprintf(itok.name,"%e",itok.dnumber);
break;
case tk_qword:
sprintf(itok.name,"0x%X%08X",itok.lnumber>>16,itok.number);
break;
default:
sprintf(itok.name,"0x%X",itok.number);
break;
}
}
if(itok.name[0]!=0){
strcpy(bstring+size,itok.name);
size+=strlen(itok.name);
}
else{
if(cur_mod!=ocur_mod){
start=inptr2-2;
if(start<0)start=0;
}
strncpy(bstring+size,(char *)(input+start),inptr2-1-start);
size+=inptr2-1-start;
}
}while(tok!=tk_closebrace&&tok!=tk_eof);
if(tok!=tk_eof)continue;
}
if(tok==tk_number){
switch(itok.rm){
case tk_double:
case tk_float:
sprintf(itok.name,"%e",itok.dnumber);
break;
case tk_qword:
sprintf(itok.name,"0x%X%08X",itok.lnumber>>16,itok.number);
break;
default:
sprintf(itok.name,"0x%X",itok.number);
break;
}
}
if(itok.name[0]!=0){
strcpy(bstring+size,itok.name);
size+=strlen(itok.name);
}
else{
if(cur_mod!=ocur_mod){
start=inptr2-2;
if(start<0)start=0;
}
strncpy(bstring+size,(char *)(input+start),inptr2-1-start);
size+=inptr2-1-start;
}
if(tok==tk_eof){
unexpectedeof();
return NULL;
}
if(tok==tk_camma&&use_extract==FALSE)break;
}while(tok!=tk_semicolon);
// size++;
bstring[size]=0;
return bstring;
}
int SkipBlock()
{
for(int i=1;i!=0;){
FastTok(0);
if(tok==tk_question)CheckDir();
switch(tok){
case tk_eof: unexpectedeof(); return FALSE;
case tk_openbrace: i++; break;
case tk_closebrace: i--; break;
}
}
return TRUE;
}
int SkipParam()
{
for(int i=1;i!=0;){
FastTok(0);
if(tok==tk_question)CheckDir();
switch(tok){
case tk_openbracket: i++; break;
case tk_closebracket: i--; break;
case tk_eof: unexpectedeof(); return FALSE;
}
}
return TRUE;
}
int SkipLocalVar()
{
while(tok!=tk_openbrace&&tok!=tk_eof){
if(tok==tk_question){
CheckDir();
continue;
}
if(tok==tk_id&&(strcmp(itok.name,"struct")==0||strcmp(itok.name,"union")==0)){
do{
FastTok(0);
if(tok==tk_eof){
unexpectedeof();
return FALSE;
}
}while(tok!=tk_semicolon&&tok!=tk_openbrace);
if(tok==tk_openbrace){
FastTok(0);
if(!SkipBlock())return FALSE;
}
}
FastTok(1);
}
return TRUE;
}
SAVEPAR *SRparam(int save,SAVEPAR *par) //save or restore global param compiler
{
if(save){
par=(SAVEPAR *)MALLOC(sizeof(SAVEPAR));
par->ooptimizespeed=optimizespeed;
par->owarning= warning;
par->odbg= dbg;
par->odosstring= dosstring;
par->ouseinline= useinline;
par->oam32= am32;
par->oalignword= alignword;
par->oAlignCycle= AlignCycle;
par->oidasm= idasm; //àññ
par->ooptnumber= optnumber;
par->odivexpand= divexpand;
par->ooptstr= optstr; //îï
par->ochip= chip;
par->oaligncycle= aligncycle;
par->ouselea= uselea;
par->oregoverstack= regoverstack;
return par;
}
if(par){
optimizespeed=par->ooptimizespeed;
warning= par->owarning;
dbg= par->odbg;
dosstring= par->odosstring;
useinline= par->ouseinline;
am32= par->oam32;
alignword= par->oalignword;
AlignCycle= par->oAlignCycle;
idasm= par->oidasm; //àññ
optnumber= par->ooptnumber;
divexpand= par->odivexpand;
optstr= par->ooptstr; //îï
chip= par->ochip;
aligncycle= par->oaligncycle;
uselea = par->ouselea;
regoverstack= par->oregoverstack;
free(par);
}
return NULL;
}
void dynamic_proc()
{
int dtok,start,size,line;
ITOK otok;
char *bstring;
idrec *ptr;
_PROCINFO_ *pinfo;
if(itok.npointr)itok.rm=(am32==TRUE?tk_dword:tk_word);
dtok=tok;
otok=itok;
line=linenum2;
switch(tok){
case tk_id:
case tk_ID:
string[0]=0;
case tk_undefproc:
case tk_declare:
break;
default: idalreadydefined(); break;
}
if(itok.flag&f_export)preerror("'_export' not use in dynamic functions");
bstring=BackString((char *)string);
start=inptr2-1;
pinfo=(_PROCINFO_ *)MALLOC(sizeof(_PROCINFO_));
if(itok.flag&f_classproc)pinfo->classteg=searchteg;
else pinfo->classteg=NULL;
pinfo->warn=warning;
pinfo->speed=optimizespeed;
pinfo->lst=(dbg&2)>>1;
pinfo->typestring=dosstring;
pinfo->inlinest=useinline;
pinfo->code32=am32;
pinfo->align=alignword;
pinfo->acycle=AlignCycle;
pinfo->idasm=idasm;
pinfo->opnum=optnumber;
pinfo->de=divexpand;
pinfo->ostring=optstr;
pinfo->chip=chip;
pinfo->sizeacycle=aligncycle;
pinfo->uselea=uselea;
pinfo->regoverstack=regoverstack;
nexttok();
if(dtok==tk_id||dtok==tk_ID){
param[0]=0;
if(tok2!=tk_closebracket&&(otok.flag&f_typeproc)==tp_fastcall){
nexttok(); //ïàðàìåòðû ðåãèñòðîâîé ïðîöåäóðû
declareparamreg();
free(bstring);
bstring=BackString((char *)param);
nexttok();
inptr=inptr2;
cha=cha2;
linenumber=linenum2;
}
}
else{
inptr=inptr2;
cha=cha2;
if(!SkipParam()){
free(bstring);
return;
}
FastTok(1);
}
if(tok==tk_semicolon)preerror("error declare dynamic function");
if((!SkipLocalVar())||(!SkipBlock())){
free(bstring);
return;
}
size=inptr-start+1;
inptr2=inptr;
cha2=cha;
linenum2=linenumber;
linenumber=line;
itok=otok;
strcpy((char *)string,bstring);
free(bstring);
bstring=(char *)MALLOC(size+1);
strncpy(bstring,(char *)(input+start),size);
bstring[size-1]=';';
bstring[size]=0;
// printf("tok=%d %s\n%s\n",dtok,itok.name,bstring);
itok.size=0;
tok=tk_proc;
itok.segm=DYNAMIC;
if(dtok==tk_id||dtok==tk_ID){
int i;
itok.number=secondcallnum++;
itok.type=tp_ucnovn;
if((i=FindUseName(itok.name))!=0)itok.segm=DYNAMIC_USED;
ptr=addtotree(itok.name);
if(i){
ptr->count=i;
ptr=itok.rec;
AddDynamicList(ptr);
}
}
else{
if(dtok==tk_undefproc)itok.segm=DYNAMIC_USED;
updatetree();
ptr=itok.rec;
//11.08.04 23:38
strcpy(ptr->recid,itok.name);
if(dtok==tk_undefproc&&(itok.flag&f_classproc))AddDynamicList(ptr);
}
ptr->line=linenumber;
ptr->file=currentfileinfo;
pinfo->buf=bstring;
ptr->pinfo=pinfo;
// ptr->sbuf=bstring;
// linenumber=linenum2;
if(searchteg)searchteg=NULL;
nexttok();
}
/* ======= procedure handling ends here ======== */
int macros(int expectedreturn)
{
int dynamicindex,actualreturn;
ITOK otok;
int orettype;
unsigned int oproctype;
int otok2;
unsigned int typep;
int snum=0;
actualreturn=(am32==FALSE?tk_word:tk_dword);
switch(tok){
case tk_ID:
case tk_id:
dynamicindex=NOT_DYNAMIC;
break;
case tk_proc:
case tk_undefproc:
case tk_declare:
dynamicindex=itok.segm;
actualreturn=itok.rm;
break;
default:
idalreadydefined();
return expectedreturn;
}
typep=itok.flag;
otok=itok;
if(tok==tk_ID)param[0]=0;
else strcpy(param,(char *)string);
nexttok();
orettype=returntype;
returntype=actualreturn; //01.08.04 14:45
oproctype=current_proc_type;
if(dynamicindex==NOT_DYNAMIC)doregparams();
else{
switch(typep&f_typeproc){
case tp_cdecl:
case tp_stdcall:
snum=swapparam();
break;
case tp_pascal:
snum=doparams();
break;
case tp_fastcall:
doregparams();
break;
}
}
itok=otok;
otok2=tok2;
if(dynamicindex==NOT_DYNAMIC){
if((actualreturn=includeit(0))==-1){
char holdstr[IDLENGTH+16];
sprintf(holdstr,"unknown macro '%s'",itok.name);
preerror(holdstr);
}
}
else insert_dynamic(TRUE);
if(actualreturn!=tk_void&&expectedreturn!=tk_ID)convert_returnvalue(expectedreturn,actualreturn);
returntype=orettype;
current_proc_type=oproctype;
if(snum!=0){
if(typep&f_retproc)warningdestroyflags();
CorrectStack(snum);
}
tok2=otok2;
return actualreturn;
}
int updatecall(unsigned int which,unsigned int where,unsigned int top)
/* update output with newly defined location, but only for addresses after
and including top. return the number of addresses updated.
which - àäðåñ ïðîöåäóðû
where - òåêóùèé àäðåñ*/
{
unsigned int count=0;
long hold;
int updates=0;
while(count<posts){
if(((postbuf+count)->type>=CALL_SHORT&&(postbuf+count)->type<=CONTINUE_32)&&
(postbuf+count)->num==which&&(postbuf+count)->loc>=top){
hold=(long)where-(long)(postbuf+count)->loc;
if((postbuf+count)->type>=CALL_NEAR&&(postbuf+count)->type<=CONTINUE_NEAR){ //NEAR
hold-=2;
*(unsigned short *)&output[(postbuf+count)->loc]=(unsigned short)hold;
}
else if((postbuf+count)->type>=CALL_32&&(postbuf+count)->type<=CONTINUE_32){//32-BIT
hold-=4;
*(unsigned long *)&output[(postbuf+count)->loc]=(unsigned long)hold;
}
else{ //SHORT
hold--; // CALL_SHORT
if(short_ok(hold))output[(postbuf+count)->loc]=(unsigned char)hold;
else{
if((postbuf+count)->type==BREAK_SHORT)preerror3("BREAK distance too large, use break",(postbuf+count)->line);
else if((postbuf+count)->type==CONTINUE_SHORT)preerror3("CONTINUE distance too large, use continue",(postbuf+count)->line);
else preerror3(shorterr,(postbuf+count)->line,(postbuf+count)->file);
}
}
if(hold<127){
if((postbuf+count)->type==JMP_NEAR||(postbuf+count)->type==JMP_32)warningjmp("GOTO",(postbuf+count)->line,(postbuf+count)->file);
if((postbuf+count)->type==BREAK_NEAR||(postbuf+count)->type==BREAK_32)warningjmp("BREAK",(postbuf+count)->line);
if((postbuf+count)->type==CONTINUE_NEAR||(postbuf+count)->type==CONTINUE_32)warningjmp("CONTINUE",(postbuf+count)->line);
}
killpost(count);
updates++;
}
else count++;
}
if(updates==1&&hold==0)return -1;
return(updates);
}
void define_locallabel()
{
FindOff(string,CS);
updatecall((unsigned int)updatelocalvar((char *)string,tk_number,outptr),outptr,procedure_start);
nextexpecting2(tk_colon);
RestoreStack();
clearregstat();
#ifdef OPTVARCONST
ClearLVIC();
#endif
}
void addacall(unsigned int idnum,unsigned char callkind)
{
CheckPosts();
(postbuf+posts)->num=idnum;
(postbuf+posts)->loc=outptr+1;
(postbuf+posts)->type=callkind;
(postbuf+posts)->line=(unsigned short)linenumber;
(postbuf+posts)->file=(unsigned short)currentfileinfo;
posts++;
}
unsigned int dofrom() // returns number of bytes read from FROM file
{
int filehandle;
long filesize;
if(tok!=tk_string){
stringexpected();
return(0);
}
#ifndef _WIN32_
for(char* p=(char *)string3; *p; ++p) if(*p=='\\') *p='/';
#endif
filehandle=open((char *)string3,O_BINARY|O_RDONLY);
if(filehandle==-1){
unableopenfile((char *)string3);
return(0);
}
if((filesize=getfilelen(filehandle))==-1L){
preerror("Unable to determine FROM file size");
close(filehandle);
return(0);
}
if(am32==FALSE&&filesize>=0xFFFFL){
preerror("FROM file too large");
close(filehandle);
return(0);
}
LoadData(filesize,filehandle);
return filesize;
}
unsigned int doextract() // returns number of bytes EXTRACTed
{
unsigned int sizetoread;
int filehandle;
long filesize,startpos;
if(tok!=tk_string){
stringexpected();
return(0);
}
filehandle=open((char *)string3,O_BINARY|O_RDONLY);
if(filehandle==-1){
unableopenfile((char *)string3);
return(0);
}
nexttok();
expecting(tk_camma);
if(tok!=tk_number){
numexpected();
return(0);
}
startpos=doconstlongmath();
expecting(tk_camma);
if(tok!=tk_number){
numexpected();
return(0);
}
sizetoread=doconstlongmath();
if((filesize=getfilelen(filehandle))==-1L){
preerror("Unable to determine EXTRACT file size");
close(filehandle);
return(0);
}
if(filesize<=startpos){
preerror("EXTRACT offset exceeds the length of the file");
close(filehandle);
return(0);
}
if(sizetoread==0)sizetoread=filesize-startpos;
if(am32==FALSE&&sizetoread>=0xFFFFL){
preerror("Block to EXTRACT exceeds 64K");
close(filehandle);
return(0);
}
lseek(filehandle,startpos,0); // error checking required on this
LoadData(sizetoread,filehandle);
return sizetoread;
}
void LoadData(unsigned int size,int filehandle)
{
if(splitdata){
while(((unsigned long)size+(unsigned long)outptrdata)>=outdatasize){
if(CheckDataSize()==0)break;
}
if((unsigned int)read(filehandle,outputdata+outptrdata,size)!=size)errorreadingfile((char *)string3);
outptrdata+=size;
}
else{
while(((unsigned long)size+(unsigned long)outptr)>=outptrsize){
if(CheckCodeSize()==0)break;
}
if((unsigned int)read(filehandle,output+outptr,size)!=size)errorreadingfile((char *)string3);
outptr+=size;
outptrdata=outptr;
}
close(filehandle);
}
void op66(int ctok)
{
if((am32==FALSE&&ctok==r32)||(am32!=FALSE&&ctok==r16)){
if(cpu<3)cpu=3;
op(0x66);
}
}
int op67(int ctok)
{
if((am32==FALSE&&ctok==r32)||(am32!=FALSE&&ctok==r16)){
if(cpu<3)cpu=3;
op(0x67);
return TRUE;
}
return FALSE;
}
void outseg(ITOK *outtok,unsigned int locadd)
{
int rmm1;
rmm1=outtok->rm&7;
if(outtok->sib!=CODE16){
if(am32==FALSE)op(0x67);
if(rmm1==4)locadd++;
}
else if(am32!=FALSE)op(0x67);
switch(outtok->segm){
case ES: op(0x26); break;
case CS: op(0x2E); break;
case FS: op(0x64);
if(cpu<3)cpu=3;
break;
case GS: op(0x65);
if(cpu<3)cpu=3;
break;
case SS:
if(outtok->sib==CODE16){
if(rmm1!=2&&rmm1!=3&&!(rmm1==6&&outtok->rm!=6))op(0x36);
}
else{
if(rmm1==4){
rmm1=outtok->sib&7;
if(rmm1!=4){
if(rmm1==5){
if(outtok->rm==4)op(0x36);
break;
}
op(0x36);
}
}
else if(rmm1==5){
if(outtok->rm==5)op(0x36);
else break;
}
else op(0x36);
}
break;
case DS:
if(outtok->sib==CODE16){
if(rmm1==2||rmm1==3||(rmm1==6&&outtok->rm!=6))op(0x3E);
}
else{
if(rmm1==4){
rmm1=outtok->sib&7;
if(rmm1==4||(rmm1==5&&outtok->rm!=4))op(0x3e);
}
else if(rmm1==5&&outtok->rm!=5)op(0x3e);
}
}
CheckPosts();
if(outtok->post!=0&&outtok->post!=UNDEF_OFSET){
if((outtok->flag&f_extern)){
(postbuf+posts)->type=EXT_VAR;
(postbuf+posts)->num=outtok->number&0xFFFF;
outtok->number>>=16;
}
else if(outtok->post==USED_DIN_VAR){
(postbuf+posts)->type=(unsigned short)(am32==0?DIN_VAR:DIN_VAR32);
// printf("Add tok=%d %08X sib=%d %s\n",outtok->rec->rectok,outtok->rec->right,outtok->rec->recsib,outtok->rec->recid);
if(outtok->rec->rectok==tk_structvar&&outtok->rec->recsib==tp_gvar){
(postbuf+posts)->num=(int)outtok->rec;//02.09.05 17:10 ->right;
}
else (postbuf+posts)->num=(int)outtok->rec;
}
// else if((outtok->flag&f_dataseg))(postbuf+posts)->type=(unsigned short)(am32==0?DATABLOCK_VAR:DATABLOCK_VAR32);
else (postbuf+posts)->type=(unsigned short)(am32==0?POST_VAR:POST_VAR32);
(postbuf+posts)->loc=outptr+locadd;
posts++;
}
else if(outtok->flag&f_reloc){
(postbuf+posts)->type=(unsigned short)(am32==0?FIX_VAR:FIX_VAR32);
(postbuf+posts)->loc=outptr+locadd;
posts++;
}
}
int addpoststring(int segm,int len,int term) /* add a string to the post queue */
{
int i;
int returnvalue;
if((returnvalue=FindDublString(segm,len,term))!=-1)return returnvalue;
CheckPosts();
(postbuf+posts)->type=(unsigned short)(am32==FALSE?POST_STRING:POST_STRING32);
(postbuf+posts)->loc=(segm==CS?outptr:outptrdata);
(postbuf+posts)->num=segm;
posts++;
returnvalue=poststrptr;
if((int)(len+poststrptr+1)>=sbufstr){
sbufstr+=SIZEBUF;
bufstr=(char *)REALLOC(bufstr,sbufstr);
}
for(i=0;i<len;i++,poststrptr++)bufstr[poststrptr]=string[i];
switch(term&3){
case zero_term:
if(term&s_unicod){
poststrptr++;
bufstr[poststrptr]=0;
}
bufstr[poststrptr]=0;
poststrptr++;
break;
case dos_term:
if(term&s_unicod){
bufstr[poststrptr]=0;
poststrptr++;
}
bufstr[poststrptr]='$';
poststrptr++;
break;
}
return(returnvalue);
}
int FindDublString(int segm,unsigned int len,int term)
{
STRING_LIST ins,outs;
void *nextstr=liststring,*prevstr=NULL;
ins.len=len;
ins.next=NULL;
ins.type=term;
/* if(splitdata){ //ðàçäåëåíûå äàíûå è êîä
ins.plase=0;
ins.ofs=outptrdata;
}
else{*/
ins.plase=POST_STRING;
ins.ofs=poststrptr;
// }
while(nextstr!=NULL){
memcpy(&outs,nextstr,sizeof(STRING_LIST));
if(term==outs.type&&len<=outs.len){
char *instr,*outstr;
outstr=(char *)nextstr+sizeof(STRING_LIST)+outs.len-1;
instr=(char *)string+len-1;
char c;
int i,j;
for(i=len,j=outs.len;i!=0;j--,i--,instr--,outstr--){
c=*instr;
if(c!=*outstr)break;
}
if(i==0){ //íàéäåíà ñòðîêà
if(!optstr)return -1;
warningstring();
if(outs.plase==0){ //óæå â ôàéëå
AddReloc(DS);
return outs.ofs+j;
}
CheckPosts();
(postbuf+posts)->type=(unsigned short)(am32==FALSE?POST_STRING:POST_STRING32);
(postbuf+posts)->loc=(segm==CS?outptr:outptrdata);
(postbuf+posts)->num=segm;
posts++;
return outs.ofs+j;
}
}
prevstr=nextstr;
nextstr=outs.next;
}
outs.next=(void *)MALLOC(sizeof(STRING_LIST)+len);
memcpy(outs.next,&ins,sizeof(STRING_LIST));
if(len!=0)memcpy((char *)outs.next+sizeof(STRING_LIST),&string,len);
if(prevstr!=NULL)memcpy(prevstr,&outs,sizeof(STRING_LIST));
else liststring=outs.next;
return -1;
}
void killpost(unsigned int poz)
{
posts--;
memcpy((postinfo *)(postbuf+poz),(postinfo *)(postbuf+posts),sizeof(postinfo));
}
void dopoststrings()
{
unsigned int addvalue,i;
if(poststrptr==0)return;
if(splitdata){
addvalue=outptrdata;
if((outptrdata+poststrptr)>=outdatasize)CheckDataSize();
}
else{
addvalue=outptr;
if((outptr+poststrptr)>=outptrsize)CheckCodeSize();
}
datasize+=poststrptr;
if(dbg&2)AddDataNullLine(3);
memcpy(&outputdata[outptrdata],bufstr,poststrptr);
outptrdata+=poststrptr;
if(!splitdata)outptr=outptrdata;
for(i=0;i<posts;i++){
int segm=(postbuf+i)->num;
if((postbuf+i)->type==POST_STRING){
if(segm==CS)*(unsigned short *)&output[(postbuf+i)->loc]+=(unsigned short)addvalue;
else *(unsigned short *)&outputdata[(postbuf+i)->loc]+=(unsigned short)addvalue;
if(splitdata&&modelmem==TINY)(postbuf+i)->type=(unsigned short)DATABLOCK_VAR;
else if(FixUp==FALSE)killpost(i--);
else (postbuf+i)->type=(unsigned short)(segm==DS?FIX_VAR:FIX_CODE);
}
else if((postbuf+i)->type==POST_STRING32){
if(segm==CS)*(unsigned int *)&output[(postbuf+i)->loc]+=addvalue;
else *(unsigned int *)&outputdata[(postbuf+i)->loc]+=addvalue;
if(splitdata&&modelmem==TINY)(postbuf+i)->type=(unsigned short)DATABLOCK_VAR32;
else if(FixUp==FALSE)killpost(i--);
else (postbuf+i)->type=(unsigned short)(segm==DS?FIX_VAR32:FIX_CODE32);
}
}
poststrptr=0; /* reset the poststrptr */
STRING_LIST ins;
void *nextstr=liststring;
while(nextstr!=NULL){
memcpy(&ins,nextstr,sizeof(STRING_LIST));
if(ins.plase!=0){
ins.plase=0;
ins.ofs+=addvalue;
memcpy(nextstr,&ins,sizeof(STRING_LIST));
}
nextstr=ins.next;
}
if(dbg&2)AddCodeNullLine();
}
void insertcode() // force code procedure at specified location
{
nexttok();
testInitVar(FALSE);
if((itok.flag&f_extern)!=0){
notexternfun();
return;
}
int tproc=itok.flag&f_typeproc;
setuprm();
switch(tok){
case tk_undefproc:
case tk_declare:
tok=tk_proc;
itok.number=outptr;
updatecall((unsigned int)updatetree(),(unsigned int)itok.number,0);
if(tproc==tp_fastcall){
if(includeit(1)==-1)thisundefined(itok.name);
}
else if(includeproc()==-1)thisundefined(itok.name);
break;
case tk_id:
case tk_ID:
tok=tk_proc;
itok.number=outptr;
string[0]=0;
itok.type=tp_ucnovn;
addtotree(itok.name);
if(tproc==tp_fastcall){
if(includeit(1)==-1)thisundefined(itok.name);
}
else if(includeproc()==-1)thisundefined(itok.name);
break;
case tk_proc:
if(itok.segm<NOT_DYNAMIC)insert_dynamic();
else preerror("Function already inserted in code");
break;
default: idalreadydefined(); break;
}
nextexpecting2(tk_openbracket);
while(tok!=tk_eof&&tok!=tk_closebracket)nexttok();
if(tok==tk_eof)unexpectedeof();
else nextseminext();
}
/************ some of the dynamic procedure support functions *************/
void insert_dynamic(int insert)
{
unsigned char *oinput;
int oinptr;
unsigned char ocha;
int oline;
int ofile;
char *ostartline;
int oendinptr;
structteg *osearchteg;
int oinsert;
_PROCINFO_ *pinfo;
SAVEPAR *par;
if(insert){
osearchteg=searchteg;
searchteg=NULL;
}
// printf("cur_mod=%08X\n",cur_mod);
oinsert=insert;
oinput=input;
oinptr=inptr2;
ocha=cha2;
oline=linenum2;
ofile=currentfileinfo;
(startfileinfo+currentfileinfo)->stlist=staticlist;
oendinptr=endinptr;
endoffile=0;
ostartline=startline;
idrec *ptr=itok.rec;
pinfo=ptr->pinfo;
input=(unsigned char *)pinfo->buf;
inptr2=1;
startline=(char *)input;
cha2=input[0];
endinptr=strlen((char *)input);
endinput=startline+endinptr;
linenumber=linenum2=ptr->line;
currentfileinfo=ptr->file;
staticlist=(startfileinfo+currentfileinfo)->stlist;
par=SRparam(TRUE,NULL);
warning=pinfo->warn;
optimizespeed=pinfo->speed;
dosstring=pinfo->typestring;
useinline=pinfo->inlinest;
am32=pinfo->code32;
alignword=pinfo->align;
AlignCycle=pinfo->acycle;
idasm=pinfo->idasm;
optnumber=pinfo->opnum;
divexpand=pinfo->de;
optstr=pinfo->ostring;
chip=pinfo->chip;
aligncycle=pinfo->sizeacycle;
uselea=pinfo->uselea;
regoverstack=pinfo->regoverstack;
if(pinfo->classteg!=NULL){
/*if((itok.flag&f_static)==0)*/searchteg=(structteg *)pinfo->classteg;
insert=0;
}
if(pinfo->lst)dbg|=2;
else dbg&=0xFD;
// puts(itok.name);
if(!insert){
procedure_start=outptr;
if(dbg){
if(dbg&2){
char m1[130];
//11.08.04 23:39
// if(searchteg)sprintf(m1,"%s::%s()",searchteg->name,itok.name);
// else sprintf(m1,"%s()",itok.name);
sprintf(m1,"%s()",itok.name);
AddCodeNullLine(m1);
}
else AddLine();
}
if(AlignProc)AlignCD(CS,alignproc);
// puts((char *)input);
if(pinfo->classteg==NULL)itok.flag&=~f_static;
setproc(1);
dopoststrings();
}
else insertproc();
input=oinput;
inptr2=oinptr;
cha2=ocha;
linenum2=oline;
// printf("cur_mod=%08X\n",cur_mod);
(startfileinfo+currentfileinfo)->stlist=staticlist;
currentfileinfo=ofile;
staticlist=(startfileinfo+currentfileinfo)->stlist;
endinptr=oendinptr;
endoffile=0;
startline=ostartline;
SRparam(FALSE,par);
if(oinsert)searchteg=osearchteg;
else searchteg=NULL;
// if(insert)nexttok();
// printf("tok=%d %08X\n",tok,cur_mod);
}
idrec *addtotree(char *keystring)//äîáàâèòü ñòðîêó â äåðåâî
{
struct idrec *ptr,*newptr;
int cmpresult;
//âûäåëèòü ïàìÿòü ïîä íîâóþ ïðîö
newptr=(struct idrec *)MALLOC(sizeof(struct idrec));
ptr=(itok.flag&f_static)!=0?staticlist:treestart; //íà÷àëî äåðåâà
if(ptr==NULL)((itok.flag&f_static)!=0?staticlist:treestart)=newptr;//íà÷àëî äåðåâà
else{ //ïîèñê ñòðîêè â äåðåâå
while(((cmpresult=strcmp(ptr->recid,keystring))<0&&ptr->left!=NULL)||
(cmpresult>0&&ptr->right!=NULL))ptr=(cmpresult<0?ptr->left:ptr->right);
(cmpresult<0?ptr->left:ptr->right)=newptr;
}
strcpy(newptr->recid,keystring);//ñêîïèð íàçâàíèå
newptr->newid=NULL;
if(string[0]!=0)newptr->newid=BackString((char *)string);
newptr->rectok=tok;
newptr->recnumber=itok.number;
newptr->recsegm=itok.segm;
newptr->recrm=itok.rm;
newptr->recpost=itok.post;
newptr->flag=itok.flag;
newptr->recsize=itok.size;
newptr->left=newptr->right=NULL;
newptr->sbuf=NULL;
newptr->recsib=itok.sib;
newptr->line=linenumber;
newptr->file=currentfileinfo;
newptr->count=0;
newptr->type=itok.type;
newptr->npointr=itok.npointr;
itok.rec=newptr;
return newptr;
}
long updatetree() // returns the old number value
{
struct idrec *ptr;
long hold;
ptr=itok.rec;
if(ptr==0)internalerror("address record not found when update tree");
if(ptr->newid)free(ptr->newid);
ptr->newid=NULL;
if(string[0]!=0)ptr->newid=BackString((char *)string);
ptr->rectok=tok;
hold=ptr->recnumber;
ptr->recnumber=itok.number;
ptr->recsegm=itok.segm;
ptr->recrm=itok.rm;
ptr->flag=itok.flag;
ptr->recsize=itok.size;
ptr->recsib=itok.sib;
return hold;
}
/* --------------- local variable handling starts here ----------------- */
unsigned int updatelocalvar(char *str,int tok4,unsigned int num)
{
struct localrec *ptr;
unsigned int retvalue;
treelocalrec *ntlr=tlr;
while(ntlr&&ntlr->level>1)ntlr=ntlr->next;
for(ptr=ntlr->lrec;;ptr=ptr->rec.next){
if(strcmp(ptr->rec.recid,str)==0){
retvalue=ptr->rec.recnumber;
ptr->rec.rectok=tok4;
ptr->rec.recnumber=num;
break;
}
if(ptr->rec.next==NULL)break;
}
return(retvalue);
}
localrec * addlocalvar(char *str,int tok4,unsigned int num,int addmain)
{
localrec *ptr,*newptr;
localrec *uptr;
treelocalrec *ntlr;
if(addmain){
ntlr=tlr;
while(ntlr&&ntlr->level>1)ntlr=ntlr->next;
uptr=ntlr->lrec;
}
else uptr=tlr->lrec;
newptr=(struct localrec *)MALLOC(sizeof(struct localrec));
if(uptr==NULL){
if(addmain)ntlr->lrec=newptr;
else tlr->lrec=newptr;
}
else{
ptr=uptr;
while(ptr->rec.next!=NULL)ptr=ptr->rec.next;
ptr->rec.next=newptr;
}
strcpy(newptr->rec.recid,str);
newptr->rec.rectok=tok4;
newptr->rec.recnumber=num;
newptr->rec.next=NULL;
newptr->rec.right=NULL;
newptr->rec.recsize=0;
newptr->fuse=NOTINITVAR;
newptr->rec.type=tp_ucnovn;
newptr->rec.flag=0;
newptr->rec.npointr=0;
newptr->rec.recpost=LOCAL;
newptr->li.count=0;
newptr->li.start=linenumber;
return newptr;
}
void KillTegList(structteg *tteg)
{
if(tteg){
KillTegList(tteg->left);
KillTegList(tteg->right);
if(tteg->baza)free(tteg->baza);
free(tteg);
}
}
void killlocals(/*int endp*/)
/* Clear and free the local linked list, check for any unresolved local
jump labels. */
{
/* if(endp){
dopoststrings();
for(int i=0;i<posts;i++){
// printf("%d type=%d num=%08X\n",i+1,(postbuf+i)->type,(postbuf+i)->num);
if((postbuf+i)->type==DIN_VAR||(postbuf+i)->type==DIN_VAR32){
idrec *ptr=(idrec *)(postbuf+i)->num;
// printf("sib=%d num=%08X %s\n",ptr->recsib,ptr->recnumber,ptr->recid);
if(ptr->recsib!=tp_gvar)continue;
puts("recsib=tp_gvar");
if(ptr->recpost==USED_DIN_VAR){
unsigned int otok,otok2;
ITOK oitok;
oitok=itok;
otok=tok;
otok2=tok2;
setdindata(ptr,i);
itok=oitok;
tok=otok;
tok2=otok2;
}
else{
if((postbuf+i)->type==DIN_VAR)*(unsigned short *)&output[(postbuf+i)->loc]+=(unsigned short)(ptr->recnumber);
else *(unsigned long *)&output[(postbuf+i)->loc]+=ptr->recnumber;
}
if(FixUp)(postbuf+i)->type=(unsigned short)((postbuf+i)->type==DIN_VAR?FIX_VAR:FIX_VAR32);
else killpost(i--);
}
}
dopoststrings();
}
*/
treelocalrec *ftlr,*ftlr1;
struct localrec *ptr, *ptr1;
for(ftlr=btlr;ftlr!=NULL;){
ftlr1=ftlr;
for(ptr=ftlr->lrec;ptr!=NULL;){
ptr1=ptr;
if(ptr->rec.rectok==tk_locallabel){ /* check for unresolved labels */
char holdstr[32+IDLENGTH];
sprintf(holdstr,"local jump label '%s' unresolved",ptr1->rec.recid);
preerror(holdstr);
}
// printf("type=%d post=%08X %s\n",ptr->rec.type,ptr->rec.recpost,ptr->rec.recid);
if(ptr->rec.rectok==tk_structvar){
if(ptr->rec.count==0){
warningnotused(ptr->rec.recid,5);
if(ptr->rec.type==tp_gvar)free(ptr->rec.sbuf);
}
}
else if(ptr->fuse<USEDVAR){
if(ptr->rec.type==tp_localvar||ptr->rec.type==tp_postvar||ptr->rec.type==tp_gvar)warningnotused(ptr->rec.recid,3);
else if(ptr->rec.type==tp_paramvar)warningnotused(ptr->rec.recid,4);
if(ptr->rec.type==tp_gvar)free(ptr->rec.sbuf);
}
ptr=ptr->rec.next;
if(ptr1->rec.recpost!=USED_DIN_VAR)free(ptr1);
}
ftlr=ftlr->next;
free(ftlr1);
}
btlr=NULL;
paramsize=0;
localsize=0;
KillTegList(ltegtree);
ltegtree=NULL;
}
/* ================ input procedures start ================= */
int loadinputfile(char *inpfile) //ñ÷èòûâàíèå ôàéëà â ïàìÿòü
{
unsigned long size;
int filehandle;
if((filehandle=open(inpfile,O_BINARY|O_RDONLY))==-1)return -2;
if((size=getfilelen(filehandle))==0){
badinfile(inpfile);
close(filehandle);
return(-1);
}
if(totalmodule==0){
startfileinfo=(struct FILEINFO *)MALLOC(sizeof(FILEINFO));
totalmodule=1;
currentfileinfo=0;
}
else{ //ïîèñê åìåíè ôàéëà â ñïèñêå îáðàáîòàííûõ
for(currentfileinfo=0;currentfileinfo<totalmodule;currentfileinfo++){
if(stricmp(inpfile,(startfileinfo+currentfileinfo)->filename)==0)break;
}
if(currentfileinfo!=totalmodule){
if(crif!=FALSE)return 1;
goto cont_load;
}
totalmodule++;
startfileinfo=(struct FILEINFO *)REALLOC(startfileinfo,sizeof(FILEINFO)*(totalmodule));
}
(startfileinfo+currentfileinfo)->stlist=NULL;
(startfileinfo+currentfileinfo)->filename=(char *)MALLOC(strlen(inpfile)+1);
strcpy((startfileinfo+currentfileinfo)->filename,inpfile);
(startfileinfo+currentfileinfo)->numdline=0;
//GetFileTime(filehandle,&(startfileinfo+currentfileinfo)->time); // bug
// getftime(filehandle,&(startfileinfo+currentfileinfo)->time);
cont_load:
staticlist=(startfileinfo+currentfileinfo)->stlist;
input=(unsigned char *)MALLOC(size+1);
printf("%08lX %s %lu\n",input,inpfile,size);
if((endinptr=read(filehandle,input,size))!=size){
printf("%d\n",endinptr);
errorreadingfile(inpfile);
close(filehandle);
return(-1);
}
close(filehandle);
return(0);
}
void notnegit(int notneg)
/* produce NOT .. or NEG .. */
{
int wordadd=0,i=0;
getoperand();
switch(tok){
case tk_reg: wordadd=1; op66(r16);
ClearReg(itok.number);
case tk_beg:
if(optimizespeed&&(chip==5||chip==6)){
if(wordadd==0&&itok.number==AL)outword(0xFF34);
else{
if(wordadd)op(0x83);
else op(0x80);
op(0xF0+itok.number);
op(0xFF);
}
if(notneg){
if(wordadd){
op66(r16);
op(0x40+itok.number);
}
else{
op(0xFE);
op(0xC0+itok.number);
}
}
}
else{
op(0xF6+wordadd);
op(0xD0+notneg+itok.number);
}
if(wordadd==0)ClearReg(itok.number&3);
break;
case tk_wordvar:
case tk_intvar: wordadd=1;
i=1;
case tk_bytevar:
case tk_charvar:
i++;
CheckAllMassiv(bufrm,i,&strinf);
if(wordadd)op66(r16);
outseg(&itok,2);
if((!notneg)&&optimizespeed&&(chip==5||chip==6)){
op(wordadd!=0?0x83:0x80);
op(0x30+itok.rm);
outaddress(&itok);
op(0xFF);
}
else{
op(0xF6+wordadd);
op(0x10+notneg+itok.rm);
outaddress(&itok);
}
KillVar(itok.name);
break;
case tk_reg32:
op66(r32);
if(optimizespeed&&(chip==5||chip==6)){
op(0x83);
outword(0xFFF0+itok.number);
if(notneg){
op66(r32);
op(0x40+itok.number);
}
}
else{
op(0xF7);
op(0xD0+notneg+itok.number);
}
if(cpu<3)cpu=3;
ClearReg(itok.number);
break;
case tk_reg64:
int r1,r2;
r1=itok.number&255;
r2=itok.number/256;
op66(r32);
op(0xF7);
op(0xD0+notneg+r2); // NEG reg
op66(r32);
op(0xF7);
op(0xD0+notneg+r1); // NEG reg
op66(r32);
op(0x83);
op(0xD8+r2);
op(0);
ClearReg(r1);
ClearReg(r2);
break;
case tk_longvar:
case tk_dwordvar:
CheckAllMassiv(bufrm,4,&strinf);
op66(r32);
outseg(&itok,2);
if((!notneg)&&optimizespeed&&(chip==5||chip==6)){
op(0x83);
op(0x30+itok.rm);
outaddress(&itok);
op(0xFF);
}
else{
op(0xF7);
op(0x10+notneg+itok.rm);
outaddress(&itok);
}
if(cpu<3)cpu=3;
KillVar(itok.name);
break;
case tk_qword:
itok.number+=4;
compressoffset(&itok);
for(i=0;i<2;i++){
CheckAllMassiv(bufrm,8,&strinf);
op66(r32);
outseg(&itok,2);
op(0xF7);
op(0x10+notneg+itok.rm);
outaddress(&itok);
if(i==1)break;
itok.number-=4;
compressoffset(&itok);
}
itok.number-=4;
compressoffset(&itok);
CheckAllMassiv(bufrm,8,&strinf);
op66(r32);
outseg(&itok,2);
op(0x83); op(0x18+itok.rm);
outaddress(&itok);
op(0);
KillVar(itok.name);
if(cpu<3)cpu=3;
break;
case tk_doublevar:
i=4;
case tk_floatvar:
if(notneg!=8)illegalfloat();
CheckAllMassiv(bufrm,4+i,&strinf);
outseg(&itok,2); //fld var
op(0xd9+i);
op(itok.rm);
outaddress(&itok);
outword(0xe0d9); //fchs
outseg(&itok,2);//fstp var
op(0xd9+i);
op(itok.rm+0x18);
outaddress(&itok);
fwait3();
break;
default: varexpected(0);
}
}
void setreturn()
{
if(numreturn){
unsigned int pos,dist;
//int j=0;
//restart:
for(int i=0;i<numreturn;i++){
// if(!(listreturn+i)->use)continue;
pos=(listreturn+i)->loc;
dist=outptr-pos;
if((listreturn+i)->type==tk_RETURN){
dist--;
// if(dist){
if(dist>127/*&&i>=j*/)jumperror((listreturn+i)->line,mesRETURN);
output[pos]=(unsigned char)dist;
/* }
else{
outptr-=2;
j=i;
(listreturn+i)->use=FALSE;
goto restart;
}*/
}
else{
dist-=(am32==0?2:4);
// if(dist){
if(dist<128/*&&i>=j*/)warningjmp(mesRETURN,(listreturn+i)->line,currentfileinfo);
if(am32)*(unsigned long *)&output[pos]=dist;
else*(unsigned short *)&output[pos]=(unsigned short)dist;
/* }
else{
outptr-=3;
if(am32)outptr-=2;
j=i;
(listreturn+i)->use=FALSE;
goto restart;
}*/
}
}
free(listreturn);
listreturn=NULL;
numreturn=0;
}
}
void RestoreSaveReg()
{
if(psavereg->all){
op(0x61);
addESP-=am32==FALSE?16:32;
}
else{
for(int i=7;i>=0;i--){
if(psavereg->reg[i]){
op66(psavereg->reg[i]);
op(0x58+i);
addESP-=am32==FALSE?2:4;
}
}
}
}
void AddRetList(int pos,int line,int type)
{
if(numreturn==0)listreturn=(RETLIST *)MALLOC(sizeof(RETLIST));
else listreturn=(RETLIST *)REALLOC(listreturn,sizeof(RETLIST)*(numreturn+1));
(listreturn+numreturn)->loc=pos;
(listreturn+numreturn)->line=line;
(listreturn+numreturn)->type=type;
// (listreturn+numreturn)->use=TRUE;
if(type==tk_return)jumploc0();
else outword(0x00EB); // JMP SHORT
numreturn++;
}
void RetProc()
{
if((current_proc_type&f_far)){
if((current_proc_type&f_typeproc)==tp_cdecl)retf();
else{
if(paramsize==0)retf(); /* RETF */
else{
op(0xCA);
outword(paramsize);
}
}
}
else{
if((current_proc_type&f_typeproc)==tp_cdecl)ret();
else if(current_proc_type==f_interrupt)op(0xCF);//interrupt procedure IRET
else{
if(paramsize==0)ret(); /* RET */
else{
op(0xC2);
outword(paramsize);
}
}
}
}
void doreturn(int typer) /* do return(...); */
{
char sign=0;
int line=linenumber;
char *ofsstr=NULL;
int i;
unsigned int oaddESP=addESP;
if(tok2==tk_openbracket)nexttok();
if((ofsstr=GetLecsem(tk_closebracket,tk_semicolon))){
int retreg;
int razr=getrazr(returntype);
if((retreg=CheckIDZReg(ofsstr,AX,razr))!=NOINREG){
GetEndLex(tk_closebracket,tk_semicolon);
if(razr==r16)tok=tk_reg;
else if(razr==r32)tok=tk_reg32;
else tok=tk_beg;
itok.number=retreg==SKIPREG?AX:retreg;
goto nn1;
}
}
getoperand();
if(tok!=tk_closebracket&&tok!=tk_semicolon){
nn1:
switch(returntype){
case tk_int: sign=1;
case tk_word: do_e_axmath(sign,r16,&ofsstr); break;
case tk_char: sign=1;
case tk_byte: doalmath(sign,&ofsstr); break;
case tk_long: sign=1;
case tk_dword: do_e_axmath(sign,r32,&ofsstr); break;
case tk_qword:
getintoreg64(EAX|(EDX*256));
if(itok.type!=tp_stopper&&tok!=tk_eof&&itok.type!=tp_compare)doregmath64(EAX|(EDX*256));
break;
case tk_void: retvoid(); nexttok(); break;
case tk_double:
/* if(tok2==tk_closebracket)doregmath64(EAX|(EDX*256));
else doeaxfloatmath(tk_reg64);
break;*/
case tk_fpust:
doeaxfloatmath(tk_fpust);
break;
case tk_float:
if(itok2.type==tp_stopper&&(tok==tk_floatvar||tok==tk_number)){
if(tok==tk_floatvar){
tok=tk_dwordvar;
do_e_axmath(0,r32,&ofsstr);
}
else doeaxfloatmath(tk_reg32,0,0);
}
else{
doeaxfloatmath(tk_stackstart,0,0);
op66(r32);
op(0x58); //pop eax
}
break;
// default:
// printf("returntype=%d\n",returntype);
}
}
if(tok==tk_closebracket)nexttok();
seminext();
if(ofsstr)free(ofsstr);
clearregstat();
#ifdef OPTVARCONST
ClearLVIC();
#endif
if(typer!=tokens){
i=(am32==0?2:4);
if(typer==tk_RETURN)i=1;
if(paramsize||localsize)i--;
if(insertmode||((!optimizespeed)&&paramsize&&
(current_proc_type&f_typeproc)!=tp_cdecl)||psavereg->size>i){
if(numblocks>1){ //çàìåíèòü return íà goto
AddRetList(outptr+1,line,typer);
retproc=TRUE;
return;
}
else{
setreturn();
if(insertmode)return;
}
}
}
if(numblocks==1)setreturn(); //06.09.04 22:20
if(!inlineflag)leaveproc();
else{
AutoDestructor();
RestoreStack();
RestoreSaveReg();
RetProc();
}
retproc=TRUE;
if(numblocks>1||(numblocks==1&&tok!=tk_closebrace))addESP=oaddESP;
}
int IsSaveReg()
{
if(psavereg->all)return TRUE;
for(int i=7;i>=0;i--){
if(psavereg->reg[i])return TRUE;
}
return FALSE;
}
void leaveproc()
{
AutoDestructor();
RestoreStack();
RestoreSaveReg();
if(ESPloc==FALSE||am32==FALSE){
if(localsize)Leave();
else if(paramsize)op(0x5D); /* POP BP */
else if(initBP)Leave();
}
else if(localsize){
if(short_ok(localsize,TRUE)){
outword(0xC483);
op(localsize);
}
else{
outword(0xC481);
outdword(localsize);
}
}
RetProc();
}
DLLLIST *FindDLL()
{
DLLLIST *newdll;
if(listdll!=NULL){ //ñïèñîê DLL íå ïóñò
for(newdll=listdll;stricmp(newdll->name,(char *)string)!=0;newdll=newdll->next){
if(newdll->next==NULL){ //ïîñëåäíÿÿ â ñïèñêå
newdll->next=(DLLLIST *)MALLOC(sizeof(DLLLIST));//ñîçäàòü íîâóþ
newdll=newdll->next;
newdll->next=NULL;
newdll->num=0;
newdll->list=NULL;
strcpy(newdll->name,(char *)string);
break;
}
}
}
else{
listdll=newdll=(DLLLIST *)MALLOC(sizeof(DLLLIST));
newdll->next=NULL;
newdll->num=0;
newdll->list=NULL;
strcpy(newdll->name,(char *)string);
}
return newdll;
}
void declareextern()
{
int next;
nexttok();
if(comfile==file_w32&&strcmp(itok.name,"WINAPI")==0){
nexttok();
if(tok!=tk_string)stringexpected();
DLLLIST *newdll;
newdll=FindDLL();
nextexpecting2(tk_openbrace); //îòêðûòèå ñïèñêà ïðîöåäóð
APIPROC *listapi=newdll->list;
returntype=tk_declare;
do{
if(tok==tk_enum)doenum();
else if(tok==tk_struct)InitStruct();
else{
next=TRUE;
if(testInitVar(FALSE)!=FALSE)preerror("Error declare WINAPI");
if(itok.rm==tokens)itok.rm=tk_dword;
if(itok.npointr)itok.rm=(am32==TRUE?tk_dword:tk_word);
ITOK hitok=itok;
int htok=tok;
param[0]=0;
hitok.sib=hitok.size=-1;
if(tok2==tk_period){
nexttok();
if(tok2==tk_number){
nexttok();
hitok.sib=itok.number;
}
}
if(tok2==tk_at){
nexttok();
if(tok2==tk_number){
nexttok();
hitok.size=itok.number;
}
}
else{
nextexpecting2(tk_openbracket);
if((hitok.flag&f_typeproc)==tp_fastcall)declareparamreg();
else declareparamstack();
}
if(htok==tk_id||htok==tk_ID){
tok=tk_apiproc;
itok=hitok;
itok.number=secondcallnum++;
itok.segm=NOT_DYNAMIC;
itok.post=dEBX|dEDI|dESI; //05.09.04 01:36
strcpy((char *)string,param);
itok.type=tp_ucnovn;
if(newdll->num==0)listapi=(APIPROC *)MALLOC(sizeof(APIPROC)); //ïåðâàÿ â ñïèñêå
else listapi=(APIPROC *)REALLOC(listapi,sizeof(APIPROC)*(newdll->num+1));
(listapi+newdll->num)->recapi=addtotree(itok.name);
if(tok2==tk_openbracket){
next=0;
nexttok();
IsUses((listapi+newdll->num)->recapi);
}
newdll->num++;
}
else warningdefined(hitok.name);
if(next)nexttok();
seminext();
}
}while(tok!=tk_closebrace);
returntype=tokens;
newdll->list=listapi;
nexttok();
}
else{
itok.flag=f_extern;
switch(tok){
case tk_far:
case tk_cdecl:
case tk_pascal:
case tk_stdcall:
case tk_fastcall:
case tk_declare:
case tk_undefproc:
case tk_ID:
case tk_id:
case tk_float:
case tk_long:
case tk_dword:
case tk_word:
case tk_byte:
case tk_char:
case tk_int:
case tk_void:
int j;
if((j=testInitVar())==FALSE)define_procedure();
else if(j==TRUE)globalvar();
break;
case tk_struct: InitStruct(); break;
default: preerror("Error declare extern");
}
if((!fobj)&&(!sobj))preerror("extern using only for compilation obj files");
}
}
int testInitVar(int checkaldef)
{
unsigned int ffar=0;
unsigned int fexport=0;
unsigned int tproc=0;
unsigned int fretproc=0;
int rettype=tokens;
unsigned int flag=itok.flag;
unsigned int npointr=0;
if(fstatic){
flag|=f_static;
fstatic=FALSE;
}
if(tok==tk_inline){
flag=f_inline;
nexttok();
}
for(;;){
if(tok==tk_far)ffar=f_far;
else if(tok==tk_export)fexport=f_export;
else if(tok>=tk_pascal&&tok<=tk_fastcall)tproc=tok;
else if((tok>=tk_void&&tok<=tk_double)||tok==tk_fpust){
if(rettype!=tokens)unknowntype();
rettype=tok;
}
else if(tok==tk_id){
if(CheckDef())continue;
if(tok2==tk_dblcolon)goto classdecl;
if(tproc==0)tproc=(comfile==file_w32?tp_stdcall:tp_pascal); //òèï ïðîö ïî óìîë÷àíèþ
else tproc=(tproc-tk_pascal)*2;
break;
}
else if(tok==tk_ID){
if(CheckDef())continue;
if(tok2==tk_dblcolon){
classdecl:
itok.flag=(unsigned int)(flag|ffar|fexport|fretproc|f_classproc);
itok.rm=rettype;
itok.npointr=(unsigned short)npointr;
doclassproc(tproc);
return 2;
}
if(tproc==0)tproc=tp_fastcall; //òèï ïðîö ïî óìîë÷àíèþ
else tproc=(tproc-tk_pascal)*2;
break;
}
else if(tok==tk_undefproc||tok==tk_declare/*||tok==tk_apiproc*/){
flag|=itok.flag; //new 18.04.07 12:19
if(tproc==0){
if(CidOrID()==tk_ID)tproc=tp_fastcall;
else tproc=(comfile==file_w32?tp_stdcall:tp_pascal);
}
else tproc=(tproc-tk_pascal)*2; // 17.09.05 17:06
if((flag&f_extern)!=0||tproc!=(itok.flag&f_typeproc)||
ffar!=(itok.flag&f_far)||(unsigned short)npointr!=itok.npointr||
((flag&f_static)&&(itok.flag&f_static)==0)){
if(strcmp(itok.name,"main")){
if(rettype==itok.rm||(rettype==tokens&&(itok.rm==(am32==0?tk_word:tk_dword))))break;
// printf("rm=%d rmnew=%d\n",itok.rm,rettype);
if(checkaldef)redeclare(itok.name);
}
}
break;
}
else if(tok==tk_proc||tok==tk_apiproc){
if(checkaldef)idalreadydefined();
break;
}
else if((tok>=tk_bits&&tok<=tk_doublevar)||tok==tk_structvar||tok==tk_pointer){
idalreadydefined();
return 2;
}
else if(tok==tk_mult){
do{
npointr++;
nexttok();
}while(tok==tk_mult);
if(rettype==tokens)rettype=am32==FALSE?tk_word:tk_dword;
continue;
}
else if(tok==tk_openbracket){
if(tok2!=tk_mult){
unuseableinput();
return 2;
}
if(tproc!=0)tproc=(tproc-tk_pascal)*2;
itok.flag=(unsigned int)(flag|ffar|tproc|fexport|fretproc);
itok.rm=rettype;
itok.npointr=(unsigned short)npointr;
return TRUE;
}
else if((tok>=tk_overflowflag&&tok<=tk_notzeroflag)||tok==tk_minusflag||
tok==tk_plusflag)fretproc=(tok-tk_overflowflag+1)*256;
else if(tok==tk_static)flag|=f_static;
else if(tok==tk_fpust)rettype=tk_fpust;
else{
unuseableinput();
return 2;
}
nexttok();
}
itok.flag=(unsigned int)(flag|ffar|tproc|fexport|fretproc);
itok.rm=rettype;
itok.npointr=(unsigned short)npointr;
if(returntype==tk_declare&&
(tok2==tk_openbracket||tok2==tk_at||tok2==tk_period))return FALSE;
if(tok2==tk_openbracket)return CheckDeclareProc();
if(rettype==tokens){
thisundefined(itok.name);//02.09.04 20:55 was unuseableinput();
return 2;
}
return TRUE;
/*-----------------23.12.01 02:11-------------------
rerurn:
FALSE - åñëè îïðåäåëåíèå, âñòàâêà ïðîöåäóðû
TRUE - ïåðåìåííàÿ èëè îáúÿâëåíèå ïðîöåäóðû
2 - îøèáêà èëè îáðàáîòàíî - íèêàêèõ äåéñòâèé íå ïðåäïðèíèìàòü.
--------------------------------------------------*/
}
int CidOrID()
{
unsigned char cha;
unsigned char *string4=(unsigned char *)itok.name;
for(;;){
cha=*string4;
if(cha>='a'&&cha<='z')return tk_id;
if(cha==0)break;
string4++;
}
return tk_ID;
}
void unpackteg(structteg *tteg)
{
int i;
elementteg *bazael;
structteg *newteg;
int ssize,count;
idrec *newrec,*ptr;
if(alignword){ //âûðîâíÿòü íà ÷åòíûé àäðåñ
if(am32==0){
if(postsize%2==1)postsize++;
}
else if(ssize==4&&postsize%4!=0)postsize+=4-(postsize%4);
}
bazael=tteg->baza;
string[0]=0;
for(i=0;i<tteg->numoper;i++){
// printf("tok=%d %s\n",(bazael+i)->tok,(bazael+i)->name);
switch((bazael+i)->tok){
case tk_floatvar:
case tk_longvar:
case tk_dwordvar:
case tk_wordvar:
case tk_bytevar:
case tk_charvar:
case tk_intvar:
case tk_doublevar:
case tk_qwordvar:
ssize=GetVarSize((bazael+i)->tok); //ðàçìåð ïåðåìåííîé
itok.type=tp_ucnovn;
tok=(bazael+i)->tok;
count=FindOff((unsigned char *)(bazael+i)->name,VARPOST);
itok.post=1;
itok.segm=DS;
itok.number=postsize;
itok.flag=tteg->flag;
itok.size=(bazael+i)->numel*ssize;
itok.rm=(am32==FALSE?rm_d16:rm_d32);
itok.npointr=0;
newrec=addtotree((bazael+i)->name);
newrec->count=count;
break;
case tk_struct:
case tk_structvar:
strcpy(itok.name,(bazael+i)->name);
newteg=(structteg *)(bazael+i)->nteg;
newrec=(struct idrec *)MALLOC(sizeof(struct idrec));
ptr=((tteg->flag&f_static)==0?treestart:staticlist); //íà÷àëî äåðåâà
if(ptr==NULL)((tteg->flag&f_static)==0?treestart:staticlist)=newrec;//íà÷àëî äåðåâà
else{ //ïîèñê ñòðîêè â äåðåâå
while(((ssize=strcmp(ptr->recid,itok.name))<0&&ptr->left!=NULL)||(ssize>0&&ptr->right!=NULL)){
ptr=(ssize<0?ptr->left:ptr->right);
}
(ssize<0?ptr->left:ptr->right)=newrec; //ñòðîêà ìåíüøå
}
newrec->recsib=0;
strcpy(newrec->recid,itok.name);//ñêîïèð íàçâàíèå
newrec->newid=(char *)newteg;
newrec->left=NULL;
newrec->right=NULL;
newrec->rectok=tk_structvar;
newrec->flag=tteg->flag|newteg->flag;
newrec->line=linenumber;
newrec->file=currentfileinfo;
if(FixUp)newrec->flag|=f_reloc;
newrec->recrm=(bazael+i)->numel;
newrec->recsize=(bazael+i)->numel*newteg->size;
newrec->recpost=1;
count=FindOff((unsigned char *)newrec->recid,VARPOST);
newrec->count=count;
break;
default:
declareanonim();
break;
}
}
AddPostData(tteg->size);
}
void unpackteg2(structteg *tteg)
{
int i;
elementteg *bazael;
structteg *newteg;
//idrec *newrec,*trec;
localrec *lrec;
bazael=tteg->baza;
string[0]=0;
for(i=0;i<tteg->numoper;i++){
switch((bazael+i)->tok){
case tk_floatvar:
case tk_longvar:
case tk_dwordvar:
case tk_wordvar:
case tk_bytevar:
case tk_charvar:
case tk_intvar:
case tk_doublevar:
case tk_qwordvar:
lrec=addlocalvar((bazael+i)->name,(bazael+i)->tok,localsize);
lrec->rec.recsize=(bazael+i)->numel*GetVarSize((bazael+i)->tok);
lrec->rec.type=tp_localvar;
lrec->rec.npointr=0;
lrec->rec.recnumber=-lrec->rec.recnumber-Align(lrec->rec.recsize,(am32==FALSE?2:4));
break;
case tk_struct:
case tk_structvar:
newteg=(structteg *)(bazael+i)->nteg;
lrec=addlocalvar((bazael+i)->name,tk_structvar,localsize);
lrec->rec.newid=(char *)tteg;
lrec->rec.flag=tteg->flag;
lrec->rec.type=tp_localvar;
lrec->rec.recrm=(bazael+i)->numel;
lrec->rec.recsize=(bazael+i)->numel*newteg->size;
lrec->rec.recpost=LOCAL;
lrec->rec.recnumber=-lrec->rec.recnumber-Align(lrec->rec.recsize,(am32==FALSE?2:4));
break;
default:
declareanonim();
break;
}
}
localsize+=tteg->size;
localsize=Align(localsize,(am32==FALSE?2:4));
}
unsigned long dounion(int Global,int flag)
{
structteg *tteg;
int noname=FALSE;
nexttok();
if(tok==tk_openbrace)noname=TRUE;
else if((tok!=tk_id&&tok!=tk_ID)||FindTeg(Global)||(Global==FALSE&&FindTeg(TRUE))){
idalreadydefined();
SkipBlock2();
return 0;
}
if((tteg=CreatTeg(Global,TRUE,noname))!=NULL){
if(tok==tk_semicolon){
if(noname==TRUE){
if(Global)unpackteg(tteg);
else unpackteg2(tteg);
if(tteg->baza)free(tteg->baza);
free(tteg);
}
nexttok();
}
else{
if(Global)InitStruct2(flag,tteg);
else return LocalStruct2(flag,0,0,0,tteg);
}
}
else declareunion();
return 0;
}
char *BackString(char *str)
{
char *retbuf=(char *)MALLOC(strlen(str)+1);
strcpy(retbuf,str);
return retbuf;
}
void GetFileTime(int fd,struct ftime *buf)
{
/*
struct stat sb;
struct tm *tblock;
fstat(fd,&sb);
tblock=localtime(&sb.st_atime);
buf->ft_tsec=tblock->tm_sec;
buf->ft_min=tblock->tm_min;
buf->ft_hour=tblock->tm_hour;
buf->ft_day=tblock->tm_mday;
buf->ft_month=tblock->tm_mon;
buf->ft_year=tblock->tm_year-80;*/
}
void CheckPosts()
{
if(posts==maxposts){
maxposts+=MAXPOSTS;
postbuf=(postinfo *)REALLOC(postbuf,maxposts*sizeof(postinfo));
}
}
void CheckRealizable()
{
switch(tok){
case tk_case:
case tk_CASE:
case tk_default:
case tk_closebrace:
return;
}
if(tok2==tk_colon)return;
if(notunreach){
notunreach=FALSE;
return;
}
warningunreach();
// preerror("Unreachable code");
}
void AddRegistr(int razr,int reg)
{
if(razr==r8&&reg>3)reg-=4;
if(razr==r64){
stat_reg[reg&255]=1;
stat_reg[reg/256]=1;
}
else stat_reg[reg]=1;
}
void ClearRegister()
{
for(int i=0;i<8;i++)stat_reg[i]=0;
}
int GetRegister(int mode)
{
int reg=SI;
if(am32!=FALSE||mode){
if(stat_reg[AX]==0)reg=AX;
else if(stat_reg[SI]==0)reg=SI;
else if(stat_reg[DI]==0)reg=DI;
else if(stat_reg[BX]==0)reg=BX;
else if(stat_reg[CX]==0)reg=CX;
else if(stat_reg[DX]==0)reg=DX;
}
else{
if(stat_reg[SI]==0)reg=SI;
else if(stat_reg[DI]==0)reg=DI;
else if(stat_reg[BX]==0)reg=BX;
}
return reg;
}
void RegAddNum(int reg)
{
if((!structadr.post)&&optnumadd(structadr.number,reg,am32==FALSE?r16:r32,0)!=FALSE)return;
if(reg==AX)op(5);
else{
op(0x81);
op(0xC0+reg);
}
if(structadr.post)setwordpost(&structadr);
if(am32)outdword(structadr.number);
else outword(structadr.number);
}
void RestoreStack()
{
if(addstack&&sizestack){
if(short_ok(sizestack,am32)){
outword(0xC483);
op(sizestack);
}
else{
outword(0xC481);
if(am32==FALSE)outword(sizestack);
else outdword(sizestack);
}
// printf("%s(%d)> Restore %d bytes stacks.\n",startfileinfo==NULL?"":(startfileinfo+currentfileinfo)->filename,linenumber,sizestack);
addESP-=sizestack;
sizestack=0;
}
}
void startblock()
{
treelocalrec *nrec;
numblocks++;
// printf("start block %d\n",numblocks);
nrec=(treelocalrec*)MALLOC(sizeof(treelocalrec));
nrec->level=numblocks;
nrec->lrec=NULL;
nrec->addesp=addESP;
nrec->next=tlr;
tlr=nrec;
}
void endblock()
{
treelocalrec *orec;
// printf("end block %d\n",numblocks);
orec=tlr;
tlr=tlr->next;
if(tlr)numblocks=tlr->level;
else numblocks=0;
if(orec->lrec==NULL){
free(orec);
return;
}
orec->endline=linenumber;
orec->next=btlr;
btlr=orec;
// if(addESP!=orec->addesp)???
}
/* end of TOKC.C */