#include"mbasic.h"

int IS_FASM_SYNTAX=1;
int EQU_VARS=0;
int CLEAR_POOL=0;
int DOS_APP=0;
int IS_LIBRARY=0;

void parse_options(int argc,char * argv[])
{
 int i;
 if(argc==3) return;
 for(i=3;i<argc;i++)
 {
  if(!strncmp(argv[i],"-fnasm-syntax",strlen(argv[i])))
  {
   IS_FASM_SYNTAX=0;
  } else if(!strncmp(argv[i],"-fequ-vars",strlen(argv[i])))
  {
   EQU_VARS=1;
  } else if(!strncmp(argv[i],"-fclear-pool",strlen(argv[i])))
  {
   CLEAR_POOL=1;
  } else if(!strncmp(argv[i],"-fdos-app",strlen(argv[i])))
  {
   DOS_APP=1;
  } else if(!strncmp(argv[i],"-flibrary",strlen(argv[i])))
  {
   IS_LIBRARY=1;
  } else Error("Unknown option: '%s'\n",argv[i]);
 }
}

void emit_clear_pool(void)
{
 _emit("INTERNAL_clear_pool:\n");
 emit("push ecx\n");
 emit("push eax\n");
 emit("push edi\n");
 emit("xor eax,eax\n");
 emit("mov ecx,dword [VAR_POOL_SIZE]\n");
 emit("mov edi,VAR_POOL_BEGIN\n");
 emit("cld\n");
 emit("rep stosb\n");
 emit("pop edi\n");
 emit("pop eax\n");
 emit("pop ecx\n");
 emit("ret\n");
}

int main(int argc,char * argv[])
{
 if(argc<3)
 
 {
  fprintf(stderr,"Usage:\n");
  fprintf(stderr,"%s infile.bas outfile.asm [options]\n",argv[0]);
  fprintf(stderr,"-fnasm-syntax - Use nasm syntax (FASM is default)\n");
  fprintf(stderr,"-fequ-vars - Make variables as EQUs\n");
  fprintf(stderr,"-fclear-pool - Clear data pool when initializing\n");
  fprintf(stderr,"-fdos-app - Make DOS application\n");
  fprintf(stderr,"-flibrary - Generate library (do not use yet)\n");
  return 1;
 }
 parse_options(argc,argv);
 io_load_program(argv[1]);
 io_init_output();
 InitParser();
 InitLabel();
 InitVariables();
 InitStrings();
 InitIncludes();
 InitArrays();
 if(!IS_LIBRARY)
 {
  _emit("; This file was generated by MenuetBASIC Compiler\n");
  _emit("; Author: Jarek Pelczar\n");
  _emit("; E-mail: jarekp3@wp.pl\n");
  _emit("; \n");
  _emit("; Input file: %s\n",argv[1]);
  _emit("; Output file: %s\n",argv[2]);
  if(argc>3)
  {
   int i;
   _emit("; Additional flags: ");
   for(i=3;i<argc;i++) _emit("%s ",argv[i]);
   _emit("\n");
  }
  if(IS_FASM_SYNTAX)
  {
   _emit("org 0\n");
   if(!DOS_APP) _emit("use32\n");
  } else {
   _emit("[ORG 0]\n");
   if(!DOS_APP) _emit("[BITS 32]\n");
  }
  if(!DOS_APP)
  {
   _emit("App_Header:\n");
   emit("db 'MENUET01'\n");
   emit("dd 1\n");
   emit("dd APP_START\n");
   emit("dd I_END\n");
   emit("dd 0x100000\n");
   emit("dd 0x09FFFF\n");
   emit("dd 0\n");
   emit("dd 0\n");
   _emit("APP_START:\n");
   _emit("mov esp,0x9FFFF\n");
  } else {
   _emit("App_Header:\n");
   emit("mov ax,cs\n");
   emit("mov ds,ax\n");
   emit("mov es,ax\n");
   emit("mov ss,ax\n");
   emit("mov esp,app_stack\n");
  }
  if(CLEAR_POOL) emit("call INTERNAL_clear_pool\n");
 }
 Block(); 
 if(!IS_LIBRARY)
 {
  _emit("INTERNAL_app_exit:\n");
  if(!DOS_APP)
  {
   emit("mov eax,-1\n");
   emit("int 0x40\n");
   emit("cli ; It MUST fail if exit didn't work (assasination :)\n");
  } else {
   emit("mov eax,0x4C00 ; Dos exit \n");
   emit("int 0x21\n");
  }
  _emit("VAR_POOL_SIZE dd VAR_POOL_END-VAR_POOL_BEGIN\n");
  if(CLEAR_POOL) emit_clear_pool();
  _emit("I_END:\n");
  if(DOS_APP)
  {
   _emit("times 1024 db 0\n");
   _emit("app_stack:\n");
  }
 }
 EmitIncludes();
 EmitStrings();
 EmitVariables();
 EmitArrays();
 io_unload_program();
 io_finalize_output(argv[2]);
 return 0;
}
