diff options
Diffstat (limited to 'build/parser.cxx')
-rw-r--r-- | build/parser.cxx | 102 |
1 files changed, 66 insertions, 36 deletions
diff --git a/build/parser.cxx b/build/parser.cxx index 1ff841b..a030a09 100644 --- a/build/parser.cxx +++ b/build/parser.cxx @@ -125,6 +125,9 @@ namespace build scope_ = &s; default_target_ = nullptr; + out_root_ = &s["out_root"].as<const path&> (); + src_root_ = &s["src_root"].as<const path&> (); + token t (type::eos, false, 0, 0); type tt; next (t, tt); @@ -394,28 +397,28 @@ namespace build } else { - //@@ TODO: assuming it is a list. - // - list_value* val (dynamic_cast<list_value*> ((*scope_)[var])); - - if (val == nullptr) // Initialization. + if (auto val = (*scope_)[var]) { - list_value_ptr nval (new list_value (*scope_, move (vns))); - scope_->variables.emplace (var, move (nval)); + //@@ TODO: assuming it is a list. + // + list_value* lv (&val.as<list_value&> ()); + + if (&lv->scope != scope_) // Append to value from parent scope? + { + list_value_ptr nval (new list_value (*scope_, lv->data)); + lv = nval.get (); // Append to. + scope_->variables.emplace (var, move (nval)); + } + + lv->data.insert (lv->data.end (), + make_move_iterator (vns.begin ()), + make_move_iterator (vns.end ())); } - else if (&val->scope != scope_) // Append to value from parent scope. + else // Initialization. { - list_value_ptr nval (new list_value (*scope_, val->data)); - val = nval.get (); // Append. + list_value_ptr nval (new list_value (*scope_, move (vns))); scope_->variables.emplace (var, move (nval)); } - - // Append. - // - if (val != nullptr) - val->data.insert (val->data.end (), - make_move_iterator (vns.begin ()), - make_move_iterator (vns.end ())); } if (tt == type::newline) @@ -454,7 +457,7 @@ namespace build // to the current directory scope. // if (p.relative ()) - p = src_out (scope_->path ()) / p; + p = src_out (scope_->path (), *out_root_, *src_root_) / p; ifstream ifs (p.string ()); @@ -532,14 +535,14 @@ namespace build // Make sure the path is in this project. Include is only meant // to be used for intra-project inclusion. // - if (!p.sub (src_root) && !(in_out = p.sub (out_root))) + if (!p.sub (*src_root_) && !(in_out = p.sub (*out_root_))) fail (l) << "out of project include " << p; } else { // Use the src directory corresponding to the current directory scope. // - p = src_out (scope_->path ()) / p; + p = src_out (scope_->path (), *out_root_, *src_root_) / p; p.normalize (); } @@ -549,6 +552,22 @@ namespace build continue; } + // Determine new bases. + // + path out_base; + path src_base; + + if (in_out) + { + out_base = p.directory (); + src_base = src_out (out_base, *out_root_, *src_root_); + } + else + { + src_base = p.directory (); + out_base = out_src (src_base, *out_root_, *src_root_); + } + ifstream ifs (p.string ()); if (!ifs.is_open ()) @@ -567,7 +586,10 @@ namespace build lexer_ = &l; scope* os (scope_); - scope_ = &scopes[(in_out ? p : out_src (p)).directory ()]; + scope_ = &scopes[out_base]; + + scope_->variables["out_base"] = move (out_base); + scope_->variables["src_base"] = move (src_base); target* odt (default_target_); default_target_ = nullptr; @@ -745,14 +767,12 @@ namespace build //@@ TODO: append namespace if any. n = t.name (); - //@@ TODO: assuming it is a list. - // const variable& var (variable_pool.find (move (n))); - list_value* val (dynamic_cast<list_value*> ((*scope_)[var])); + auto val ((*scope_)[var]); // Undefined namespaces variables are not allowed. // - if (val == nullptr && var.name.find ('.') != string::npos) + if (!val && var.name.find ('.') != string::npos) fail (t) << "undefined namespace variable " << var.name; if (paren) @@ -765,7 +785,14 @@ namespace build tt = peek (); - if (val == nullptr || val->data.empty ()) + if (!val) + continue; + + //@@ TODO: assuming it is a list. + // + const list_value& lv (val.as<list_value&> ()); + + if (lv.data.empty ()) continue; // Should we accumulate? If the buffer is not empty, then @@ -778,33 +805,36 @@ namespace build ((tt == type::name || tt == type::dollar) // Start. && !peeked ().separated ())) { - // This should be a simple value. The token still points - // to the name (or closing paren). + // This should be a simple value or a simple directory. The + // token still points to the name (or closing paren). // - if (val->data.size () > 1) + if (lv.data.size () > 1) fail (t) << "concatenating expansion of " << var.name << " contains multiple values"; - const name& n (val->data[0]); + const name& n (lv.data[0]); if (!n.type.empty ()) fail (t) << "concatenating expansion of " << var.name << " contains type"; if (!n.dir.empty ()) - fail (t) << "concatenating expansion of " << var.name - << " contains directory"; - - concat += n.value; + { + if (!n.value.empty ()) + fail (t) << "concatenating expansion of " << var.name + << " contains directory"; - text << "concat: " << concat; + concat += n.dir.string (); + } + else + concat += n.value; } else { // Copy the names from the variable into the resulting name list // while doing sensible things with the types and directories. // - for (const name& n: val->data) + for (const name& n: lv.data) { const path* dp1 (dp); const string* tp1 (tp); |