void CmdBase::PrintUsage(const Args& args, Str::StringRef syntax, Str::StringRef description) const { if(description.empty()) { Print("%s: %s %s", _("usage"), args.Argv(0).c_str(), syntax.c_str()); } else { Print("%s: %s %s — %s", _("usage"), args.Argv(0).c_str(), syntax.c_str(), description.c_str()); } }
//TODO: error handling? int VMBase::Create(Str::StringRef name, Type type) { if (module) { Com_Printf(S_ERROR "Attempting to re-create an already-loaded VM"); return -1; } const std::string& libPath = FS::GetLibPath(); bool debug = Cvar_Get("vm_debug", "0", CVAR_INIT)->integer; if (type == TYPE_NATIVE) { std::string exe = FS::Path::Build(libPath, name + EXE_EXT); Com_Printf("Trying to load native module %s\n", exe.c_str()); module = NaCl::LoadModule(exe.c_str(), nullptr, debug); } else if (type == TYPE_NACL) { // Extract the nexe from the pak so that sel_ldr can load it std::string nexe = name + "-" ARCH_STRING ".nexe"; try { FS::File out = FS::HomePath::OpenWrite(nexe); FS::PakPath::CopyFile(nexe, out); out.Close(); } catch (std::system_error& err) { Com_Printf(S_ERROR "Failed to extract NaCl module %s: %s\n", nexe.c_str(), err.what()); return -1; } std::string sel_ldr = FS::Path::Build(libPath, "sel_ldr" EXE_EXT); std::string irt = FS::Path::Build(libPath, "irt_core-" ARCH_STRING ".nexe"); #ifdef __linux__ std::string bootstrap = FS::Path::Build(libPath, "nacl_helper_bootstrap"); NaCl::LoaderParams params = {sel_ldr.c_str(), irt.c_str(), bootstrap.c_str()}; #else NaCl::LoaderParams params = {sel_ldr.c_str(), irt.c_str(), nullptr}; #endif Com_Printf("Trying to load NaCl module %s\n", nexe.c_str()); module = NaCl::LoadModule(FS::Path::Build(FS::GetHomePath(), nexe).c_str(), ¶ms, debug); } else { Com_Printf(S_ERROR "Invalid VM type"); return -1; } if (!module) { Com_Printf(S_ERROR "Couldn't load VM %s", name.c_str()); return -1; } if (debug) Com_Printf("Waiting for GDB connection on localhost:4014\n"); // Read the ABI version from the root socket. // If this fails, we assume the remote process failed to start std::vector<char> buffer; if (!module.GetRootSocket().RecvMsg(buffer) || buffer.size() != sizeof(int)) { Com_Printf(S_ERROR "The '%s' VM did not start.", name.c_str()); return -1; } Com_Printf("Loaded module with the NaCl ABI"); return *reinterpret_cast<int*>(buffer.data()); }
intptr_t DynamicLib::InternalLoadSym(Str::StringRef sym, std::string& errorString) { #ifdef _WIN32 intptr_t p = reinterpret_cast<intptr_t>( GetProcAddress(static_cast<HMODULE>(handle), sym.c_str())); if (!p) errorString = Win32StrError(GetLastError()); return p; #else intptr_t p = reinterpret_cast<intptr_t>(dlsym(handle, sym.c_str())); if (!p) errorString = dlerror(); return p; #endif }
bool ParseCvarValue(Str::StringRef value, std::size_t& result) { if ( value.empty() || !Str::cisdigit(value[0]) ) { return false; } result = std::stoul(value); return true; }
void Rocket_AddConsoleText(Str::StringRef text) { // HACK: Ugly way to force pre-engine-upgrade behavior. TODO: Make it work without this hack static char buffer[ MAX_STRING_CHARS ]; Q_strncpyz( buffer, text.c_str(), sizeof(buffer) ); if ( !Q_stricmp( "\n", buffer ) ) { return; } RocketConsoleTextElement::lines.push_front( ConsoleLine( Rocket::Core::String( va( "%s\n", buffer ) ) ) ); }
Args::Args(Str::StringRef cmd) { const char* in = cmd.begin(); //Skip leading whitespace SkipSpaces(in, cmd.end()); //Return if the cmd is empty if (in == cmd.end()) return; //Build arg tokens std::string currentToken; while (true) { //Check for end of current token if (SkipSpaces(in, cmd.end())) { args.push_back(std::move(currentToken)); if (in == cmd.end()) return; currentToken.clear(); } //Handle quoted strings if (in[0] == '\"') { in++; //Read all characters until quote end while (in != cmd.end()) { if (in[0] == '\"') { in++; break; } else if (in + 1 != cmd.end() && in[0] == '\\') { currentToken.push_back(in[1]); in += 2; } else { currentToken.push_back(in[0]); in++; } } } else { if (in + 1 != cmd.end() && in[0] == '\\') { currentToken.push_back(in[1]); in += 2; } else { currentToken.push_back(in[0]); in++; } } } }
DynamicLib DynamicLib::Open(Str::StringRef filename, std::string& errorString) { #ifdef _WIN32 void* handle = LoadLibraryW(Str::UTF8To16(filename).c_str()); if (!handle) errorString = Win32StrError(GetLastError()); #else // Handle relative paths correctly const char* dlopenFilename = filename.c_str(); std::string relativePath; if (filename.find('/') == std::string::npos) { relativePath = "./" + filename; dlopenFilename = relativePath.c_str(); } void* handle = dlopen(dlopenFilename, RTLD_NOW); if (!handle) errorString = dlerror(); #endif DynamicLib out; out.handle = handle; return out; }
void Drop(Str::StringRef message) { // Transform into a fatal error if too many errors are generated in quick // succession. static Sys::SteadyClock::time_point lastError; Sys::SteadyClock::time_point now = Sys::SteadyClock::now(); static int errorCount = 0; if (now - lastError < std::chrono::milliseconds(100)) { if (++errorCount > 3) Sys::Error(message); } else errorCount = 0; lastError = now; throw DropErr(message.c_str()); }
void Field::RunCommand(Str::StringRef defaultCommand) { if (GetText().empty()) { return; } std::string current = Str::UTF32To8(GetText()); if (current[0] == '/' or current[0] == '\\') { Cmd::BufferCommandText(current.c_str() + 1, true); } else if (defaultCommand.empty()) { Cmd::BufferCommandText(current, true); } else { Cmd::BufferCommandText(defaultCommand + " " + Cmd::Escape(current), true); } AddToHistory(hist, std::move(current)); Clear(); }
std::string Escape(Str::StringRef text) { if (text.empty()) { return "\"\""; } bool escaped = false; bool maybeComment = false; std::string res = "\""; for (char c: text) { if (c == '\\') { res.append("\\\\"); } else if (c == '\"') { res.append("\\\""); } else if (c == '$') { res.append("\\$"); } else { if (Str::cisspace(c) || c == ';') { escaped = true; } res.push_back(c); } if (maybeComment && (c == '/' || c == '*')) { escaped = true; maybeComment = false; } else if (c == '/') { maybeComment = true; } else { maybeComment = false; } } if (escaped) { res += "\""; } else { res.erase(0, 1); } return res; }