#pragma warning(disable:4786) #include "libs.h" #include #include "../config/config.h" #include "../stdutil/stdutil.h" #include #include #include #include #include #include #include #include using namespace std; #include "../LinkerLib/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 "../Runtime/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::iterator it; map &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 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; } 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 *v_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; v_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 + "\\debugger.dll").c_str()); if (dbgHandle) { typedef Debugger *(_cdecl*GetDebugger)(Module*, Environ*); GetDebugger gd = (GetDebugger)GetProcAddress(dbgHandle, "debuggerGetDebugger"); if (gd) debugger = gd(module, v_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 v_environ; closeLibs(); return 0; }