diff options
author | John Hodge <tpg@mutabah.net> | 2018-02-10 12:25:44 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2018-02-10 12:25:44 +0800 |
commit | 9e864a5d3ea05706ea6c7f68e47d32629a2c877e (patch) | |
tree | 290754fd4b3f1a3d265303373b5428872e92c9c0 /tools | |
parent | daacad86908557e5914d2d6931f3db6d1b75f1d0 (diff) | |
download | mrust-9e864a5d3ea05706ea6c7f68e47d32629a2c877e.tar.gz |
minicargo - Add parser for cfg() in target-specific options.
Diffstat (limited to 'tools')
-rw-r--r-- | tools/minicargo/debug.h | 3 | ||||
-rw-r--r-- | tools/minicargo/main.cpp | 5 | ||||
-rw-r--r-- | tools/minicargo/manifest.cpp | 189 |
3 files changed, 166 insertions, 31 deletions
diff --git a/tools/minicargo/debug.h b/tools/minicargo/debug.h index c445594f..ace00876 100644 --- a/tools/minicargo/debug.h +++ b/tools/minicargo/debug.h @@ -14,13 +14,12 @@ extern void Debug_Print(dbg_cb_t cb); #if defined(NOLOG) # define DEBUG(fmt) do { } while(0) -# define TODO(fmt) do { } while(0) # define TRACE_FUNCTION_F(fmt) do{}while(0) #else # define DEBUG(fmt) do { Debug_Print([&](auto& os){ os << "DEBUG: " << fmt; }); } while(0) -# define TODO(fmt) do { Debug_Print([&](auto& os){ os << "TODO: " << fmt; }); abort(); } while(0) # define TRACE_FUNCTION_F(fmt) DebugFunctionScope trace_function_hdr { __FUNCTION__, [&](auto& os){ os << fmt; } } #endif +#define TODO(fmt) do { ::std::cerr << "TODO: " << fmt << ::std::endl; abort(); } while(0) namespace { static inline void format_to_stream(::std::ostream& os) { diff --git a/tools/minicargo/main.cpp b/tools/minicargo/main.cpp index 8bfb2bb3..008ae0aa 100644 --- a/tools/minicargo/main.cpp +++ b/tools/minicargo/main.cpp @@ -84,7 +84,7 @@ int main(int argc, const char* argv[]) build_opts.build_script_overrides = ::std::move(bs_override_dir); build_opts.output_dir = opts.output_directory ? ::helpers::path(opts.output_directory) : ::helpers::path("output"); build_opts.lib_search_dirs.reserve(opts.lib_search_dirs.size()); - build_opts.target_name = opts.target; + build_opts.target_name = opts.target; for(const auto* d : opts.lib_search_dirs) build_opts.lib_search_dirs.push_back( ::helpers::path(d) ); Debug_SetPhase("Enumerate Build"); @@ -208,6 +208,9 @@ int ProgramOptions::parse(int argc, const char* argv[]) } this->target = argv[++i]; } + else if( ::std::strcmp(arg, "--pause") == 0 ) { + this->pause_before_quit = true; + } else { ::std::cerr << "Unknown flag " << arg << ::std::endl; return 1; diff --git a/tools/minicargo/manifest.cpp b/tools/minicargo/manifest.cpp index e7228ed7..a3158874 100644 --- a/tools/minicargo/manifest.cpp +++ b/tools/minicargo/manifest.cpp @@ -217,6 +217,7 @@ PackageManifest PackageManifest::load_from_toml(const ::std::string& path) { // TODO: Target opts? if( key_val.path.size() < 3 ) { + throw ::std::runtime_error("Expected at least three path components in `[target.{...}]`"); } const auto& cfg = key_val.path[1]; const auto& real_section = key_val.path[2]; @@ -224,34 +225,166 @@ PackageManifest PackageManifest::load_from_toml(const ::std::string& path) // - It can be a target spec, or a cfg(foo) same as rustc bool success; if( cfg.substr(0, 4) == "cfg(" ) { - // TODO: Parser? - if( cfg == "cfg(unix)" ) { - success = CFG_UNIX; - } - else if( cfg == "cfg(all(unix, not(target_os = \"macos\")))" ) { - success = CFG_UNIX; - } - else if( cfg == "cfg(not(target_os = \"emscripten\"))" ) { - success = true; - } - else if( cfg == "cfg(all(unix, not(target_os = \"emscripten\"), not(target_os = \"macos\"), not(target_os = \"ios\")))" ) { - success = CFG_UNIX; - } - else if( cfg == "cfg(windows)" ) { - success = CFG_WINDOWS; - } - else if( cfg == "cfg(target_env = \"msvc\")" ) { - success = CFG_WINDOWS; - } - else if( cfg == "cfg(not(windows))" ) { - success = !CFG_WINDOWS; - } - else if( cfg == "cfg(not(stage0))" ) { - success = true; - } - else { - TODO("Target deps - " << cfg); - } + class Parser + { + public: + class Tok + { + friend class Parser; + const char* s; + const char* e; + Tok(const char* s, const char* e): + s(s), e(e) + { + } + public: + bool operator==(const char* v) const { + return (strlen(v) == e - s) && memcmp(s, v, e-s) == 0; + } + bool operator!=(const char* v) const { + return (strlen(v) != e - s) || memcmp(s, v, e-s) != 0; + } + ::std::string to_string() const { + return ::std::string(s, e); + } + }; + private: + const char* m_pos; + Tok m_cur; + + public: + Parser(const char* s): + m_pos(s), + m_cur(nullptr,nullptr) + { + consume(); + } + const Tok& cur() const { + return m_cur; + } + + Tok consume() { + auto rv = m_cur; + m_cur = get_next(); + //::std::cout << "consume: " << rv.to_string() << " => " << m_cur.to_string() << ::std::endl; + return rv; + } + bool consume_if(const char* s) { + if( cur() == s ) { + consume(); + return true; + } + else { + return false; + } + } + private: + Tok get_next() { + while(*m_pos == ' ') + m_pos ++; + if(*m_pos == 0) + return Tok { m_pos, m_pos }; + switch(*m_pos) + { + case '(': case ')': + case ',': case '=': + return Tok { m_pos++, m_pos }; + case '"': { + auto s = m_pos; + m_pos ++; + while( *m_pos != '"' ) + { + if( *m_pos == '\\' ) + { + TODO("Escape sequences in cfg parser"); + } + m_pos ++; + } + m_pos ++; + return Tok { s, m_pos }; } + default: + if( isalnum(*m_pos) || *m_pos == '_' ) + { + auto s = m_pos; + while(isalnum(*m_pos) || *m_pos == '_') + m_pos ++; + return Tok { s, m_pos }; + } + else + { + throw ::std::runtime_error(format("Unexpected character in cfg() - ", *m_pos)); + } + } + } + }; + + struct H { + static bool check_cfg(Parser& p) + { + if( p.consume_if("not") ) { + if( !p.consume_if("(") ) + throw ::std::runtime_error("Expected '(' after `not`"); + auto rv = !check_cfg(p); + if( !p.consume_if(")") ) + throw ::std::runtime_error("Expected ')' after `not` content"); + return rv; + } + else if( p.consume_if("all") ) { + if( !p.consume_if("(") ) + throw ::std::runtime_error("Expected '(' after `all`"); + bool rv = true; + do + { + rv &= check_cfg(p); + } while(p.consume_if(",")); + if( !p.consume_if(")") ) + throw ::std::runtime_error("Expected ')' after `all` content"); + return rv; + } + // Strings + else if( p.consume_if("target_os") ) { + if( !p.consume_if("=") ) + throw ::std::runtime_error("Expected '=' after target_os"); + auto t = p.consume(); + if( t == "\"emscripten\"" ) { + return false; + } + else { + TODO("Handle target_os string - " << t.to_string()); + } + } + else if( p.consume_if("target_arch") ) { + if( !p.consume_if("=") ) + throw ::std::runtime_error("Expected '=' after target"); + auto t = p.consume(); + if( t == "\"wasm32\"" ) { + return false; + } + else{ + TODO("Handle target_arch string - " << t.to_string()); + } + } + // Flags + else if( p.consume_if("unix") ) { + return CFG_UNIX; + } + else if( p.consume_if("windows") ) { + return CFG_WINDOWS; + } + else if( p.consume_if("stage0") ) { + return false; + } + else { + TODO("Unknown fragment in cfg - " << p.cur().to_string()); + throw ::std::runtime_error(""); + } + } + }; + + Parser p { cfg.data() + 4 }; + success = H::check_cfg(p); + if( !p.consume_if(")") ) + throw ::std::runtime_error(format("Expected ')' after cfg condition - got", p.cur().to_string())); } else { // It's a target name |