diff options
author | Karen Arutyunov <karen@codesynthesis.com> | 2020-05-22 15:32:31 +0300 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2020-05-27 08:38:57 +0200 |
commit | b0b048c03930b826ab3dbf88b56fd664fca26886 (patch) | |
tree | d6e5e89fb40a31136f6d3e870e59c23f14b70631 /libbuild2/script/lexer.cxx | |
parent | b27f36b7af5186ad66fd1afa6e7fdc742f2aa1bd (diff) |
Add script command redirect aliases
Diffstat (limited to 'libbuild2/script/lexer.cxx')
-rw-r--r-- | libbuild2/script/lexer.cxx | 162 |
1 files changed, 127 insertions, 35 deletions
diff --git a/libbuild2/script/lexer.cxx b/libbuild2/script/lexer.cxx index fff9307..d78e999 100644 --- a/libbuild2/script/lexer.cxx +++ b/libbuild2/script/lexer.cxx @@ -165,7 +165,7 @@ namespace build2 // if (m == lexer_mode::command_expansion) { - if (optional<token> t = next_cmd_op (c, sep, m)) + if (optional<token> t = next_cmd_op (c, sep)) return move (*t); } @@ -176,14 +176,12 @@ namespace build2 } optional<token> lexer:: - next_cmd_op (const xchar& c, bool sep, lexer_mode m) + next_cmd_op (const xchar& c, bool sep) { - auto make_token = [&sep, &m, &c] (type t, string v = string ()) + auto make_token = [&sep, &c] (type t, string v = string ()) { - bool q (m == lexer_mode::here_line_double); - return token (t, move (v), sep, - (q ? quote_type::double_ : quote_type::unquoted), q, + quote_type::unquoted, false, c.line, c.column, token_printer); }; @@ -247,89 +245,183 @@ namespace build2 // case '<': { - type r (type::in_str); + optional<type> r; xchar p (peek ()); - if (p == '|' || p == '-' || p == '<') + if (p == '|' || p == '-' || p == '=' || p == '<') // <| <- <= << { - get (); + xchar c (get ()); switch (p) { - case '|': return make_token (type::in_pass); - case '-': return make_token (type::in_null); - case '<': + case '|': return make_token (type::in_pass); // <| + case '-': return make_token (type::in_null); // <- + case '=': return make_token (type::in_file); // <= + case '<': // << { - r = type::in_doc; p = peek (); - if (p == '<') + if (p == '=' || p == '<') // <<= <<< { - get (); - r = type::in_file; + xchar c (get ()); + + switch (p) + { + case '=': + { + r = type::in_doc; // <<= + break; + } + case '<': + { + p = peek (); + + if (p == '=') + { + get (); + r = type::in_str; // <<<= + } + + if (!r && redirect_aliases.lll) + r = type::in_lll; // <<< + + // We can still end up with the << or < redirect alias, + // if any of them is present. + // + if (!r) + unget (c); + } + + break; + } } + + if (!r && redirect_aliases.ll) + r = type::in_ll; // << + + // We can still end up with the < redirect alias, if it is + // present. + // + if (!r) + unget (c); + break; } } } + if (!r && redirect_aliases.l) + r = type::in_l; // < + + if (!r) + return nullopt; + // Handle modifiers. // const char* mods (nullptr); - switch (r) + + switch (redirect_aliases.resolve (*r)) { case type::in_str: case type::in_doc: mods = ":/"; break; } - return make_token_with_modifiers (r, mods); + token t (make_token_with_modifiers (*r, mods)); + + return t; } // > // case '>': { - type r (type::out_str); + optional<type> r; xchar p (peek ()); - if (p == '|' || p == '-' || p == '!' || p == '&' || - p == '=' || p == '+' || p == '>') + if (p == '|' || p == '-' || p == '!' || p == '&' || // >| >- >! >& + p == '=' || p == '+' || p == '?' || p == '>') // >= >+ >? >> { - get (); + xchar c (get ()); switch (p) { - case '|': return make_token (type::out_pass); - case '-': return make_token (type::out_null); - case '!': return make_token (type::out_trace); - case '&': return make_token (type::out_merge); - case '=': return make_token (type::out_file_ovr); - case '+': return make_token (type::out_file_app); - case '>': + case '|': return make_token (type::out_pass); // >| + case '-': return make_token (type::out_null); // >- + case '!': return make_token (type::out_trace); // >! + case '&': return make_token (type::out_merge); // >& + case '=': return make_token (type::out_file_ovr); // >= + case '+': return make_token (type::out_file_app); // >+ + case '?': return make_token (type::out_file_cmp); // >? + case '>': // >> { - r = type::out_doc; p = peek (); - if (p == '>') + if (p == '?' || p == '>') // >>? >>> { - get (); - r = type::out_file_cmp; + xchar c (get ()); + + switch (p) + { + case '?': + { + r = type::out_doc; // >>? + break; + } + case '>': + { + p = peek (); + + if (p == '?') + { + get (); + r = type::out_str; // >>>? + } + + if (!r && redirect_aliases.ggg) + r = type::out_ggg; // >>> + + // We can still end up with the >> or > redirect alias, + // if any of themis present. + // + if (!r) + unget (c); + } + + break; + } } + + if (!r && redirect_aliases.gg) + r = type::out_gg; // >> + + // We can still end up with the > redirect alias, if it is + // present. + // + if (!r) + unget (c); + break; } } } + if (!r && redirect_aliases.g) + r = type::out_g; // > + + if (!r) + return nullopt; + // Handle modifiers. // const char* mods (nullptr); const char* stop (nullptr); - switch (r) + + switch (redirect_aliases.resolve (*r)) { case type::out_str: case type::out_doc: mods = ":/~"; stop = "~"; break; } - return make_token_with_modifiers (r, mods, stop); + return make_token_with_modifiers (*r, mods, stop); } } |