//===== « £¨ ª®¬¯¨«ï樨
#pragma option w32c
#stack 0x8000
#argc TRUE
//===== ®¤ª«îç ¥¬ë¥ ¬®¤ã«¨
#include "wapi.h--"
#include "enums.h--"
#include "data.h--"
#include "opcodesc.h--"
#include "tree.h--"
#include "directiv.h--"
#include "tokscan.h--"
#include "exe.h--"
#include "generate.h--"
#include "parser.h--"
//===== « ¢ ï äãªæ¨ï ¯à®£à ¬¬ë
main()
dword count,pari,cmdline;
{
stdout=GetStdHandle(STD_OUTPUT_HANDLE);
WRITESTR("\n32-Compiler Version 0.01\tXAC (C) 1999.");
WRITESTR("\nBased on SPHINX C-- Compiler Peter Cellik (C) 1995.\n");
// §¡®à ª®¬¬ ¤®© áâப¨: 32.exe <SourceFileName> [/map] [/debug]
pari=@PARAMCOUNT();
for(count=1;count<pari;count++){ //®¡à ¡®âª ª®¬ ¤®© áâப¨
cmdline=@PARAMSTR(count);
CharUpperA(EAX);
CharToOemA(cmdline,cmdline); // ८¡à §ã¥¬ ¢ ¢ OEM ª®¤à®¢ª¥
ESI=cmdline;
IF(DSBYTE[ESI]=='/'){
ESI++;
IF(lstrcmpA("MAP",ESI)==0)makemapfile = 1;
ELSE IF(lstrcmpA("DEBUG",ESI)==0)dbg=1;
ELSE{
WRITESTR("ERROR > Unknown command line option: '");
WRITESTR(cmdline);
WRITESTR("'\n");
ExitProcess(e_unknowncommandline);
}
}
ELSE{ // ®¯¨à㥬 ¨¬ï ¨á室®£® ä ©« ¡¥§ à áè¨à¥¨ï
EDI=#rawfilename;
for(;;){
$LODSB
IF(AL=='.')||(AL==0)BREAK; //
áâì à áè¨à¥¨¥?
$STOSB;
}
AL=0;
$STOSB;
lstrcpyA(#inputfile,cmdline); // ®¯¨à㥬 ¨¬ï ¢å®¤®£® ä ©« á à áè¨à¥¨¥¬
}
}
IF(rawfilename[0]==0){
errmsg();
WRITESTR("No input file specified");
pari=1;
}
IF(pari < 2){
WRITESTR("\nUsage: 32.exe [/MAP] [/DEBUG] <Source file>");
WRITESTR("\n\t/MAP\t<< generate map file");
WRITESTR("\n\t/DEBUG\t<< generate .TDS - debug info file\n");
ExitProcess(e_noinputspecified);
}
GetMem(); // ¢ë¤¥«¥¨¥ ¯ ¬ï⨠¤«ï ª®¬¯¨«ï樨
TokInit(); // ¨¨æ¨ «¨§ æ¨ï ᯨ᪮¢
Compile();
IF( error == 0 )EAX=e_ok;
ELSE EAX=e_someerrors;
ExitProcess(EAX);
}
//===== ®¬¯¨«ïâ®à
Compile()
{
IF(makemapfile)StartMapfile();
WRITESTR("Compiling ...\n");
Preview(#inputfile);
CompileAll();
/*if( endifcount > 0 )
preerror("#endif expected before end of file");
if( outptr%16 != 0 ) // paragraph align the end of the code seg
outptr += 16 - outptr%16;*/
DoLink(); // ®à¬¨à®¢ ¨¥ link
IF(posts > 0)DoPosts(); // ¡®¢«¥¨¥ ¢á¥å post ¤à¥á®¢
SeekUndefined(treestart);
if(error==0){
wsprintfA(#mapstr,"\nCOMPILING FINISHED.\tErrors: %d\tLines: %u\n",error,totallines);
WRITESTR(#mapstr);
runfilesize = outptr-output;
postsize += postsize%2;
PrintMemsizes(GetStdHandle(STD_OUTPUT_HANDLE));
IF(WriteEXE()==0) {
wsprintfA(#mapstr,"\nRun File Saved (%ld bytes).\n",runfilesize);
WRITESTR(#mapstr);
wsprintfA(#mapstr,"DLL: %d\tAPI: %d \n",DLLcount,APIcount);
WRITESTR(#mapstr);
}
// if(dbg)
// dotds(); // do turbo debugger line info
}
IF(makemapfile)FinishMapfile();
}
// ---- ।¢ à¨â¥«ì ï ®¡à ¡®âª ä ©«
Preview(dword filename)
long hold;
char trialfilename[FILENAMESIZE];
{
lstrcpyA(#trialfilename,filename);
hold = LoadInputfile(#trialfilename);
IF(EAX==-2)unabletoopen(#trialfilename);
IF(hold!=0)ExitProcess(e_cannotopeninput);
lstrcpyA(#currentfilename,#trialfilename);
module++;
IF(module<MAXMDL) {
lstrcpyA(FILENAMESIZE*module+#modules,#currentfilename);
currmod = module;
}
IF(makemapfile){
EBX=inptr;
cha=DSBYTE[EBX];
wsprintfA(#mapstr,"File %s included.\n\n%c",#currentfilename,cha);
fprint(mapfile,#mapstr);
}
ShowSrcLine();
NextChar();
cha2 = cha;
inptr2=inptr;
linenum2 = 1;
NextTok();
WHILE(tok!=tk_eof){ // ®ª ¥ ª®ç¨âáï ¢å®¤®© ¡ãä¥à
IF(tok==tk_directive){
GetDirAddr(#Jmp_Directives,number);
EAX();
}
ELSE IF(tok==tk_command){
GetDirAddr(#Jmp_Commands,number);
EAX();
}
ELSE IF(tok==tk_id)GetProc(tk_void);
ELSE IF(tok==tk_void){
NextTok();
GetProc(tk_void);
}
ELSE{
preerror("unuseable input");
NextTok();
}
}
LocalFree(input);
}
// ---- ®¬¯¨«ïæ¨ï ®¤®© ¯à®æ¥¤ãàë ¨«¨ ®¡ê¥¨ï ¤ ëå
CompileSrc(dword ptr)
{
EAX=src;
if(EAX){
inptr = EAX;
inptr2 = EAX;
endoffile = 0; // ç «® ¡ãä¥à
linenum2 = modline&0xFFFF;
currmod=modline>>16;
lstrcpyA(#currentfilename,FILENAMESIZE*currmod+#modules);
NextChar();
cha2 = cha;
inptr2=inptr;
IF(tok==tk_proc){
Proc(cpt_near);
DoPoststrings();
}
ELSE IF(tok==tk_var)GlobalVar(type);
ELSE preerror("Bad input format\n");
}
ELSE{ // post-¯¥à¥¬¥ ï ¡¥§ à §¬¥à®áâ¨
ESI=ptr;
DSDWORD[ESI+recnumber] = postsize;
DSDWORD[ESI+recpost] = 1;
postsize+=TypeSize(type);
}
}
// ---- ®¬¯¨«ïæ¨ï ¢á¥å ¯à®æ¥¤ãà ¨ ®¡ê¥¨© ¤ ëå
CompileAll()
{
IF(SearchTree(#tok,#type,#src,#post,"main",#number))AX=3; // Console
ELSE IF(SearchTree(#tok,#type,#src,#post,"WinMain",#number))AX=2; // GUI
ELSE{
preerror("Main not found");
return;
}
OptSubSystem=AX;
OptEntryPointRVA=OptBaseOfCode+outptr-output;
CompileSrc(treeptr); // ®¬¯¨«ïæ¨ï main
WHILE(SeekToDo(treestart)){
ESI=treeptr;
wsprintfA(#mapstr,"==>%3d %8lXh %8lXh %6Xh\t%s\n",DSDWORD[ESI+rectok],
DSDWORD[ESI+rectype],DSDWORD[ESI+recnumber],DSDWORD[ESI+recpost],
DSDWORD[ESI+recid]);
fprint(mapfile,#mapstr);
CompileSrc(treeptr); // ®¬¯¨«ïæ¨ï ¨á室¨ª®¢
}
IF(makemapfile)
fprint(mapfile,"Compile all sources\n");
}
// ---- ¡à ¡®âª ¯ à ¬¥â஢ ¯à¨ ®¡ê¥¨¨ ¯à®æ¥¤ãàë
DeclareParams()
dword paramtok,paramtype;
{
LL:
IF(tok==tk_command)GetDirAddr(#Jmp_Commands,number);
ELSE EAX=-1;
IF(EAX==#CmdShort){
paramtok = tk_param;
paramtype=tk_short;
}
ELSE IF(EAX==#CmdWord){
paramtok = tk_param;
paramtype=tk_word;
}
ELSE IF(EAX==#CmdChar){
paramtok = tk_param;
paramtype=tk_char;
}
ELSE IF(EAX==#CmdByte){
paramtok = tk_param;
paramtype=tk_byte;
}
ELSE IF(EAX==#CmdInt){
paramtok = tk_param;
paramtype=tk_int;
}
ELSE IF(EAX==#CmdDword){
paramtok = tk_param;
paramtype=tk_dword;
}
ELSE{
datatype_expected();
NextTok();
}
for(;;){
NextTok();
IF(tok==tk_id ){
paramsize += 4;
AddLocalvar(#string,paramtok,paramtype,paramsize);
}
ELSE IF(tok==tk_semicolon){
NextTok();
$JMP LL
}
ELSE IF(tok==tk_closebracket)BREAK;
ELSE IF(tok!=tk_comma)idexpected();
}
}
// ---- ¡à ¡®âª «®ª «ìëå ¯¥à¥¬¥ëå ¯à¨ ®¡ê¥¨¨ ¯à®æ¥¤ãàë
DeclareLocals()
dword size;
dword loctok,loctype;
{
LL:
IF(tok==tk_command)GetDirAddr(#Jmp_Commands,number);
IF(EAX==#CmdShort){
loctok = tk_local;
loctype=tk_short;
size = 2;
}
else IF(EAX==#CmdWord){
loctok = tk_local;
loctype=tk_word;
size = 2;
}
else IF(EAX==#CmdChar){
loctok = tk_local;
loctype=tk_char;
size = 1;
}
ELSE IF(EAX==#CmdByte){
loctok = tk_local;
loctype=tk_byte;
size = 1;
}
ELSE IF(EAX==#CmdInt){
loctok = tk_local;
loctype=tk_int;
size = 4;
}
ELSE IF(EAX==#CmdDword){
loctok = tk_local;
loctype=tk_dword;
size = 4;
}
ELSE IF(tok==tk_eof)||(tok==tk_openbrace)$JMP L1
ELSE{
datatype_expected();
NextTok();
goto LL;
}
for(;;){
NextTok();
IF(tok==tk_id){
AddLocalvar(#string,loctok,loctype,localsize);
IF(tok2==tk_openblock){
NextTok();
NextTok();
localsize += DoConstLongMath()*size;
EAX=localsize;
$TEST EAX,3;
IF(NOTZEROFLAG){
EAX=EAX>>2+1<<2;
localsize=EAX; // ëà ¢¨¢ ¨¥ dword
}
expecting(tk_closeblock);
}
ELSE localsize+=4;
}
ELSE IF(tok==tk_semicolon){
NextTok();
$JMP LL
}
ELSE IF(tok==tk_openbrace)||(tok==tk_eof)BREAK;
ELSE IF(tok!=tk_comma)idexpected();
}
L1:
IF(paramsize==0)Asm("push ebp; mov ebp,esp;");
wsprintfA(#mapstr,"sub esp,%d;",localsize);
Asm(#mapstr);
}
// ---- ¡à ¡®âª ®¡à é¥¨ï ª 㦥 ®¯¨á ®© ¯à®æ¥¤ãà¥
DoAnyProc()
byte s[80];
{
wsprintfA(#s,"call %s;",#string);
NextTok();
DoParams();
Asm(#s);
}
// ---- ¡à ¡®âª à ¥¥ ®¡ê¢«¥®©, ® ¯®ª ¥ ¨§¢¥á⮩ ¬¥âª¨
dword DoAnyUndefproc(dword expectedreturn)
byte s[80];
{
IF( tok2 == tk_colon ){ // ¬¥âª
number = outptr-output+OptImageBase+OptBaseOfCode;
tok = tk_proc;
ESI=treeptr;
DSDWORD[ESI+rectok] = tok;
DSDWORD[ESI+recnumber] = number;
DSDWORD[ESI+recpost] = 0;
NextTok(); // move past id
NextTok(); // move past :
RETURN(tokens);
}
IF( tok2 == tk_openbracket ){
wsprintfA(#s,"call %s;",#string);
NextTok();
DoParams();
Asm(#s);
RETURN(tk_dword);
}
undefinederror();
NextTok();
return(tk_int);
}
// ---- ¡à ¡®âª ®¡à é¥¨ï ª API äãªæ¨¨
dword doAPI()
dword hold;
byte s[IDLENGTH];
{
if( tok2 == tk_openbracket ){
hold = treeptr;
GetVarname(#s);
NextTok();
DoParams();
IF(posts>=MAXPOSTS){
preerror("maximum number of API procedure calls exceeded");
return(tokens);
}
EBX=hold;
IF(DSDWORD[EBX+recpost]==0) { // ¥à¢ë© ¢ë§®¢ API?
DSDWORD[EBX+recpost]=1; // ®â¬¥â¨¬ ¢ë§®¢ ¤ ®© API
APIcount++;
EAX=DSDWORD[EBX+rectype]; // ª § ⥫ì DLL, ¢ ª®â®à®¬ 室¨âáï API
DSDWORD[EAX+recmodline]++; // ¢¥«¨ç¨¬ áç¥â稪 API, ¢ë§¢ ëå ¨§ DLL
}
OUTWORD(0x15FF); // call [dword]
SetPost(hold,POST_API);
OUTDWORD(0);
IF(list){
fprint(mapfile,"\t//\tcall ");
fprint(mapfile,#s);
fprint(mapfile,"\n");
}
return(tk_int);
}
undefinederror();
NextTok();
return(tokens);
}
// ---- ¡à ¡®âª ¯à®£à ¬¬®£® ¡«®ª {...}
void DoBlock()
{
expecting(tk_openbrace);
for(;;){
IF(tok==tk_eof){
unexpectedeof();
BREAK;
}
IF(tok == tk_closebrace){
NextTok();
BREAK;
}
DoCommand();
}
}
// ---- ¡à ¡®âª ®¤®© ª®¬ ¤ë ¢ãâਠ¡«®ª
DoCommand()
{
LL:
FastSearch(#string,#St_Sizes);// â® à §¬¥à ®¯¥à ¤ ?
IF(CARRYFLAG){ // : byte,word ¨«¨ dword
type=EAX<<1+tk_byte;
string[0]=0;
tok=tk_var;
GOTO LL;
}
IF(tok==tk_mnemonics){
DoMnemonics();
NextTok();
}
else IF(tok==tk_directive){
GetDirAddr(#Jmp_Directives,number);
EAX();
}
else IF(tok==tk_command){
GetDirAddr(#Jmp_Commands,number);
EAX();
}
else IF(tok==tk_id){
DoId(tk_void);
IF(EAX!=tokens)NextSemiNext();
}
else IF(tok==tk_undefproc){
DoAnyUndefproc(tk_void);
IF(EAX!=tokens)NextSemiNext();
}
else IF(tok==tk_proc){
DoAnyProc();
NextSemiNext();
}
else IF(tok==tk_API){
IF(doAPI()!=tokens)NextSemiNext();
}
else IF(tok==tk_var)||(tok==tk_local)||(tok==tk_param)||(tok==tk_reg)DoVar(type);
ELSE IF(tok==tk_openblock)DoVar(tk_dword);
ELSE IF(tok==tk_string){
Macros();
NextSemiNext();
}
ELSE IF(tok==tk_locallabel)DoLocalPost();
ELSE IF(tok==tk_openbrace)DoBlock();
ELSE IF(tok==tk_comma)||(tok==tk_semicolon)NextTok();
ELSE IF(tok==tk_eof)unexpectedeof();
/* case tk_from:
NextTok(); DoFrom(0); NextSemiNext(); break;
case tk_extract:
NextTok(); DoExtract(0); SemiNext(); break;
*/
}
// ---- ¡à ¡®âª ®¢ëå ¨¤¥â¨ä¨ª â®à®¢
dword DoId(dword expectedreturn)
byte s[80];
{
IF(tok2 == tk_colon){ // ¬¥âª ?
number = outptr-output+OptImageBase+OptBaseOfCode;
tok = tk_proc;
post = 0;
AddToTree(#string);
NextTok(); NextTok(); // ¯à®¯ãá⨬ ¨¤¥â¨ä¨ª â®à ¨ :
EAX=tokens;
}
ELSE IF(tok2 == tk_openbracket){ // ¢ë§®¢ ¯à®æ¥¤ãàë
wsprintfA(#s,"call %s;",#string);
tok = tk_undefproc;
number=0;
post=1;
AddToTree(#string);
NextTok();
DoParams();
Asm(#s);
EAX=expectedreturn;
}
ELSE{
undefinederror();
NextTok();
EAX=tk_int;
}
}
// ---- ¡à ¡®âª ¯ à ¬¥â஢ ¯à¨ ¢ë§®¢¥ ¯à®æ¥¤ãàë
DoParams()
{
IF(tok==tk_openbracket){
inptr2--;
DoParam();
NextTok();
}
ELSE expecting(tk_openbracket);
}
// ---- ¡à ¡®âª <Var> ...
DoVar(dword vartype)
dword next,vtok;
byte varName[2*IDLENGTH];
byte varName2[2*IDLENGTH];
{
next=1;
vtok=GetVarname(#varName);
NextTok();
IF(tok==tk_assign){
NextTok();
IF(tok2notstopper()){
DoExpr(#varName,vtok,vartype,"mov");
next=0;
}
ELSE GetIntoVar(#varName,vtok,vartype);
}
else IF(tok==tk_minusminus){ // Var--;
wsprintfA(#mapstr,"dec %s",#varName);
Asm(#mapstr);
}
else IF(tok==tk_plusplus){ // Var++;
wsprintfA(#mapstr,"inc %s",#varName);
Asm(#mapstr);
}
else IF(tok==tk_plusequals){ // Var+=Expr;
NextTok();
DoExpr(#varName,tk_var,vartype,"add");
next=1;
}
else IF(tok==tk_minusequals){ // Var-=Expr;
NextTok();
DoExpr(#varName,tk_var,vartype,"sub");
next=1;
}
else IF(tok==tk_andequals){ // Var&=Expr;
NextTok();
DoExpr(#varName,tk_var,vartype,"and");
next=1;
}
else IF(tok==tk_xorequals){ // Var^=Expr;
NextTok();
DoExpr(#varName,tk_var,vartype,"xor");
next=1;
}
else IF(tok==tk_orequals){ // Var|=Expr;
NextTok();
DoExpr(#varName,tk_var,vartype,"or");
next=1;
}
else if(tok==tk_swap){ // Var><Var;
NextTok();
GetVarname(#varName2);
IF(tok==tk_reg){
wsprintfA(#mapstr,"xchg %s,%s",#string,#varName);
Asm(#mapstr);
}
else if(tok==tk_var)&&(tok2notstopper()==0){
IF(vartype==tk_dword)||(vartype==tk_int){
wsprintfA(#mapstr,"xchg %s,eax",#varName);
Asm(#mapstr);
wsprintfA(#mapstr,"xchg %s,eax",#varName2);
Asm(#mapstr);
wsprintfA(#mapstr,"xchg %s,eax",#varName);
}
else IF(vartype==tk_word)||(vartype==tk_short){
wsprintfA(#mapstr,"xchg %s,ax",#varName);
Asm(#mapstr);
wsprintfA(#mapstr,"xchg %s,ax",#varName2);
Asm(#mapstr);
wsprintfA(#mapstr,"xchg %s,ax",#varName);
}
ELSE IF(vartype==tk_byte)||(vartype==tk_char){
wsprintfA(#mapstr,"xchg %s,al",#varName);
Asm(#mapstr);
wsprintfA(#mapstr,"xchg %s,al",#varName2);
Asm(#mapstr);
wsprintfA(#mapstr,"xchg %s,al",#varName);
}
Asm(#mapstr);
}
ELSE swaperror();
}
else IF(tok==tk_llequals){ // Var<<=Expr;
NextTok();
IF(tok == tk_number) wsprintfA(#mapstr,"shl %s,%d",#varName,DoConstMath());
ELSE{
Expression("cl",tk_reg,tk_byte);
wsprintfA(#mapstr,"shl %s,cl",#varName);
next=0;
}
Asm(#mapstr);
}
ELSE IF(tok==tk_rrequals){ // Var>>=Expr;
NextTok();
IF(tok == tk_number)wsprintfA(#mapstr,"shr %s,%d",#varName,DoConstMath());
ELSE{
Expression("cl",tk_reg,tk_byte);
wsprintfA(#mapstr,"shr %s,cl",#varName);
next=0;
}
Asm(#mapstr);
}
ELSE operatorexpected();
IF(next)NextSemiNext();
ELSE SemiNext();
}
// ---- ¡à ¡®âª ááë«®ª ¢¯¥à¥¤
DoPosts()
dword addhold,i;
{
i=0;
while(i<posts){
ECX=i<<2;
ESI=posttype+ECX;
EAX=DSDWORD[ESI];
ESI=postloc+ECX;
EBX=DSDWORD[ESI];
ESI=postnum+ECX;
ECX=DSDWORD[ESI];
IF(EAX==POST_DATA){
IF(DSDWORD[ECX+recpost]){
GetDword(EBX);
EAX=EAX+DSDWORD[ECX+recnumber]+OptImageBase+OptBaseOfCode+outptr-output;
}
ELSE{
GetDword(EBX);
EAX+=DSDWORD[ECX+recnumber];
}
SetDword(EBX,EAX);
}
ELSE IF(EAX==POST_CALL){
EAX=DSDWORD[ECX+recnumber]-OptImageBase-OptBaseOfCode-EBX; // áç¥â ®â®á¨â¥«ì®£® ᬥ饨ï EAX-=addvalue;
EAX+=output;
SetDword(EBX,EAX-4);
}
ELSE IF(EAX==POST_LOC){
EAX=ECX; EAX-=OptImageBase;
EAX-=OptBaseOfCode; EAX-=EBX; // áç¥â ®â®á¨â¥«ì®£® ᬥ饨ï EAX-=addvalue;
EAX+=output; SetDword(EBX,EAX-4);
}
ELSE IF(EAX==POST_API){
addhold = OptImageBase + DSDWORD[ECX+recmodline];
SetDword(EBX,addhold);
}
ELSE preerror("Bad post type\n");
i++;
}
}
// ---- ëáâàë© ¯®¨áª ¯® â ¡«¨æ¥
// OUTPUT: EAX=No.& CARRYFLAG - success
dword FastSearch(dword probe,table)
byte ident[IDLENGTH];
{
$PUSH ECX,ESI,EDI,EDX
lstrcpyA(#ident,probe);
CharUpperA(#ident);
lstrlenA(#ident);
EDX=EAX-1;
$JZ HET // ident ¨§ ®¤®£® ᨬ¢®«
EBX=0;
BL=ident;//[0]; // ஢¥à¨¬ ¯¥à¢ë© ᨬ¢®« ¢ ident
BL-='A';
$JC HET // ¥ ¡ãª¢
$CMP BL,'Z'-'A';
$JA HET // ¨ ¥ 'A'...'Z'
EAX=0;
EBX=EBX<<2+table;
EDI=DSDWORD[EBX]; // §ïâì ¤à¥á § ¯¨á¨ ¨§ table
$OR EDI,EDI;
$JE HET // ¥â § ¯¨á¨ ¤«ï â ª®£® ident...
TRY0:
AH=DSBYTE[EDI];
EDI++; // ®¬¥à § ¯¨á¨ ¨§ table ¨ áâப㠢 table
TRY1:
ESI=#ident+1;
ECX=EDX; // §ïâì ident ¤«¨ã - 1
$REPE $CMPSB;
$JNE NXT // à ¢¨¬ á § ¯¨áìî ¢ table
$JCXZ YES1 // ®¢¯ «¨ ¯® ¤«¨¥ probe
NXT:
EDI--;
LOOK:
AL=DSBYTE[EDI];
EDI++;
$OR AL,AL;
$JE TRY0 // ஢¥à¨¬ á«¥¤ãîéãî § ¯¨áì
$CMP AL,'/';
$JE NEAR TRY1 // ஢¥à¨¬ ALIAS
$CMP AL,_END;
$JE NEAR HET // ®¥æ â ¡«¨æë - ¢ë室
GOTO LOOK;
HET:
$CLC;
GOTO EX; // ident ¥ ©¤¥ ¢ table
YES1:
$CMP DSBYTE[EDI],0;
$JZ YES;
$CMP DSBYTE[EDI],_END;
$JZ YES;
$CMP DSBYTE[EDI],'/';
$JZ YES;
GOTO NXT;
YES:
AL=AH;
AH=0;
$STC // ident ©¤¥ ¢ table
EX:
$POP EDX,EDI,ESI,ECX;
}
// ---- 뢮¤ áâ â¨á⨪¨ ¯® ª®¬¯¨«ï樨
FinishMapfile()
{
fprint(mapfile,"\n");
DisplayTree();
fprint(mapfile,"Component Sizes:\n");
PrintMemsizes(mapfile);
wsprintfA(#mapstr,"Run file size: %ld bytes\n",runfilesize);
fprint(mapfile,#mapstr);
wsprintfA(#mapstr,"\nEND OF MAP FILE FOR %s.%s\n\n",#rawfilename,"EXE");
fprint(mapfile,#mapstr);
_lclose(mapfile);
mapfile=0;
list=0;
}
// ---- 뢮¤ ¢ ä ©«
fprint(dword handle,str)
{
_lwrite(handle,str,lstrlenA(str));
}
// ---- 뤥«¥¨¥ ¯ ¬ï⨠¤«ï ª®¬¯¨«ï樨. ਠ¥ã¤ ç¥ ¢ë室 ¨§ ª®¬¯¨«ïâ®à
GetMem()
{
output=LocalAlloc(0x40,MAXDATA);
IF(EAX==NULL)outofmemory2();
LocalUnlock(output);
outptr=output;
startptr=output;
postloc=LocalAlloc(0x40,MAXPOSTS*4);
IF(EAX==NULL)outofmemory2();
postnum=LocalAlloc(0x40,MAXPOSTS*4);
IF(EAX==NULL)outofmemory2();
posttype=LocalAlloc(0x40,MAXPOSTS);
IF(EAX==NULL)outofmemory2();
dbginfo=LocalAlloc(0x40,MAXDBGS*dbg_size);
IF(EAX==NULL)outofmemory2();
dbgs=dbginfo;
}
// ---- ⥨¥ ¤¢®©®£® á«®¢
dword GetDword(dword ptr)
{
ESI><ptr;
$LODSD;
ESI><ptr;
}
// ---- ¨æ¨ « § æ¨ï ᯨáª
// «ï keylist = {"ZAK",0,"AAD",0,"ABC",0,"BAR",0,"AAA",0,"ZZ",0,"BAC",_END};
// áä®à¬¨àã¥âáï áâàãªâãà ¢ ¯ ¬ï⨠᫥¤ãî饣® ¢ ¤ :
// table
// +-----+
// | 'A' | ---> db 4,'AA',1,'AD',2,'BC',_END
// +-----+
// | 'B' | ---> db 6,'AC',3,'AR",_END
// +-----+
// | ... |
// +-----+
// | 'Z' | ---> db 0,'AK',5,'Z',_END
// +-----+
InitList(dword keylist,table)
dword ptr;
{
ptr=LocalAlloc(0x40,SORTSIZE*256);
IF(EAX==NULL)outofmemory2();
EDI><EAX; //ptr;
ESI=keylist;
ECX=0;
BL=0;
// ¥á¥¨¥ áâப ¨§ keylist ¢ ptr
for(;;){
for(;;){
$PUSH EDI;
IF(DSBYTE[ESI]!='-')BREAK;
ESI+=2;
BL++;
$POP EDI;
}
AL=BL;
$STOSB // ®åà ¨¬ ¯®à浪®¢ë© ®¬¥à áâப¨
for(;;){
$LODSB // ª®¯¨à㥬 áâப㠢 ptr
IF(AL<' ')BREAK;
$STOSB;
}
IF(AL==_END)BREAK;
$STOSB;
$POP EDI;
BL++;
EDI+=SORTSIZE;
ECX++;
}
ESI=ptr;
$PUSH ECX // ®¯¨à®¢ ¨¥ ¢ ptr § ª®ç¥®. ®åà ¨¬ ª®«-¢® áâப
ECX--;
IF(NOTZEROFLAG){// ᥣ® ®¤ áâப ? - á®àâ¨à®¢ª ¥ ã¦
// ®àâ¨à®¢ª áâப ¢ ptr
loop(ECX){
$PUSH ESI,ECX;
EDI=ESI+SORTSIZE;
loop(ECX){
$PUSH ECX,ESI,EDI;
ECX=SORTSIZE;
ESI++;
EDI++;
$REPE $CMPSB;
$POP EDI,ESI;
IF(NOTCARRYFLAG){ // ¯à®¢¥à¨â ãá«®¢¨¥ ????????????à ¢¥¨¥ ¤¢ãå áâப
EAX=ESI;
EDX=EDI;
EDI=#Buffer16;
ECX=SORTSIZE/4; // 諨 ¬¥ìèãî áâபã
$REP $MOVSD;
ESI=EDX;
EDI=EAX;
ECX=SORTSIZE/4; // -¯®¬¥ï¥¬ ¬¥áâ ¬¨
$REP $MOVSD;
ESI=#Buffer16;
EDI=EDX;
ECX=SORTSIZE/4;
$REP $MOVSD;
ESI=EAX;
EDI=EDX;
}
EDI+=SORTSIZE;
$POP ECX;
}
$POP ECX,ESI;
ESI+=SORTSIZE;
}
}
// ®àâ¨à®¢ª ¢¢¥¤¥ëå áâப ¢ ¡ãä¥à¥ ptr § ª®ç¥
EDI=table;
ECX=26;
EAX=0;
$REP $STOSD; // ¡ã«¥ ¥ table
$POP ECX;
ESI=ptr;
EDI=ESI;
$PUSH ESI;
GOTO L42; // ®à¬ à㥬 â ¡«¨æã
loop(ECX){
$PUSH ESI;
IF(AH!=DSBYTE[ESI+1]){
EDI--;
AL=_END;
$STOSB // ⬥⨬ ª®¥æ â ¡«¨æë ¤«ï ¤ ®£® ᨬ¢®« ¢ AH
L42:
AH=DSBYTE[ESI+1];
EBX=0;
BL=AH;
BL-='A';
EBX=EBX<<2+table; //¤ «ìè¥ ¨¤¥â ªà å
DSDWORD[EBX]=EDI; // ¯¨áì 㪠§ â¥«ï ¢ table
}
$MOVSB // ¯®¬¨¬ ¯®à浪®¢ë© ®¬¥à áâப¨
ESI++; // யã᪠¯¥à¢®£® ᨬ¢®« - ® 㦥 ¨§¢¥áâ¥
do{
$LODSB;
$STOSB;
}while(AL!=0); // ®¯¨à㥬 áâப㠢 table
$POP ESI;
ESI+=SORTSIZE;
} // த®«¦¨¬ ¤«ï á«¥¤ãî饩 áâப¨
EDI--;
AL=_END;
$STOSB // table áä®à¬¨à®¢ . ⬥⨬ ª®¥æ
}
// ---- ஢¥àª æ¨äàã
dword IsNumber(dword ch)
{
IF(ch<'0')||(ch>'9')EAX=0;
ELSE EAX=1;
}
// ---- ⥨¥ ¢å®¤®£® ä ©« ¢ ¡ãä¥à
long LoadInputfile(dword infile)
dword fhandle, size;
{
fhandle=_lopen(infile,0);
IF(EAX==-1){
GetLastError();
return(-2);
}
EAX=GetFileSize(EAX,0);
IF(EAX==-1){
unabletoopen(infile);
_lclose(fhandle);
return(-1);
}
size=EAX;
input=LocalAlloc(0x40,EAX+2); // ¯®«¥ ï ã«ï¬¨
IF(EAX==NULL){
preerror("Not enough memory for input buffer");
_lclose(fhandle);
RETURN(-1);
}
EAX=_lread(fhandle,input,size);
IF(EAX!=size){
preerror("File Read error");
_lclose(fhandle);
RETURN(-1);
}
_lclose(fhandle);
inptr = input;
inptr2 = input;
endoffile = 0; // ç «¥ ä ©«
return(0);
}
// ---- ¡à ¡®âª ¬ ªà®á
Macros()
byte holdcha;
byte s[STRLEN],s2[STRLEN];
{
IF(makemapfile){
fprint(mapfile,#string);
fprint(mapfile,"\n");
}
holdcha=cha2;
$PUSH linenum2,inptr2,number,tok2,tok,input,inptr,currmod,
linenumber,endoffile,displaytokerrors;
lstrcpyA(#s,#string);
lstrcpyA(#s2,#string2);
input=#s;
inptr=input;
inptr2=input;
endoffile=0; // ç «¥ ä ©«
NextChar();
cha2=cha;
inptr2=inptr;
linenum2 = 1;
NextTok();
for(;;){
IF(tok==tk_eof)BREAK;
DoCommand();
}
lstrcpyA(#string,#s);
lstrcpyA(#string2,#s2);
$POP displaytokerrors,endoffile,linenumber,currmod,inptr,input,tok,tok2,
number,inptr2,linenum2;
cha2=holdcha;
}
// ---- ç¨á⪠ᯨ᪠«®ª «ìëå ¯¥à¥¬¥ëå
KillLocals()
dword ptr1,ptr2;
{
ptr2=locallist;
WHILE( ptr2 != NULL ){
ptr1=ptr2;
IF( DSDWORD[EAX+localtok]==tk_locallabel) // ஢¥àª ¥§ ªàëâë¥ ¬¥âª¨
localunresolved(EAX+localid);
EAX=ptr2;
ptr2=DSDWORD[EAX+localnext];
GlobalFree(ptr1);
}
locallist = NULL;
paramsize = 0;
localsize = 0;
}
// ---- ¢¥à襨¥ ⥫ ¯à®æ¥¤ãàë
LeaveProc()
{
IF(localsize > 0)Asm("leave");
ELSE{
IF(paramsize > 0)Asm("pop ebp");
}
IF( current_proc_type == cpt_far ){
IF(paramsize == 0)EAX="retf";
ELSE{
wsprintfA(#mapstr,"retf %d;",paramsize);
EAX=#mapstr;
}
}
ELSE{
IF(paramsize == 0)EAX="ret";
ELSE{
wsprintfA(#mapstr,"ret %d;",paramsize);
EAX=#mapstr;
}
}
Asm(EAX);
}
// ---- ⥨¥ ®ç¥à¥¤®£® ᨬ¢®« ¨§ ¢å®¤®£® ¡ãä¥à
NextChar()
{
ESI><inptr;
// EAX=0;
$LODSB
cha=AL;
inptr><ESI; // ¯®¬¨¬ ⥪ãéãî ¯®§ æ¨î ¢ ¡ãä¥à¥
IF(AL==0)||(AL==26)endoffile = 1;
IF(AL == 13){ // CR
linenumber++; // ¡ à㦥 ª®¥æ áâப¨
totallines++;
ShowSrcLine();
NextChar();
}
}
// ---- ®«ã票¥ ®ç¥à¥¤®£® token
void NextTok()
{
inptr = inptr2;
linenumber = linenum2;
cha = cha2;
displaytokerrors = 1;
TokScan(#tok,#type,#src,#post,#string,#number);
IF(linenumber!=linenum2){ // ®¢ ï áâப ?
IF(dbg){ // ॡã¥âáï ®â« ¤ª ?
$PUSH ESI
ESI=dbgs*dbg_size+dbginfo;
EAX=currmod;
$CMP EAX,DSDWORD[ESI+dbg_mod];
$JNE DIFF // ॡã¥âáï § ¯®¬¨âì ¨ä®à¬ æ¨î ¯® ®¢®© áâப¥
EAX=linenumber;
$CMP EAX,DSDWORD[ESI+dbg_line]
$JNE DIFF // ॡã¥âáï § ¯®¬¨âì ¨ä®à¬ æ¨î ¯® ®¢®© áâப¥
DSDWORD[ESI+dbg_line]=linenumber; // ¯®¬¨¬ ®¬¥à áâப¨
GOTO ALL;
DIFF:
dbgs++;
ESI+=dbg_size;
DSDWORD[ESI+dbg_mod]=currmod;
DSDWORD[ESI+dbg_line]=linenumber;
DSDWORD[ESI+dbg_loc]=outptr;
ALL:
$POP ESI
}
}
inptr2 = inptr;
linenum2 = linenumber;
cha2 = cha;
displaytokerrors = 0; // ¥§ ¢ë¢®¤ á®®¡é¥¨© ®¡ ®è¨¡ª å
TokScan(#tok2,#type2,#src2,#post2,#string2,#number2);
linenumber = linenum2;
}
// ---- «¥¤ãî騩 token § ªàëâë© ;
NextSemiNext ()
{
NextTok();
SemiNext();
}
// ---- ªàë¢ î騩 ; ¨ token § ¨¬
SemiNext ()
{
IF(tok != tk_semicolon)expected(';');
NextTok();
}
// ---- ¯¨áì ¡ ©â ¢ CODE
OP()
{
EDI><outptr;
$STOSB;
outptr><EDI;
}
// ---- ¯¨áì á«®¢ ¢ CODE
OUTWORD()
{
EDI><outptr;
$STOSW;
outptr><EDI;
}
// ---- ¯¨áì ¤¢®©®£® á«®¢ ¢ CODE
OUTDWORD()
{
EDI><outptr;
$STOSD;
outptr><EDI;
}
// ---- 뢮¤ à §¬¥à®¢ CODE&DATA
PrintMemsizes(dword handle)
{
wsprintfA(#mapstr,"Code:%u bytes,\tPost: %u bytes\n",outptr-output,postsize);
fprint(handle,#mapstr);
}
// ---- ¡à ¡®âª ¯à®æ¥¤ãà
Proc(dword proc_type)
{
current_proc_type = proc_type;
tok = tk_proc;
number = outptr-output+OptImageBase+OptBaseOfCode;
ESI=treeptr;
DSDWORD[ESI+rectok] = tok;
DSDWORD[ESI+recnumber] = number;
DSDWORD[ESI+recpost] = 0;
NextTok();
expecting(tk_openbracket);
IF(tok!=tk_closebracket)DeclareParams();
NextTok();
IF(paramsize > 0)Asm("push ebp;mov ebp,esp");
IF( tok != tk_openbrace )DeclareLocals();
DoBlock(); // ¡à ¡®âª ⥫ ¯à®æ¥¤ãàë { ... }
LeaveProc();
KillLocals();
}
// ---- ¯¨áì ¤¢®©®£® á«®¢ ¯® ¤à¥áã
SetDword(dword ptr, value)
{
EDI><ptr;
EAX><value;
$STOSD;
EDI><ptr;
EAX><value;
}
// ---- 뢮¤ áâப¨ ¨á室®£® ⥪áâ
ShowSrcLine()
byte str[STRLEN];
{
IF(list){
ESI><inptr;
$PUSH EDI,ESI;
ESI++;
EDI=#str;
for(;;){
$LODSB;
IF(AL==13)||(AL==0)BREAK;
$STOSB;
}
AL=0;
$STOSB
$POP ESI,EDI;
ESI><inptr;
IF(displaytokerrors){
fprint(mapfile,#str);
fprint(mapfile,"\n");
}
// AL=cha;
}
}
// ---- ®§¤ ¨¥ ä ©« áâ â¨á⨪¨
StartMapfile()
byte mapfilename[80];
{
wsprintfA(#mapfilename,"%s.MAP",#rawfilename);
mapfile=_lcreat(#mapfilename,0x1000);
IF(EAX==0){
errmsg();
WRITESTR("Unable to create map file");
WRITESTR(#mapfilename);
ExitProcess(e_cannotopenmapfile);
}
wsprintfA(#mapstr,"MAP FILE FOR %s.%s\n\n",#rawfilename,"EXE");
fprint(mapfile,#mapstr);
}
// ---- ¨æ¨ «¨§ æ¨ï ᯨ᪮¢ १¥à¢ëå á«®¢
TokInit()
{
InitList(#Mnemonics,#St_Mnemonics);
InitList(#Registers,#St_Registers);
InitList(#Directives,#St_Directives);
InitList(#Sizes,#St_Sizes);
}
// ---- ®§¢à é ¥â à §¬¥à ¤«ï § ¤ ®£® ⨯ ¤ ëå
dword TypeSize(dword vartype)
char holdstr[60];
{
IF(vartype==tk_void) RETURN(0);
IF(vartype==tk_char)||(vartype==tk_byte) RETURN(1);
IF(vartype==tk_short)||(vartype==tk_word) RETURN(2);
IF(vartype==tk_dword)||(vartype==tk_int) RETURN(4);
wsprintfA(#holdstr,"vartype=%d in TypeSize()",vartype);
internalerror(holdstr);
return(-1);
}
// ---- யã᪠¯à®¡¥«®¢ ¨ â ¡ã«ï権
WhiteSpaces()
{
for(;;){
AL=cha;
IF(AL!=32)&&(AL!=10)&&(AL!=9)BREAK;
NXT:
NextChar();
}
IF(AL == 13){ // CR
linenumber++; // ¡ à㦥 ª®¥æ áâப¨
totallines++;
ShowSrcLine();
GOTO NXT;
}
}
// ---- 뢮¤ stdout
WRITESTR()
{
fprint(stdout,EAX);
}
//===== ¡à ¡®âª ®è¨¡®ª
// ----
datatype_expected()
{
preerror("byte, word, short, char, dword or int expected");
}
// ----
errmsg()
{
WRITESTR("\nERROR> ");
}
// ----
expected(dword ch)
byte hstr[80];
{
wsprintfA(#hstr,"'%c' expected",ch);
preerror(#hstr);
}
// ----
expectederror(dword str)
byte hstr[80];
{
IF(displaytokerrors){
wsprintfA(#hstr,"'%s' expected",str);
preerror(#hstr);
}
}
// ---- ஢¥àª ⥪ã饣® token § ¤ ë© â¨¯
expecting(dword want)
{
if(want!=tok){
IF(want==tk_closebracket) expected(')');
else IF(want==tk_openbracket) expected('(');
ELSE IF(want==tk_semicolon) expected(';');
ELSE IF(want==tk_colon) expected(':');
ELSE IF(want==tk_openblock) expected('[');
ELSE IF(want==tk_closeblock) expected(']');
ELSE IF(want==tk_openbrace) expected('{');
ELSE IF(want==tk_closebrace) expected('}');
ELSE IF(want==tk_comma) expected(',');
ELSE preerror("expecting a different token");
}
NextTok();
}
// ----
/*idalreadydefined()
byte holdstr[80];
{
wsprintfA(#holdstr,"identifier %s already defined",#string);
preerror(#holdstr);
NextTok();
} */
// ----
idexpected()
{
preerror("undefined 'identifier' expected");
}
// ---- ãâà¥ïï ®è¨¡ª ª®¬¯¨«ïâ®à
internalerror(dword str)
{
error++;
wsprintfA(#mapstr,"%s(%d)#%d> *** SERIOUS COMPILER INTERNAL ERROR ***\n>%s.\n",
#currentfilename,linenumber,error,str);
WRITESTR(#mapstr);
wsprintfA(#mapstr,"STRING:%s\n",#string);
WRITESTR(#mapstr);
wsprintfA(#mapstr,"TOK:%d\tPOST:%d\tnumber:%ld\n",tok,post,number);
WRITESTR(#mapstr);
wsprintfA(#mapstr,"STRING2:%s\n",#string2);
WRITESTR(#mapstr);
wsprintfA(#mapstr,"TOK2:%d\tPOST2:%d\tnumber2:%ld\n",tok2,post2,number2);
WRITESTR(#mapstr);
WRITESTR("Oh no.\n");
IF(makemapfile)CloseHandle(mapfile);
ExitProcess(e_internalerror);
}
// ----
localunresolved(dword str)
byte holdstr[80];
{
wsprintfA(#holdstr,"local jump label '%s' unresolved",str);
preerror(#holdstr);
}
// ----
maxwordpostserror ()
{
preerror("maximum number of word post location references exceeded");
}
// ----
/*notyet()
{
preerror("specified syntax not handled in this version!!!");
} */
// ----
numexpected()
{
preerror("'number' expected");
}
// ----
operatorexpected ()
{
preerror("operator identifier expected");
}
// ----
outofmemory()
{
preerror("Compiler out of memory");
IF( makemapfile )CloseHandle(mapfile);
ExitProcess(e_outofmemory);
}
// ----
outofmemory2()
{
errmsg();
WRITESTR("Not enough memory for the compiler's buffers.\n");
ExitProcess(e_outofmemory );
}
// ---- 訡ª ¢ ⥪ã饩 áâப¥: ¯®ª § ®¬¥à áâப¨ ¨ ¨¬¥¨ ä ©«
preerror(dword str)
{
IF(error < maxerrors){
error++;
wsprintfA(#mapstr,"%s (%d)#%d> %s.\n",#currentfilename,linenumber,error,str);
WRITESTR(#mapstr);
IF(makemapfile)fprint(mapfile,#mapstr);
}
ELSE toomanyerrors();
}
// ----
/*regnameerror()
{
preerror("register name cannot be used as an identifier");
NextTok();
} */
// ---- ॡã¥âáï áâப
stringexpected()
{
preerror("'string' expected");
}
// ---- ¥¤®¯ãáâ¨¬ë© ®¯¥à ¤ ¤«ï swap
swaperror ()
{
preerror("invalid or incompatable swap item");
}
// ---- ।¥«ì®¥ ç¨á«® ®è¨¡®ª - ¢ë室
toomanyerrors()
{
IF( makemapfile )CloseHandle(mapfile);
ExitProcess( e_toomanyerrors );
}
// ----
unabletoopen(dword str)
byte hstr[80];
{
wsprintfA(#hstr,"unable to open file '%s'",str);
preerror(#hstr);
}
// ----
undefinederror()
byte holdstr[80];
{
wsprintfA(#holdstr,"'%s' undefined",#string);
preerror(holdstr);
}
// ----
unexpectedeof()
{
preerror("unexpected END OF FILE");
}
// ----
warning(dword str)
{
wsprintfA(#mapstr,"%s (%d)Warning> %s.\n",#currentfilename,linenumber,str);
WRITESTR(#mapstr);
IF(makemapfile)fprint(mapfile,#mapstr);
}
/*
void TestProc()
char buf[20];
{
$pushad
wsprintfA(#buf,"%08X\n",SSDWORD[EBP+4]);
WRITESTR(#buf);
$popad
} */