//===== ”« £¨ ª®¬¯¨«ï樨
#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
} */