diff --git a/CMakeLists.txt b/CMakeLists.txt index 94ac0e5..ad55fea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,6 +66,7 @@ flex_target(Lexer shell/lexer.l set(fxos_shell_SOURCES shell/main.cpp + shell/legacy.cpp shell/parser.cpp shell/session.cpp shell/theme.cpp diff --git a/doc/program-structure.md b/doc/program-structure.md index 5702fe1..31fea73 100644 --- a/doc/program-structure.md +++ b/doc/program-structure.md @@ -4,7 +4,7 @@ The loading and management of programs go through several layers that each have ### Loading layer -```c++ +```cpp #include #include ``` @@ -19,7 +19,7 @@ While not explicitly supported yet, the loading layer could be used to load comp ### Binary layer -```c++ +```cpp #include #include #include @@ -36,7 +36,7 @@ Analysis results at the binary layer include: ### Project layer -```c++ +```cpp #include ``` diff --git a/doc/projects.md b/doc/projects.md index 630c621..62dcd3e 100644 --- a/doc/projects.md +++ b/doc/projects.md @@ -75,7 +75,7 @@ In version 1.x, fxos still loads `fxosrc` if it exists, and lists any legacy vir (3) % fxos -p ``` -When specifying an existing folder as argument (1), fxos assumes the folder is a project folder and attempts to load it. When specifying an existing file (2), a new temporary project is created, with that file mapped in the virtual sapce. When specifying `-p`, fxos loads the most recent project with the provided name. +When specifying an existing folder as argument (1), fxos assumes the folder is a project folder and attempts to load it. When specifying an existing file (2), a new temporary project is created, with that file mapped in the virtual space. When specifying `-p`, fxos loads the most recent project with the provided name. **`pl`: Project Load** @@ -83,5 +83,5 @@ When specifying an existing folder as argument (1), fxos assumes the folder is a pl ( | "") ``` -`pl` loads an existing project. With a symbol argument, loads a recent project by name. With string that identifies a folder, loads a project from the filesystem. +`pl` loads an existing project. With a symbol argument, loads a recent project by name. With a string that identifies a folder, loads a project from the filesystem. diff --git a/shell/i.cpp b/shell/i.cpp index ea996c4..e14378b 100644 --- a/shell/i.cpp +++ b/shell/i.cpp @@ -213,6 +213,21 @@ void _ip(Session &session) for(auto &e: entries) fmt::print(" {} ({}, last used {:%c})\n", e.name, e.path, fmt::localtime(e.utime)); + + if(session.legacySpaces.size() != 0) { + fmt::print("\nLegacy vspaces:\n"); + + for(auto const &[name, lvs]: session.legacySpaces) { + fmt::print(" {} ({} symbols, {} syscalls)\n", name, + lvs.symbols.size(), lvs.syscalls.size()); + for(auto const &b: lvs.bindings) { + fmt::print(" "); + for(auto const &r: b.regions) + fmt::print("0x{:08x} ", r.start); + fmt::print("'{}'\n", b.path); + } + } + } } //--- diff --git a/shell/legacy.cpp b/shell/legacy.cpp new file mode 100644 index 0000000..834e171 --- /dev/null +++ b/shell/legacy.cpp @@ -0,0 +1,58 @@ +#include "legacy.h" +#include "session.h" +#include "parser.h" + +#include + +bool legacy_command(Session &session, std::string const &cmd, Parser &parser) +{ + if(cmd == "vc") { + std::string name + = parser.at_end() + ? session.legacyGenerateSpaceName("space", true) + : session.legacyGenerateSpaceName(parser.symbol(), false); + parser.end(); + + /* Construct a new legacy space at name */ + session.legacySpaces[name]; + session.legacyCurrentSpace = name; + return true; + } + else if(cmd == "vm") { + LegacyBinding b; + b.path = parser.str(); + while(!parser.at_end()) + b.regions.push_back(parser.region(nullptr)); + parser.end(); + + session.legacySpaces[session.legacyCurrentSpace].bindings.push_back(b); + return true; + } + else if(cmd == "vs") { + std::string name = parser.symbol("vspace_name"); + parser.end(); + + if(session.legacySpaces.count(name)) + session.legacyCurrentSpace = name; + return true; + } + else if(cmd == "ms") { + auto &lvs = session.legacySpaces[session.legacyCurrentSpace]; + + if(parser.lookahead().type == T::SYSCALL) { + int id = parser.expect(T::SYSCALL).value.NUM; + lvs.syscalls[id] = parser.symbol(); + } + else { + int addr = parser.expr(nullptr); + lvs.symbols[addr] = parser.symbol(); + } + + return true; + } + else if(cmd != "." && cmd != ".dt") { + FxOS_log( + WRN, "skipping unrecognized command '%s' in fxosrc", cmd.c_str()); + } + return false; +} diff --git a/shell/legacy.h b/shell/legacy.h new file mode 100644 index 0000000..bacb192 --- /dev/null +++ b/shell/legacy.h @@ -0,0 +1,39 @@ +//--- +// fxos-shell.legacy: Legacy vpsace/pseudo-project format +//--- + +#ifndef FXOS_LEGACY_H +#define FXOS_LEGACY_H + +#include +#include + +class Session; +class Parser; + +#include +#include +#include + +struct LegacyBinding +{ + std::string path; + std::vector regions; +}; + +/* Flat description of a legacy vspace loaded via an fxosrc file. Name might be + empty. */ +struct LegacyVspace +{ + LegacyVspace() = default; + + std::vector bindings; + std::map symbols; + std::map syscalls; +}; + +/* Try to execute a given command as a legacy command. Returns true if handled, + false if normal behavior should be used. */ +bool legacy_command(Session &session, std::string const &cmd, Parser &parser); + +#endif /* FXOS_LEGACY_H */ diff --git a/shell/main.cpp b/shell/main.cpp index c330cf5..c99b7d0 100644 --- a/shell/main.cpp +++ b/shell/main.cpp @@ -17,6 +17,7 @@ namespace fs = std::filesystem; #include "shell.h" #include "theme.h" #include "parser.h" +#include "legacy.h" #include "errors.h" #include "commands.h" #include @@ -153,24 +154,20 @@ char *autocomplete(char const *text, int state) static bool read_interactive(Session &s, std::string &cmdline) { - std::string prompt = "no_vspace> "; - if(s.current_space) { - std::string name = "(none)"; + std::string prompt; - for(auto &it: s.spaces) { - if(it.second.get() == s.current_space) - name = it.first; - } + Project *p = s.project(); + if(p) + prompt += p->name() + (p->isDirty() ? "*" : ""); - Project *p = s.project(); - if(!p) - prompt - = fmt::format("{} @ 0x{:08x}> ", name, s.current_space->cursor); - else - prompt = fmt::format( - "{}{}|{}> ", p->name(), p->isDirty() ? "*" : "", name); + std::string vspace_name = "(none)"; + for(auto &it: s.spaces) { + if(it.second.get() == s.current_space) + vspace_name = it.first; } + prompt += fmt::format("|{}> ", vspace_name); + /* We need to insert RL_PROMPT_{START,END}_IGNORE into the color formatting, so we trick a little bit by using a space */ std::string color = fmt::format(theme(9), " "); @@ -426,8 +423,10 @@ int main(int argc, char **argv) if(fs::exists(path / "fxosrc")) fxosrc_files.push_back(path / "fxosrc"); } - if(fxosrc_files.size() > 0) + if(fxosrc_files.size() > 0) { _dot(s, fxosrc_files, true); + FxOS_log(WRN, "Legacy fxosrc files found; use pm to migrate."); + } } /* Whether we have reached an idle state after parsing fxosrc files */ @@ -477,6 +476,9 @@ int main(int argc, char **argv) if(cmd == "_p") { parser.dump_command(); } + else if(!has_idled && legacy_command(s, cmd, parser)) { + continue; + } else if(commands.count(cmd)) { if(parser.lookahead().type == '?') command_help(cmd); diff --git a/shell/session.cpp b/shell/session.cpp index 5d6397e..f4a157c 100644 --- a/shell/session.cpp +++ b/shell/session.cpp @@ -104,6 +104,12 @@ VirtualSpace *Session::get_space(std::string name) return it == this->spaces.end() ? nullptr : it->second.get(); } +std::string Session::legacyGenerateSpaceName( + std::string prefix, bool force_suffix) +{ + return generate_space_name(prefix, force_suffix); +} + std::string Session::generate_space_name(std::string prefix, bool force_suffix) { if(!force_suffix && this->spaces.count(prefix) == 0) diff --git a/shell/session.h b/shell/session.h index f1b966b..77c9fbf 100644 --- a/shell/session.h +++ b/shell/session.h @@ -5,6 +5,7 @@ #ifndef FXOS_SESSION_H #define FXOS_SESSION_H +#include "legacy.h" #include #include @@ -72,6 +73,14 @@ struct Session return m_recent; } + //=== Legacy (0.x) virtual space info for migrations ===// + + std::map legacySpaces; + std::string legacyCurrentSpace; + + std::string legacyGenerateSpaceName(std::string prefix, + bool force_suffix=false); + //--- // Virtual spaces // TODO: To be replaced with legacy descriptions