blitz3d/blitz/main.cpp

298 lines
6.8 KiB
C++

#pragma warning(disable:4786)
#include "libs.h"
#include <iostream>
#include "../config/config.h"
#include "../stdutil/stdutil.h"
#include <set>
#include <map>
#include <list>
#include <string>
#include <vector>
#include <fstream>
#include <iostream>
#include <iomanip>
using namespace std;
#include "../linker/linker.h"
#include "../compiler/environ.h"
#include "../compiler/parser.h"
#include "../compiler/assem_x86/assem_x86.h"
#include "../compiler/codegen_x86/codegen_x86.h"
#include "../bbruntime_dll/bbruntime_dll.h"
static void showInfo(){
const int major=(VERSION&0xffff)/100,minor=(VERSION&0xffff)%100;
cout<<"BlitzCC V"<<major<<"."<<minor<<endl;
cout<<"(C)opyright 2000-2003 Blitz Research Ltd"<<endl;
}
static void showUsage(){
cout<<"Usage: blitzcc [-h|-q|+q|-c|-d|-k|+k|-v|-o exefile] [sourcefile.bb]"<<endl;
}
static void showHelp(){
showUsage();
cout<<"-h : show this help"<<endl;
cout<<"-q : quiet mode"<<endl;
cout<<"+q : very quiet mode"<<endl;
cout<<"-c : compile only"<<endl;
cout<<"-d : debug compile"<<endl;
cout<<"-k : dump keywords"<<endl;
cout<<"+k : dump keywords and syntax"<<endl;
cout<<"-v : version info"<<endl;
cout<<"-o exefile : generate executable"<<endl;
}
static void err( const string &t ){
cout<<t<<endl;
exit(-1);
}
static void usageErr(){
err( "Usage error" );
}
static string quickHelp( const string &kw ){
Environ *e=runtimeEnviron;
Decl *d=e->funcDecls->findDecl( tolower( kw ) );
if( !d || d->type->funcType()==0 ) return "No quick help available for "+kw;
string t=kw;
FuncType *f=d->type->funcType();
if( f->returnType==Type::float_type ) t+='#';
else if( f->returnType==Type::string_type ) t+='$';
t+=" ";
if( f->returnType!=Type::void_type ) t+="( ";
for( int k=0;k<f->params->size();++k ){
string s;
if( k ) s+=',';
Decl *p=f->params->decls[k];s+=p->name;
if( p->type==Type::float_type ) s+='#';
else if( p->type==Type::string_type ) s+='$';
else if( p->type==Type::void_type ) s+='*';
if( p->defType ) s='['+s+']';
t+=s;
}
if( f->returnType!=Type::void_type ){
t+=f->params->size() ? " )" : ")";
}
return t;
}
static void dumpKeys( bool lang,bool mod,bool help ){
if( lang ){
map<string,int>::iterator it;
map<string,int> &keywords=Toker::getKeywords();
for( it=keywords.begin();it!=keywords.end();++it ){
if( it->first.find(' ')!=string::npos ) continue;
cout<<it->first<<endl;
}
}
if( !mod ) return;
for( int k=0;k<keyWords.size();++k ){
string t=keyWords[k];
if( t[0]=='_' ) continue;
if( !isalpha( t[0] ) ) t=t.substr( 1 );
for( int n=0;n<t.size();++n ){
if( !isalnum(t[n]) && t[n]!='_' ){
t=t.substr( 0,n );
break;
}
}
if( help ) t=quickHelp(t);
cout<<t<<endl;
}
}
static string verstr( int ver ){
return itoa((ver&65535)/100)+"."+itoa((ver&65535)%100);
}
static void versInfo(){
cout<<"Compiler version:"<<verstr(bcc_ver)<<endl;
cout<<"Runtime version:"<<verstr(run_ver)<<endl;
cout<<"Debugger version:"<<verstr(dbg_ver)<<endl;
cout<<"Linker version:"<<verstr(lnk_ver)<<endl;
}
static void demoError(){
cout<<"Compiler can not be used standalone in demo version."<<endl;
exit(0);
}
int _cdecl main( int argc,char *argv[] ){
string in_file,out_file,args;
bool debug=false,quiet=false,veryquiet=false,compileonly=false;
bool dumpkeys=false,dumphelp=false,showhelp=false,dumpasm=false;
bool versinfo=false;
for( int k=1;k<argc;++k ){
string t=argv[k];
t=tolower(t);
if( t=="-h" ){
showhelp=true;
}else if( t=="-a" ){
dumpasm=true;
}else if( t=="-q" ){
quiet=true;
}else if( t=="+q" ){
quiet=veryquiet=true;
}else if( t=="-c" ){
compileonly=true;
}else if( t=="-d" ){
debug=true;
}else if( t=="-k" ){
dumpkeys=true;
}else if( t=="+k" ){
dumpkeys=dumphelp=true;
}else if( t=="-v" ){
versinfo=true;
}else if( t=="-o" ){
if( out_file.size() || k==argc-1 ) usageErr();
out_file=argv[++k];
}else{
if( in_file.size() || t[0]=='-' || t[0]=='+' ) usageErr();
in_file=argv[k];
for( ++k;k<argc;++k ){
string t=argv[k];
if( t.find(' ')!=string::npos ) t='\"'+t+'\"';
if( args.size() ) args+=' ';
args+=t;
}
}
}
if( out_file.size() && !in_file.size() ) usageErr();
if( const char *er=openLibs() ) err( er );
if( const char *er=linkLibs() ) err( er );
if( showhelp ) showHelp();
if( dumpkeys ) dumpKeys( true,true,dumphelp );
if( versinfo ) versInfo();
if( !in_file.size() ) return 0;
#ifdef DEMO
if( !getenv( "blitzide" ) ) demoError();
#endif
if( in_file[0]=='\"' ){
if( in_file.size()<3 || in_file[in_file.size()-1]!='\"' ) usageErr();
in_file=in_file.substr( 1,in_file.size()-2 );
}
ifstream in( in_file.c_str() );
if( !in ) err( "Unable to open input file" );
if( !quiet ){
showInfo();
cout<<"Compiling \""<<in_file<<"\""<<endl;
}
int n=in_file.rfind( '/' );
if( n==string::npos ) n=in_file.rfind( '\\' );
if( n!=string::npos ){
if( !n || in_file[n-1]==':' ) ++n;
SetCurrentDirectory( in_file.substr(0,n).c_str() );
}
ProgNode *prog=0;
Environ *environ=0;
Module *module=0;
try{
//parse
if( !veryquiet ) cout<<"Parsing..."<<endl;
Toker toker( in );
Parser parser( toker );
prog=parser.parse( in_file );
//semant
if( !veryquiet ) cout<<"Generating..."<<endl;
environ=prog->semant( runtimeEnviron );
//translate
if( !veryquiet ) cout<<"Translating..."<<endl;
qstreambuf qbuf;
iostream asmcode( &qbuf );
Codegen_x86 codegen( asmcode,debug );
prog->translate( &codegen,userFuncs );
if( dumpasm ){
cout<<endl<<string( qbuf.data(),qbuf.size() )<<endl;
}
//assemble
if( !veryquiet ) cout<<"Assembling..."<<endl;
module=linkerLib->createModule();
Assem_x86 assem( asmcode,module );
assem.assemble();
}catch( Ex &x ){
string file='\"'+x.file+'\"';
int row=((x.pos>>16)&65535)+1,col=(x.pos&65535)+1;
cout<<file<<":"<<row<<":"<<col<<":"<<row<<":"<<col<<":"<<x.ex<<endl;
exit(-1);
}
delete prog;
if( out_file.size() ){
if( !veryquiet ) cout<<"Creating executable \""<<out_file<<"\"..."<<endl;
if( !module->createExe( out_file.c_str(),(home+"/bin/runtime.dll").c_str() ) ){
err( "Error creating executable" );
}
}else if( !compileonly ){
void *entry=module->link( runtimeModule );
if( !entry ) return 0;
HMODULE dbgHandle=0;
Debugger *debugger=0;
if( debug ){
dbgHandle=LoadLibrary( (home+"/bin/debugger.dll").c_str() );
if( dbgHandle ){
typedef Debugger *(_cdecl*GetDebugger)( Module*,Environ* );
GetDebugger gd=(GetDebugger)GetProcAddress( dbgHandle,"debuggerGetDebugger" );
if( gd ) debugger=gd( module,environ );
}
if( !debugger ) err( "Error launching debugger" );
}
if( !veryquiet ) cout<<"Executing..."<<endl;
runtimeLib->execute( (void(*)())entry,args.c_str(),debugger );
if( dbgHandle ) FreeLibrary( dbgHandle );
}
delete module;
delete environ;
closeLibs();
return 0;
}