aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/script/parser.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'libbuild2/script/parser.cxx')
-rw-r--r--libbuild2/script/parser.cxx100
1 files changed, 65 insertions, 35 deletions
diff --git a/libbuild2/script/parser.cxx b/libbuild2/script/parser.cxx
index 160374d..6c651a6 100644
--- a/libbuild2/script/parser.cxx
+++ b/libbuild2/script/parser.cxx
@@ -114,11 +114,11 @@ namespace build2
//
auto check_command = [&c, this] (const location& l, bool last)
{
- if (c.out.type == redirect_type::merge &&
- c.err.type == redirect_type::merge)
+ if (c.out && c.out->type == redirect_type::merge &&
+ c.err && c.err->type == redirect_type::merge)
fail (l) << "stdout and stderr redirected to each other";
- if (!last && c.out.type != redirect_type::none)
+ if (!last && c.out)
fail (l) << "stdout is both redirected and piped";
};
@@ -176,33 +176,41 @@ namespace build2
auto add_word = [&c, &p, &mod, &check_regex_mod, this] (
string&& w, const location& l)
{
- auto add_merge = [&l, this] (redirect& r, const string& w, int fd)
+ auto add_merge = [&l, this] (optional<redirect>& r,
+ const string& w,
+ int fd)
{
+ assert (r); // Must already be present.
+
try
{
size_t n;
if (stoi (w, &n) == fd && n == w.size ())
{
- r.fd = fd;
+ r->fd = fd;
return;
}
}
catch (const exception&) {} // Fall through.
fail (l) << (fd == 1 ? "stderr" : "stdout") << " merge redirect "
- << "file descriptor must be " << fd;
+ << "file descriptor must be " << fd;
};
- auto add_here_str = [] (redirect& r, string&& w)
+ auto add_here_str = [] (optional<redirect>& r, string&& w)
{
- if (r.modifiers.find (':') == string::npos)
+ assert (r); // Must already be present.
+
+ if (r->modifiers.find (':') == string::npos)
w += '\n';
- r.str = move (w);
+ r->str = move (w);
};
auto add_here_str_regex = [&l, &check_regex_mod] (
- redirect& r, int fd, string&& w)
+ optional<redirect>& r, int fd, string&& w)
{
+ assert (r); // Must already be present.
+
const char* what (nullptr);
switch (fd)
{
@@ -210,11 +218,11 @@ namespace build2
case 2: what = "stderr regex redirect"; break;
}
- check_regex_mod (r.modifiers, w, l, what);
+ check_regex_mod (r->modifiers, w, l, what);
regex_parts rp (parse_regex (w, l, what));
- regex_lines& re (r.regex);
+ regex_lines& re (r->regex);
re.intro = rp.intro;
re.lines.emplace_back (
@@ -225,7 +233,7 @@ namespace build2
// Note that the position is synthetic, but that's ok as we don't
// expect any diagnostics to refer this line.
//
- if (r.modifiers.find (':') == string::npos)
+ if (r->modifiers.find (':') == string::npos)
re.lines.emplace_back (l.line, l.column, string (), false);
};
@@ -249,8 +257,12 @@ namespace build2
}
};
- auto add_file = [&parse_path] (redirect& r, int fd, string&& w)
+ auto add_file = [&parse_path] (optional<redirect>& r,
+ int fd,
+ string&& w)
{
+ assert (r); // Must already be present.
+
const char* what (nullptr);
switch (fd)
{
@@ -259,7 +271,7 @@ namespace build2
case 2: what = "stderr redirect path"; break;
}
- r.file.path = parse_path (move (w), what);
+ r->file.path = parse_path (move (w), what);
};
switch (p)
@@ -442,6 +454,9 @@ namespace build2
mod = move (t.value);
+ // Handle the none redirect (no data allowed) in the switch construct
+ // if/when the respective syntax is invented.
+ //
redirect_type rt (redirect_type::none);
switch (tt)
{
@@ -487,19 +502,30 @@ namespace build2
case type::out_file_app: rt = redirect_type::file; break;
}
- redirect& r (fd == 0 ? c.in : fd == 1 ? c.out : c.err);
- redirect_type overriden (r.type);
+ optional<redirect>& r (fd == 0 ? c.in :
+ fd == 1 ? c.out :
+ c.err);
+
+ optional<redirect_type> overriden;
+
+ if (r)
+ overriden = r->type;
r = redirect (rt);
// Don't move as still may be used for pending here-document end
// marker processing.
//
- r.modifiers = mod;
+ r->modifiers = mod;
switch (rt)
{
case redirect_type::none:
+ // Remove the assertion if/when the none redirect syntax is
+ // invented.
+ //
+ assert (false);
+ // Fall through.
case redirect_type::pass:
case redirect_type::null:
case redirect_type::trace:
@@ -554,11 +580,9 @@ namespace build2
// Also sets for stdin, but this is harmless.
//
- r.file.mode = tt == type::out_file_ovr
- ? redirect_fmode::overwrite
- : (tt == type::out_file_app
- ? redirect_fmode::append
- : redirect_fmode::compare);
+ r->file.mode = tt == type::out_file_ovr ? redirect_fmode::overwrite :
+ tt == type::out_file_app ? redirect_fmode::append :
+ redirect_fmode::compare;
break;
@@ -569,8 +593,9 @@ namespace build2
// to this command redirect from the corresponding here_doc object.
//
if (!pre_parse_ &&
- (overriden == redirect_type::here_doc_literal ||
- overriden == redirect_type::here_doc_regex))
+ overriden &&
+ (*overriden == redirect_type::here_doc_literal ||
+ *overriden == redirect_type::here_doc_regex))
{
size_t e (expr.size () - 1);
size_t p (expr.back ().pipe.size ());
@@ -1251,25 +1276,30 @@ namespace build2
auto i (h.redirects.cbegin ());
command& c (p.first[i->expr].pipe[i->pipe]);
- redirect& r (i->fd == 0 ? c.in : i->fd == 1 ? c.out : c.err);
+
+ optional<redirect>& r (i->fd == 0 ? c.in :
+ i->fd == 1 ? c.out :
+ c.err);
+
+ assert (r); // Must be present since it is referred.
if (v.re)
{
- assert (r.type == redirect_type::here_doc_regex);
+ assert (r->type == redirect_type::here_doc_regex);
- r.regex = move (v.regex);
- r.regex.flags = move (h.regex_flags);
+ r->regex = move (v.regex);
+ r->regex.flags = move (h.regex_flags);
}
else
{
- assert (r.type == redirect_type::here_doc_literal);
+ assert (r->type == redirect_type::here_doc_literal);
- r.str = move (v.str);
+ r->str = move (v.str);
}
- r.end = move (h.end);
- r.end_line = v.end_line;
- r.end_column = v.end_column;
+ r->end = move (h.end);
+ r->end_line = v.end_line;
+ r->end_column = v.end_column;
// Note that our references cannot be invalidated because the
// command_expr/command-pipe vectors already contain all their
@@ -1280,7 +1310,7 @@ namespace build2
command& c (p.first[i->expr].pipe[i->pipe]);
(i->fd == 0 ? c.in : i->fd == 1 ? c.out : c.err) =
- redirect (redirect_type::here_doc_ref, r);
+ redirect (redirect_type::here_doc_ref, *r);
}
}