aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libbuild2/parser.cxx68
-rw-r--r--libbuild2/parser.hxx8
2 files changed, 63 insertions, 13 deletions
diff --git a/libbuild2/parser.cxx b/libbuild2/parser.cxx
index a404115..0fcf977 100644
--- a/libbuild2/parser.cxx
+++ b/libbuild2/parser.cxx
@@ -3181,7 +3181,7 @@ namespace build2
source_buildfile (istream& is,
const path_name& in,
const location& loc,
- bool deft)
+ optional<bool> deft)
{
tracer trace ("parser::source_buildfile", &path_);
@@ -3199,11 +3199,11 @@ namespace build2
lexer_ = &l;
target* odt;
- if (deft)
- {
+ if (!deft || *deft)
odt = default_target_;
+
+ if (deft && *deft)
default_target_ = nullptr;
- }
token t;
type tt;
@@ -3213,13 +3213,14 @@ namespace build2
if (tt != type::eos)
fail (t) << "unexpected " << t;
- if (deft)
+ if (deft && *deft)
{
if (stage_ != stage::boot && stage_ != stage::root)
process_default_target (t, bf);
+ }
+ if (!deft || *deft)
default_target_ = odt;
- }
lexer_ = ol;
path_ = op;
@@ -3230,11 +3231,35 @@ namespace build2
void parser::
parse_source (token& t, type& tt)
{
+ // source [<attrs>] <path>+
+ //
+
// The rest should be a list of buildfiles. Parse them as names in the
- // value mode to get variable expansion and directory prefixes.
+ // value mode to get variable expansion and directory prefixes. Also
+ // handle optional attributes.
//
mode (lexer_mode::value, '@');
- next (t, tt);
+ next_with_attributes (t, tt);
+ attributes_push (t, tt);
+
+ bool nodt (false); // Source buildfile without default target semantics.
+ {
+ attributes as (attributes_pop ());
+ const location& l (as.loc);
+
+ for (const attribute& a: as)
+ {
+ const string& n (a.name);
+
+ if (n == "no_default_target")
+ {
+ nodt = true;
+ }
+ else
+ fail (l) << "unknown source directive attribute " << a;
+ }
+ }
+
const location l (get_location (t));
names ns (tt != type::newline && tt != type::eos
? parse_names (t, tt, pattern_mode::expand, "path", nullptr)
@@ -3264,7 +3289,7 @@ namespace build2
source_buildfile (ifs,
path_name (p),
get_location (t),
- false /* default_target */);
+ nodt ? optional<bool> {} : false);
}
catch (const io_error& e)
{
@@ -3278,6 +3303,9 @@ namespace build2
void parser::
parse_include (token& t, type& tt)
{
+ // include <path>+
+ //
+
tracer trace ("parser::parse_include", &path_);
if (stage_ == stage::boot)
@@ -4072,6 +4100,7 @@ namespace build2
bool meta (false); // Import with metadata.
bool once (false); // Import buildfile once.
+ bool nodt (false); // Import buildfile without default target semantics.
{
attributes& as (attributes_top ());
const location& l (as.loc);
@@ -4089,6 +4118,10 @@ namespace build2
meta = true;
}
+ else if (n == "no_default_target")
+ {
+ nodt = true;
+ }
else if (n == "once")
{
once = true;
@@ -4213,8 +4246,15 @@ namespace build2
if (meta)
fail (loc) << "metadata requested for buildfile target " << n;
- if (once && var != nullptr)
- fail (loc) << "once importation requested with variable assignment";
+ if (var != nullptr)
+ {
+ if (once)
+ fail (loc) << "once importation requested with variable assignment";
+
+ if (nodt)
+ fail (loc) << "no_default_target importation requested with "
+ << "variable assignment";
+ }
if (ph2 && !ph2->empty ())
fail (loc) << "rule hint specified for buildfile target " << n;
@@ -4224,6 +4264,10 @@ namespace build2
if (once)
fail (loc) << "once importation requested for target " << n;
+ if (nodt)
+ fail (loc) << "no_default_target importation requested for target "
+ << n;
+
if (var == nullptr)
fail (loc) << "variable assignment required to import target " << n;
}
@@ -4323,7 +4367,7 @@ namespace build2
source_buildfile (ifs,
path_name (p),
loc,
- false /* default_target */);
+ nodt ? optional<bool> {} : false);
}
catch (const io_error& e)
{
diff --git a/libbuild2/parser.hxx b/libbuild2/parser.hxx
index 7263e59..b756984 100644
--- a/libbuild2/parser.hxx
+++ b/libbuild2/parser.hxx
@@ -388,11 +388,17 @@ namespace build2
// processing. If the specified path name has a real path, then also enter
// it as a buildfile.
//
+ // If default_target is nullopt, then disable the default target semantics
+ // as when loading boostrap.build or root.build. If it is false, then
+ // continue with the existing default_target value. If it is true, then
+ // start with a new default_value and call process_default_target() at
+ // the end.
+ //
void
source_buildfile (istream&,
const path_name&,
const location&,
- bool default_target);
+ optional<bool> default_target);
// The what argument is used in diagnostics (e.g., "expected <what>
// instead of ...".