kolibrios-gitea/programs/develop/c--/trunk/32.c--
Yogev Ezra 02b76505a6 Add sources of "C--"'like compiler written in C--.
git-svn-id: svn://kolibrios.org@1846 a494cfbc-eb01-0410-851d-a64ba20cac60
2011-02-05 16:39:49 +00:00

1442 lines
30 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//===== ”« £¨ ª®¬¯¨«ï樨
#pragma option w32c
#stack 0x8000
#argc TRUE
//===== <20>®¤ª«îç ¥¬ë¥ ¬®¤ã«¨
#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");
// <20> §¡®à ª®¬¬ ­¤­®© áâப¨: 32.exe <SourceFileName> [/map] [/debug]
pari=@PARAMCOUNT();
for(count=1;count<pari;count++){ //®¡à ¡®âª  ª®¬ ­¤­®© áâப¨
cmdline=@PARAMSTR(count);
CharUpperA(EAX);
CharToOemA(cmdline,cmdline); // <20>८¡à §ã¥¬ ¢ ‡€ƒ‹ ¢ 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();
}
// ---- <20>।¢ à¨â¥«ì­ ï ®¡à ¡®âª  ä ©« 
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){ // <20>®ª  ­¥ ª®­ç¨âáï ¢å®¤­®© ¡ãä¥à
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; // <20>  ­ ç «® ¡ãä¥à 
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) { // <20>¥à¢ë© ¢ë§®¢ 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);// <20>â® à §¬¥à ®¯¥à ­¤ ?
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; // <20> áç¥â ®â­®á¨â¥«ì­®£® ᬥ饭¨ï EAX-=addvalue;
EAX+=output;
SetDword(EBX,EAX-4);
}
ELSE IF(EAX==POST_LOC){
EAX=ECX; EAX-=OptImageBase;
EAX-=OptBaseOfCode; EAX-=EBX; // <20> áç¥â ®â­®á¨â¥«ì­®£® ᬥ饭¨ï 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++;
}
}
// ---- <20>ëáâàë© ¯®¨áª ¯® â ¡«¨æ¥
// 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]; // <20>஢¥à¨¬ ¯¥à¢ë© ᨬ¢®« ¢ ident
BL-='A';
$JC HET // <20>¥ ¡ãª¢ 
$CMP BL,'Z'-'A';
$JA HET // ¨ ­¥ 'A'...'Z'
EAX=0;
EBX=EBX<<2+table;
EDI=DSDWORD[EBX]; // ‚§ïâì  ¤à¥á § ¯¨á¨ ¨§ table
$OR EDI,EDI;
$JE HET // <20>¥â § ¯¨á¨ ¤«ï â ª®£® ident...
TRY0:
AH=DSBYTE[EDI];
EDI++; // <20>®¬¥à § ¯¨á¨ ¨§ 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 // <20>஢¥à¨¬ á«¥¤ãîéãî § ¯¨áì
$CMP AL,'/';
$JE NEAR TRY1 // <20>஢¥à¨¬ 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));
}
// ---- ‚뤥«¥­¨¥ ¯ ¬ï⨠¤«ï ª®¬¯¨«ï樨. <20>ਠ­¥ã¤ ç¥ ¢ë室 ¨§ ª®¬¯¨«ïâ®à 
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; // <20> è«¨ ¬¥­ìèãî áâபã
$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++; // <20>யã᪠¯¥à¢®£® ᨬ¢®«  - ®­ 㦥 ¨§¢¥á⥭
do{
$LODSB;
$STOSB;
}while(AL!=0); // Š®¯¨à㥬 áâப㠢 table
$POP ESI;
ESI+=SORTSIZE;
} // <20>த®«¦¨¬ ¤«ï á«¥¤ãî饩 áâப¨
EDI--;
AL=_END;
$STOSB // table áä®à¬¨à®¢ ­ . Žâ¬¥â¨¬ ª®­¥æ
}
// ---- <20>஢¥àª  ­  æ¨äàã
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; // <20>  ­ ç «¥ ä ©« 
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; // <20>  ­ ç «¥ ä ©« 
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) // <20>஢¥àª  ­  ­¥§ ªàëâë¥ ¬¥âª¨
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();
}
}
// ---- <20>®«ã祭¨¥ ®ç¥à¥¤­®£® token
void NextTok()
{
inptr = inptr2;
linenumber = linenum2;
cha = cha2;
displaytokerrors = 1;
TokScan(#tok,#type,#src,#post,#string,#number);
IF(linenumber!=linenum2){ // <20>®¢ ï áâப ?
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; // <20>¥§ ¢ë¢®¤  á®®¡é¥­¨© ®¡ ®è¨¡ª å
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);
}
// ---- <20>யã᪠¯à®¡¥«®¢ ¨ â ¡ã«ï権
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);
}
}
// ---- <20>஢¥àª  ⥪ã饣® 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");
}
// ---- <20>¥¤®¯ãáâ¨¬ë© ®¯¥à ­¤ ¤«ï swap
swaperror ()
{
preerror("invalid or incompatable swap item");
}
// ---- <20>।¥«ì­®¥ ç¨á«® ®è¨¡®ª - ¢ë室
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
} */