Files
BlitzNext/blitz/libs.cpp
T

318 lines
6.8 KiB
C++
Raw Normal View History

2014-01-31 08:23:00 +13:00
#include "libs.h"
#include <windows.h>
int bcc_ver;
int lnk_ver;
int run_ver;
int dbg_ver;
string home;
Linker *linkerLib;
Runtime *runtimeLib;
Module *runtimeModule;
Environ *runtimeEnviron;
vector<string> keyWords;
vector<UserFunc> userFuncs;
static HMODULE linkerHMOD, runtimeHMOD;
2014-01-31 08:23:00 +13:00
2017-04-09 05:36:37 +02:00
static Type *bbtypeof(int c) {
switch (c) {
case '%':return Type::int_type;
case '#':return Type::float_type;
case '$':return Type::string_type;
2014-01-31 08:23:00 +13:00
}
return Type::void_type;
}
static int curr;
static string text;
2017-04-09 05:36:37 +02:00
static int bbnext(istream &in) {
2014-01-31 08:23:00 +13:00
text = "";
2014-01-31 08:23:00 +13:00
int t = 0;
2014-01-31 08:23:00 +13:00
for (;;) {
while (isspace(in.peek())) in.get();
if (in.eof()) return curr = 0;
t = in.get(); if (t != ';') break;
while (!in.eof() && in.get() != '\n') {}
2014-01-31 08:23:00 +13:00
}
if (isalpha(t)) {
text += (char)t;
while (isalnum(in.peek()) || in.peek() == '_') text += (char)in.get();
return curr = -1;
2014-01-31 08:23:00 +13:00
}
if (t == '\"') {
while (in.peek() != '\"') text = text + (char)in.get();
2014-01-31 08:23:00 +13:00
in.get();
return curr = -2;
2014-01-31 08:23:00 +13:00
}
return curr = t;
2014-01-31 08:23:00 +13:00
}
static const char *linkRuntime() {
2014-01-31 08:23:00 +13:00
while (const char *sym = runtimeLib->nextSym()) {
2014-01-31 08:23:00 +13:00
string s(sym);
2014-01-31 08:23:00 +13:00
int pc = runtimeLib->symValue(sym);
2014-01-31 08:23:00 +13:00
//internal?
if (s[0] == '_') {
runtimeModule->addSymbol(("_" + s).c_str(), pc);
2014-01-31 08:23:00 +13:00
continue;
}
bool cfunc = false;
2014-01-31 08:23:00 +13:00
if (s[0] == '!') {
cfunc = true;
s = s.substr(1);
2014-01-31 08:23:00 +13:00
}
keyWords.push_back(s);
2014-01-31 08:23:00 +13:00
//global!
2017-04-09 05:36:37 +02:00
size_t start = 0, end, k;
Type *t = Type::void_type;
2017-04-09 05:36:37 +02:00
if (!isalpha(s[0])) { start = 1; t = bbtypeof(s[0]); }
for (k = 1; k < s.size(); ++k, end = k) {
if (!isalnum(s[k]) && s[k] != '_') break;
2014-01-31 08:23:00 +13:00
}
2016-10-03 17:11:15 +02:00
DeclSeq *params = new DeclSeq();
string n = s.substr(start, end - start);
while (k < s.size()) {
2017-04-09 05:36:37 +02:00
Type *t = bbtypeof(s[k++]);
int from = k;
for (; isalnum(s[k]) || s[k] == '_'; ++k) {}
string str = s.substr(from, k - from);
ConstType *defType = 0;
if (s[k] == '=') {
int from = ++k;
if (s[k] == '\"') {
for (++k; s[k] != '\"'; ++k) {}
string t = s.substr(from + 1, k - from - 1);
2016-10-03 17:11:15 +02:00
defType = new ConstType(t); ++k;
} else {
if (s[k] == '-') ++k;
for (; isdigit(s[k]); ++k) {}
if (t == Type::int_type) {
int n = atoi(s.substr(from, k - from));
2016-10-03 17:11:15 +02:00
defType = new ConstType(n);
} else {
2017-04-09 05:36:37 +02:00
float n = (float)atof(s.substr(from, k - from));
2016-10-03 17:11:15 +02:00
defType = new ConstType(n);
2014-01-31 08:23:00 +13:00
}
}
}
Decl *d = params->insertDecl(str, t, DECL_PARAM, defType);
2014-01-31 08:23:00 +13:00
}
2016-10-03 17:11:15 +02:00
FuncType *f = new FuncType(t, params, false, cfunc);
n = tolower(n);
runtimeEnviron->funcDecls->insertDecl(n, f, DECL_FUNC);
runtimeModule->addSymbol(("_f" + n).c_str(), pc);
2014-01-31 08:23:00 +13:00
}
return 0;
}
static set<string> _ulibkws;
static const char *loadUserLib(const string &userlib) {
2014-01-31 08:23:00 +13:00
string t = home + "/userlibs/" + userlib;
2014-01-31 08:23:00 +13:00
string lib = "";
2014-01-31 08:23:00 +13:00
ifstream in(t.c_str());
2017-04-09 05:36:37 +02:00
bbnext(in);
while (curr) {
if (curr == '.') {
2014-01-31 08:23:00 +13:00
2017-04-09 05:36:37 +02:00
if (bbnext(in) != -1) return "expecting identifier after '.'";
2014-01-31 08:23:00 +13:00
if (text == "lib") {
2017-04-09 05:36:37 +02:00
if (bbnext(in) != -2) return "expecting string after lib directive";
lib = text;
2014-01-31 08:23:00 +13:00
} else {
2014-01-31 08:23:00 +13:00
return "unknown decl directive";
}
2017-04-09 05:36:37 +02:00
bbnext(in);
2014-01-31 08:23:00 +13:00
} else if (curr == -1) {
2014-01-31 08:23:00 +13:00
if (!lib.size()) return "function decl without lib directive";
2014-01-31 08:23:00 +13:00
string id = text;
string lower_id = tolower(id);
2014-01-31 08:23:00 +13:00
if (_ulibkws.count(lower_id)) return "duplicate identifier";
_ulibkws.insert(lower_id);
2014-01-31 08:23:00 +13:00
Type *ty = 0;
2017-04-09 05:36:37 +02:00
switch (bbnext(in)) {
case '%':ty = Type::int_type; break;
case '#':ty = Type::float_type; break;
case '$':ty = Type::string_type; break;
2014-01-31 08:23:00 +13:00
}
2017-04-09 05:36:37 +02:00
if (ty) bbnext(in);
else ty = Type::void_type;
2014-01-31 08:23:00 +13:00
2016-10-03 17:11:15 +02:00
DeclSeq *params = new DeclSeq();
2014-01-31 08:23:00 +13:00
if (curr != '(') return "expecting '(' after function identifier";
2017-04-09 05:36:37 +02:00
bbnext(in);
if (curr != ')') {
for (;;) {
if (curr != -1) break;
string arg = text;
Type *ty = 0;
2017-04-09 05:36:37 +02:00
switch (bbnext(in)) {
case '%':ty = Type::int_type; break;
case '#':ty = Type::float_type; break;
case '$':ty = Type::string_type; break;
case '*':ty = Type::null_type; break;
2014-01-31 08:23:00 +13:00
}
2017-04-09 05:36:37 +02:00
if (ty) bbnext(in);
else ty = Type::int_type;
2014-01-31 08:23:00 +13:00
ConstType *defType = 0;
2014-01-31 08:23:00 +13:00
Decl *d = params->insertDecl(arg, ty, DECL_PARAM, defType);
2014-01-31 08:23:00 +13:00
if (curr != ',') break;
2017-04-09 05:36:37 +02:00
bbnext(in);
2014-01-31 08:23:00 +13:00
}
}
if (curr != ')') return "expecting ')' after function decl";
2014-01-31 08:23:00 +13:00
keyWords.push_back(id);
2014-01-31 08:23:00 +13:00
2016-10-03 17:11:15 +02:00
FuncType *fn = new FuncType(ty, params, true, true);
2014-01-31 08:23:00 +13:00
runtimeEnviron->funcDecls->insertDecl(lower_id, fn, DECL_FUNC);
2014-01-31 08:23:00 +13:00
2017-04-09 05:36:37 +02:00
if (bbnext(in) == ':') { //real name?
bbnext(in);
if (curr != -1 && curr != -2) return "expecting identifier or string after alias";
id = text;
2017-04-09 05:36:37 +02:00
bbnext(in);
2014-01-31 08:23:00 +13:00
}
userFuncs.push_back(UserFunc(lower_id, id, lib));
2014-01-31 08:23:00 +13:00
}
}
return 0;
}
static const char *linkUserLibs() {
2014-01-31 08:23:00 +13:00
_ulibkws.clear();
WIN32_FIND_DATA fd;
HANDLE h = FindFirstFile((home + "/userlibs/*.decls").c_str(), &fd);
2014-01-31 08:23:00 +13:00
if (h == INVALID_HANDLE_VALUE) return 0;
2014-01-31 08:23:00 +13:00
const char *err = 0;
2014-01-31 08:23:00 +13:00
do {
if (err = loadUserLib(fd.cFileName)) {
2014-01-31 08:23:00 +13:00
static char buf[64];
sprintf(buf, "Error in userlib '%s' - %s", fd.cFileName, err);
err = buf; break;
2014-01-31 08:23:00 +13:00
}
} while (FindNextFile(h, &fd));
2014-01-31 08:23:00 +13:00
FindClose(h);
2014-01-31 08:23:00 +13:00
_ulibkws.clear();
return err;
}
const char *openLibs() {
/*char *p = getenv("blitzpath");
if (!p) return "Can't find blitzpath environment variable";
*/
char* buf = new char[MAX_PATH];
GetModuleFileName(NULL, buf, MAX_PATH);
home = string(buf);
delete buf;
string::size_type pos = home.find_last_of("\\/");
home = home.substr(0, pos);
2014-01-31 08:23:00 +13:00
linkerHMOD = LoadLibrary((home + "\\linker.dll").c_str());
if (!linkerHMOD) return "Unable to open linker.dll";
2014-01-31 08:23:00 +13:00
typedef Linker *(_cdecl*GetLinker)();
GetLinker gl = (GetLinker)GetProcAddress(linkerHMOD, "linkerGetLinker");
if (!gl) return "Error in linker.dll";
linkerLib = gl();
2014-01-31 08:23:00 +13:00
runtimeHMOD = LoadLibrary((home + "\\runtime.dll").c_str());
if (!runtimeHMOD) return "Unable to open runtime.dll";
2014-01-31 08:23:00 +13:00
typedef Runtime *(_cdecl*GetRuntime)();
GetRuntime gr = (GetRuntime)GetProcAddress(runtimeHMOD, "runtimeGetRuntime");
if (!gr) return "Error in runtime.dll";
runtimeLib = gr();
2014-01-31 08:23:00 +13:00
bcc_ver = VERSION;
lnk_ver = linkerLib->version();
run_ver = runtimeLib->version();
2014-01-31 08:23:00 +13:00
if ((lnk_ver >> 16) != (bcc_ver >> 16) ||
(run_ver >> 16) != (bcc_ver >> 16) ||
(lnk_ver >> 16) != (bcc_ver >> 16)) return "Library version error";
2014-01-31 08:23:00 +13:00
runtimeLib->startup(GetModuleHandle(0));
2014-01-31 08:23:00 +13:00
runtimeModule = linkerLib->createModule();
2016-10-03 17:11:15 +02:00
runtimeEnviron = new Environ("", Type::int_type, 0, 0);
2014-01-31 08:23:00 +13:00
keyWords.clear();
userFuncs.clear();
return 0;
}
const char *linkLibs() {
2014-01-31 08:23:00 +13:00
if (const char *p = linkRuntime()) return p;
2014-01-31 08:23:00 +13:00
if (const char *p = linkUserLibs()) return p;
2014-01-31 08:23:00 +13:00
return 0;
}
void closeLibs() {
2014-01-31 08:23:00 +13:00
delete runtimeEnviron;
if (linkerLib) linkerLib->deleteModule(runtimeModule);
if (runtimeLib) runtimeLib->shutdown();
if (runtimeHMOD) FreeLibrary(runtimeHMOD);
if (linkerHMOD) FreeLibrary(linkerHMOD);
runtimeEnviron = 0;
linkerLib = 0;
runtimeLib = 0;
runtimeHMOD = 0;
linkerHMOD = 0;
2014-01-31 08:23:00 +13:00
}