aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-03-03 12:53:37 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-03-03 12:53:37 +0200
commitc76fe316122969986103d243706dc7fa7ab6ddc1 (patch)
treebddbe5695a9079b701219a3dc0d3c5805f4ca9e6
parent17287b34a8090d381278c02b7bc6676669968099 (diff)
Use names() to handle include/source, support include of directories
This gives us variable expansion and directory prefixes. Also, in include, if the path is a directory (either ends with / or has dir{} type), then we append 'buildfile'.
-rw-r--r--build/parser.cxx71
-rw-r--r--tests/build/buildfile4
-rw-r--r--tests/build/semantics/include/includer1
-rw-r--r--tests/build/semantics/source/sourcer1
4 files changed, 57 insertions, 20 deletions
diff --git a/build/parser.cxx b/build/parser.cxx
index d5b07b1..1ff841b 100644
--- a/build/parser.cxx
+++ b/build/parser.cxx
@@ -435,14 +435,20 @@ namespace build
{
tracer trace ("parser::source", &path_);
- // The rest should be a list of paths to buildfiles.
+ // The rest should be a list of buildfiles. Parse them as names
+ // to get variable expansion and directory prefixes.
//
- for (; tt != type::newline && tt != type::eos; next (t, tt))
- {
- if (tt != type::name)
- fail (t) << "expected buildfile to source instead of " << t;
+ location l (get_location (t, &path_));
+ names_type ns (tt != type::newline && tt != type::eos
+ ? names (t, tt)
+ : names_type ());
- path p (t.name ());
+ for (name& n: ns)
+ {
+ // Construct the buildfile path.
+ //
+ path p (move (n.dir));
+ p /= path (move (n.value));
// If the path is relative then use the src directory corresponding
// to the current directory scope.
@@ -453,7 +459,7 @@ namespace build
ifstream ifs (p.string ());
if (!ifs.is_open ())
- fail (t) << "unable to open " << p;
+ fail (l) << "unable to open " << p;
ifs.exceptions (ifstream::failbit | ifstream::badbit);
@@ -467,6 +473,8 @@ namespace build
lexer* ol (lexer_);
lexer_ = &l;
+ token t (type::eos, false, 0, 0);
+ type tt;
next (t, tt);
clause (t, tt);
@@ -479,8 +487,10 @@ namespace build
path_ = op;
}
- if (tt != type::eos)
- next (t, tt); // Swallow newline.
+ if (tt == type::newline)
+ next (t, tt);
+ else if (tt != type::eos)
+ fail (t) << "expected newline instead of " << t;
}
void parser::
@@ -488,16 +498,33 @@ namespace build
{
tracer trace ("parser::include", &path_);
- // The rest should be a list of paths to buildfiles.
+ // The rest should be a list of buildfiles. Parse them as names
+ // to get variable expansion and directory prefixes.
//
- for (; tt != type::newline && tt != type::eos; next (t, tt))
+ location l (get_location (t, &path_));
+ names_type ns (tt != type::newline && tt != type::eos
+ ? names (t, tt)
+ : names_type ());
+
+ for (name& n: ns)
{
- if (tt != type::name)
- fail (t) << "expected buildfile to include instead of " << t;
+ // Construct the buildfile path. If it is a directory, then append
+ // 'buildfile'.
+ //
+ path p (move (n.dir));
+ if (n.value.empty ())
+ p /= path ("buildfile");
+ else
+ {
+ bool d (path::traits::is_separator (n.value.back ())
+ || n.type == "dir");
- path p (t.name ());
- bool in_out (false);
+ p /= path (move (n.value));
+ if (d)
+ p /= path ("buildfile");
+ }
+ bool in_out (false);
if (p.absolute ())
{
p.normalize ();
@@ -506,7 +533,7 @@ namespace build
// to be used for intra-project inclusion.
//
if (!p.sub (src_root) && !(in_out = p.sub (out_root)))
- fail (t) << "out of project include " << p;
+ fail (l) << "out of project include " << p;
}
else
{
@@ -518,14 +545,14 @@ namespace build
if (!include_.insert (p).second)
{
- level4 ([&]{trace (t) << "skipping already included " << p;});
+ level4 ([&]{trace (l) << "skipping already included " << p;});
continue;
}
ifstream ifs (p.string ());
if (!ifs.is_open ())
- fail (t) << "unable to open " << p;
+ fail (l) << "unable to open " << p;
ifs.exceptions (ifstream::failbit | ifstream::badbit);
@@ -545,6 +572,8 @@ namespace build
target* odt (default_target_);
default_target_ = nullptr;
+ token t (type::eos, false, 0, 0);
+ type tt;
next (t, tt);
clause (t, tt);
@@ -561,8 +590,10 @@ namespace build
path_ = op;
}
- if (tt != type::eos)
- next (t, tt); // Swallow newline.
+ if (tt == type::newline)
+ next (t, tt);
+ else if (tt != type::eos)
+ fail (t) << "expected newline instead of " << t;
}
void parser::
diff --git a/tests/build/buildfile b/tests/build/buildfile
new file mode 100644
index 0000000..99a0a6f
--- /dev/null
+++ b/tests/build/buildfile
@@ -0,0 +1,4 @@
+d=path/ prefix-map/
+
+.: $d
+include $d
diff --git a/tests/build/semantics/include/includer b/tests/build/semantics/include/includer
index c129e33..70527a5 100644
--- a/tests/build/semantics/include/includer
+++ b/tests/build/semantics/include/includer
@@ -7,3 +7,4 @@ nested/:
include includee5
include ../includee2 # skipped
}
+:
diff --git a/tests/build/semantics/source/sourcer b/tests/build/semantics/source/sourcer
index e8b9558..eb1310e 100644
--- a/tests/build/semantics/source/sourcer
+++ b/tests/build/semantics/source/sourcer
@@ -6,3 +6,4 @@ nested/:
source sourcee3
source ../sourcee1
}
+: