Commit 8a22e607 authored by Victor Yacovlev's avatar Victor Yacovlev

Implemented loading external modules from relative path to main program

parent c951d5e8
......@@ -97,6 +97,7 @@ public /*typedefs*/:
public /*methods*/:
/** Set parsed Kumir bytecode */
inline void setProgram(const Bytecode::Data & data, bool isMain, const String & filename);
inline void setProgramDirectory(const Kumir::String & path) { s_programDirectory = path; };
inline bool loadProgramFromBinaryBuffer(std::list<char> & stream, bool isMain, const String & filename, String & error);
inline bool loadProgramFromTextBuffer(const std::string & stream, bool isMain, const String & filename, String & error);
......@@ -189,6 +190,7 @@ private /*fields*/:
AnyValue register0;
Stack<Variable> stack_values;
Stack<Context> stack_contexts;
Kumir::String s_programDirectory;
public /*constructors*/:
inline KumirVM();
private /*methods*/:
......@@ -304,10 +306,18 @@ void KumirVM::setProgram(const Bytecode::Data &program, bool isMain, const Strin
}
if (externModuleContext==-1) {
externModuleContext = currentModuleContext + 1;
const std::string filename = Kumir::Coder::encode(VM_LOCALE, e.fileName);
Kumir::String modulePath;
if (e.fileName[0]==Kumir::Char('/') || s_programDirectory.length()==0)
modulePath = e.fileName;
else {
modulePath = s_programDirectory;
modulePath.push_back(Kumir::Char('/'));
modulePath += e.fileName;
}
const std::string filename = Kumir::Coder::encode(VM_LOCALE, modulePath);
std::fstream externalfile(filename.c_str());
if (!Kumir::Files::exist(e.fileName) || !externalfile.is_open()) {
Kumir::String errorMessage = Kumir::Core::fromUtf8("Не могу загрузить внешний исполнитель: ")+e.fileName;
if (!Kumir::Files::exist(modulePath) || !externalfile.is_open()) {
Kumir::String errorMessage = Kumir::Core::fromUtf8("Не могу загрузить внешний исполнитель: ")+modulePath;
throw errorMessage;
}
Bytecode::Data programData;
......
......@@ -84,6 +84,29 @@ Kumir::String decodeHttpStringValue(const std::string & s)
return result;
}
int showErrorMessage(const Kumir::String & message, int code) {
bool toHttp = false;
#if !defined(WIN32) && !defined(_WIN32)
char * REQUEST_METHOD = getenv("REQUEST_METHOD");
char * QUERY_STRING = getenv("QUERY_STRING");
toHttp = (REQUEST_METHOD!=0 && QUERY_STRING!=0);
#endif
if (!toHttp) {
const std::string localMessage = Kumir::Coder::encode(LOCALE, message);
std::cerr << localMessage << std::endl;
return code;
}
else {
const std::string localMessage = Kumir::Coder::encode(Kumir::UTF8, message);
std::cout << "Content-type: text/html;charset=utf-8\n\n\n";
std::cout << "<html><head><title>An error occured on server</title></head>\n";
std::cout << "<body>\n";
std::cout << localMessage << std::endl;
std::cout << "</body></html>\n";
return 0;
}
}
bool InteractionHandler::readScalarArgument(const Kumir::String &message, const Kumir::String &name, VM::ValueType type, VM::AnyValue &val)
{
Kumir::IO::InputStream stream;
......@@ -258,6 +281,15 @@ int main(int argc, char *argv[])
InteractionHandler interactionHandler(argc, argv);
vm.setExternalHandler(&interactionHandler);
Kumir::String programPath = Kumir::Files::getAbsolutePath(Kumir::Coder::decode(LOCALE, programName));
size_t slashPos = programPath.find_last_of(Kumir::Char('/'));
Kumir::String programDir;
if (slashPos!=Kumir::String::npos) {
programDir = programPath.substr(0, slashPos);
}
vm.setProgramDirectory(programDir);
static const Kumir::String LOAD_ERROR = Kumir::Core::fromUtf8("ОШИБКА ЗАГРУЗКИ ПРОГРАММЫ: ");
try {
......@@ -265,20 +297,15 @@ int main(int argc, char *argv[])
}
catch (Kumir::String & msg) {
Kumir::String message = LOAD_ERROR + msg;
const std::string localMessage = Kumir::Coder::encode(LOCALE, message);
std::cerr << localMessage << std::endl;
return 11;
return showErrorMessage(message, 11);
}
catch (std::string & msg) {
Kumir::String message = LOAD_ERROR + Kumir::Core::fromAscii(msg);
const std::string localMessage = Kumir::Coder::encode(LOCALE, message);
std::cerr << localMessage << std::endl;
return 11;
return showErrorMessage(message, 11);
}
catch (...) {
const std::string localMessage = Kumir::Coder::encode(LOCALE, LOAD_ERROR);
std::cerr << localMessage << std::endl;
return 11;
Kumir::String message = LOAD_ERROR;
return showErrorMessage(message, 11);
}
vm.reset();
......@@ -301,8 +328,7 @@ int main(int argc, char *argv[])
else {
message = RUNTIME_ERROR + vm.error();
}
const std::string localMessage = Kumir::Coder::encode(LOCALE, message);
std::cerr << localMessage << std::endl;
return showErrorMessage(message, 10);
return 10;
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment