aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2020-05-18 12:06:16 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2020-05-18 12:06:16 +0300
commitdfb1415d5eaf006ee45235f275d17f52d3db38e5 (patch)
treebc617819ce3ecee2687252b82c9fb664d76b630b
parent96908ec43ed27d9f34da27b6a94a6db357465056 (diff)
Add dump(ostream,script::lines) (partial implementation)build-script
-rw-r--r--libbuild2/build/script/lexer.test.cxx2
-rw-r--r--libbuild2/build/script/parser+line.test.testscript39
-rw-r--r--libbuild2/build/script/parser.test.cxx21
-rw-r--r--libbuild2/build/script/token.cxx4
-rw-r--r--libbuild2/build/script/token.hxx2
-rw-r--r--libbuild2/lexer.test.cxx2
-rw-r--r--libbuild2/script/lexer.test.cxx2
-rw-r--r--libbuild2/script/script.cxx68
-rw-r--r--libbuild2/script/script.hxx3
-rw-r--r--libbuild2/script/token.cxx6
-rw-r--r--libbuild2/script/token.hxx2
-rw-r--r--libbuild2/test/script/lexer.test.cxx2
-rw-r--r--libbuild2/test/script/token.cxx6
-rw-r--r--libbuild2/test/script/token.hxx2
-rw-r--r--libbuild2/token.cxx39
-rw-r--r--libbuild2/token.hxx27
16 files changed, 199 insertions, 28 deletions
diff --git a/libbuild2/build/script/lexer.test.cxx b/libbuild2/build/script/lexer.test.cxx
index 15c0954..1c47442 100644
--- a/libbuild2/build/script/lexer.test.cxx
+++ b/libbuild2/build/script/lexer.test.cxx
@@ -55,7 +55,7 @@ namespace build2
{
// Print each token on a separate line without quoting operators.
//
- t.printer (cout, t, false);
+ t.printer (cout, t, print_mode::normal);
cout << endl;
}
}
diff --git a/libbuild2/build/script/parser+line.test.testscript b/libbuild2/build/script/parser+line.test.testscript
new file mode 100644
index 0000000..df4e77b
--- /dev/null
+++ b/libbuild2/build/script/parser+line.test.testscript
@@ -0,0 +1,39 @@
+# file : libbuild2/build/script/parser+line.test.testscript
+# license : MIT; see accompanying LICENSE file
+
+test.options += -d
+
+#\
+: if-else
+:
+$* <<EOI >|
+ if foo
+ bar
+ elif fox
+ baz
+ end
+ if! foo
+ bar
+ elif! fox
+ baz
+ end
+ EOI
+
+: command
+:
+$* <<EOI >|
+ foo >| 2>- &a &?b
+ foo >=c 2>~/error:.*/ &!c
+ foo >>:/~%EOF%
+ %.*
+ abc
+ %xyz.*%
+ EOF
+ EOI
+
+: quoting
+:
+$* <<EOI >|
+ foo 'bar' "baz" '' ""
+ EOI
+#\
diff --git a/libbuild2/build/script/parser.test.cxx b/libbuild2/build/script/parser.test.cxx
index 2763464..77f6596 100644
--- a/libbuild2/build/script/parser.test.cxx
+++ b/libbuild2/build/script/parser.test.cxx
@@ -67,7 +67,10 @@ namespace build2
bool line_;
};
- // Usage: argv[0] [-l]
+ // Usages:
+ //
+ // argv[0] [-l]
+ // argv[0] -d
//
int
main (int argc, char* argv[])
@@ -86,6 +89,7 @@ namespace build2
context ctx (sched, mutexes);
bool line (false);
+ bool dump (false);
for (int i (1); i != argc; ++i)
{
@@ -93,10 +97,14 @@ namespace build2
if (a == "-l")
line = true;
+ else if (a == "-d")
+ dump = true;
else
assert (false);
}
+ assert (!dump || !line);
+
try
{
cin.exceptions (istream::failbit | istream::badbit);
@@ -123,9 +131,14 @@ namespace build2
parser p (ctx);
p.pre_parse (cin, nm, 11 /* line */, s);
- environment e (s, tt);
- print_runner r (line);
- p.execute (e, r);
+ if (!dump)
+ {
+ environment e (s, tt);
+ print_runner r (line);
+ p.execute (e, r);
+ }
+ else
+ build2::script::dump (cout, "", s.lines);
}
catch (const failed&)
{
diff --git a/libbuild2/build/script/token.cxx b/libbuild2/build/script/token.cxx
index 289dfd2..7c15dff 100644
--- a/libbuild2/build/script/token.cxx
+++ b/libbuild2/build/script/token.cxx
@@ -12,11 +12,11 @@ namespace build2
namespace script
{
void
- token_printer (ostream& os, const token& t, bool d)
+ token_printer (ostream& os, const token& t, print_mode m)
{
// No build script-specific tokens so far.
//
- build2::script::token_printer (os, t, d);
+ build2::script::token_printer (os, t, m);
}
}
}
diff --git a/libbuild2/build/script/token.hxx b/libbuild2/build/script/token.hxx
index 4cd90d7..90c1379 100644
--- a/libbuild2/build/script/token.hxx
+++ b/libbuild2/build/script/token.hxx
@@ -28,7 +28,7 @@ namespace build2
};
void
- token_printer (ostream&, const token&, bool);
+ token_printer (ostream&, const token&, print_mode);
}
}
}
diff --git a/libbuild2/lexer.test.cxx b/libbuild2/lexer.test.cxx
index 5e39e43..443622c 100644
--- a/libbuild2/lexer.test.cxx
+++ b/libbuild2/lexer.test.cxx
@@ -62,7 +62,7 @@ namespace build2
// Print each token on a separate line without quoting operators.
//
- t.printer (cout, t, false);
+ t.printer (cout, t, print_mode::normal);
if (quote)
{
diff --git a/libbuild2/script/lexer.test.cxx b/libbuild2/script/lexer.test.cxx
index 85304ea..24fe335 100644
--- a/libbuild2/script/lexer.test.cxx
+++ b/libbuild2/script/lexer.test.cxx
@@ -45,7 +45,7 @@ namespace build2
{
// Print each token on a separate line without quoting operators.
//
- t.printer (cout, t, false);
+ t.printer (cout, t, print_mode::normal);
cout << endl;
}
}
diff --git a/libbuild2/script/script.cxx b/libbuild2/script/script.cxx
index b5456f9..db34084 100644
--- a/libbuild2/script/script.cxx
+++ b/libbuild2/script/script.cxx
@@ -33,6 +33,74 @@ namespace build2
return o << s;
}
+ void
+ dump (ostream& os, const string& ind, const lines& ls)
+ {
+ for (const line& l: ls)
+ {
+ os << ind;
+
+ // @@ Should be across lines?
+ //
+ // We will consider mixed quoting as a double quoting since the
+ // information is lost and we won't be able to restore the token
+ // original representation.
+ //
+// char qseq ('\0'); // Can be used as bool.
+
+ for (const replay_token& rt: l.tokens)
+ {
+ const token& t (rt.token);
+
+ // Left and right quotes (can be used as bool).
+ //
+ char lq ('\0');
+ char rq ('\0');
+
+ /*
+ if (t.qtype != quote_type::unquoted)
+ {
+ auto quote = [&t] ()
+ {
+ return t.qtype == quote_type::single ? '\'' : '"';
+ }
+
+ if (t.qcomp) // Complete quoting.
+ {
+ // If we are inside quoted token sequence then we do noting.
+ // Otherwise we just quote the token not starting a sequence.
+ //
+ if (!qseq)
+ {
+ lq = quote ();
+ rq = lq;
+ }
+ }
+ else // Partial quoting.
+ {
+ if (!qseq)
+ lq =
+
+ }
+ }
+ */
+ // @@ Add 2 spaces indentation for if block contents.
+
+ if (t.separated &&
+ t.type != token_type::newline &&
+ &rt != &l.tokens[0]) // Not first in the line.
+ os << ' ';
+
+ if (lq) os << lq;
+ t.printer (os, t, print_mode::raw);
+ if (rq) os << rq;
+
+// prev_qcomp = t.qcomp;
+// prev_qtype = t.qtype;
+ }
+ }
+ }
+
// Quote if empty or contains spaces or any of the special characters.
// Note that we use single quotes since double quotes still allow
// expansion.
diff --git a/libbuild2/script/script.hxx b/libbuild2/script/script.hxx
index 96c1343..f02583c 100644
--- a/libbuild2/script/script.hxx
+++ b/libbuild2/script/script.hxx
@@ -48,6 +48,9 @@ namespace build2
//
using lines = small_vector<line, 1>;
+ void
+ dump (ostream&, const string& ind, const lines&);
+
// Parse object model.
//
diff --git a/libbuild2/script/token.cxx b/libbuild2/script/token.cxx
index be0aa54..6c9de87 100644
--- a/libbuild2/script/token.cxx
+++ b/libbuild2/script/token.cxx
@@ -10,13 +10,13 @@ namespace build2
namespace script
{
void
- token_printer (ostream& os, const token& t, bool d)
+ token_printer (ostream& os, const token& t, print_mode m)
{
const string& v (t.value);
// Only quote non-name tokens for diagnostics.
//
- const char* q (d ? "'" : "");
+ const char* q (m == print_mode::diagnostics ? "'" : "");
switch (t.type)
{
@@ -39,7 +39,7 @@ namespace build2
case token_type::out_file_ovr: os << q << ">=" << v << q; break;
case token_type::out_file_app: os << q << ">+" << v << q; break;
- default: build2::token_printer (os, t, d);
+ default: build2::token_printer (os, t, m);
}
}
}
diff --git a/libbuild2/script/token.hxx b/libbuild2/script/token.hxx
index 0630e46..a2ccaee 100644
--- a/libbuild2/script/token.hxx
+++ b/libbuild2/script/token.hxx
@@ -49,7 +49,7 @@ namespace build2
};
void
- token_printer (ostream&, const token&, bool);
+ token_printer (ostream&, const token&, print_mode);
}
}
diff --git a/libbuild2/test/script/lexer.test.cxx b/libbuild2/test/script/lexer.test.cxx
index c728d68..9c64616 100644
--- a/libbuild2/test/script/lexer.test.cxx
+++ b/libbuild2/test/script/lexer.test.cxx
@@ -56,7 +56,7 @@ namespace build2
{
// Print each token on a separate line without quoting operators.
//
- t.printer (cout, t, false);
+ t.printer (cout, t, print_mode::normal);
cout << endl;
}
}
diff --git a/libbuild2/test/script/token.cxx b/libbuild2/test/script/token.cxx
index df5493f..efeb17b 100644
--- a/libbuild2/test/script/token.cxx
+++ b/libbuild2/test/script/token.cxx
@@ -12,11 +12,11 @@ namespace build2
namespace script
{
void
- token_printer (ostream& os, const token& t, bool d)
+ token_printer (ostream& os, const token& t, print_mode m)
{
// Only quote non-name tokens for diagnostics.
//
- const char* q (d ? "'" : "");
+ const char* q (m == print_mode::diagnostics ? "'" : "");
switch (t.type)
{
@@ -27,7 +27,7 @@ namespace build2
case token_type::plus: os << q << '+' << q; break;
case token_type::minus: os << q << '-' << q; break;
- default: build2::script::token_printer (os, t, d);
+ default: build2::script::token_printer (os, t, m);
}
}
}
diff --git a/libbuild2/test/script/token.hxx b/libbuild2/test/script/token.hxx
index 5bb2319..dead796 100644
--- a/libbuild2/test/script/token.hxx
+++ b/libbuild2/test/script/token.hxx
@@ -37,7 +37,7 @@ namespace build2
};
void
- token_printer (ostream&, const token&, bool);
+ token_printer (ostream&, const token&, print_mode);
}
}
}
diff --git a/libbuild2/token.cxx b/libbuild2/token.cxx
index 4975a02..ebbdd83 100644
--- a/libbuild2/token.cxx
+++ b/libbuild2/token.cxx
@@ -8,18 +8,45 @@ using namespace std;
namespace build2
{
void
- token_printer (ostream& os, const token& t, bool d)
+ token_printer (ostream& os, const token& t, print_mode m)
{
// Only quote non-name tokens for diagnostics.
//
- const char* q (d ? "'" : "");
+ const char* q (m == print_mode::diagnostics ? "'" : "");
+ bool r (m == print_mode::raw);
switch (t.type)
{
- case token_type::eos: os << "<end of file>"; break;
- case token_type::newline: os << "<newline>"; break;
- case token_type::pair_separator: os << "<pair separator " << t.value[0] << ">"; break;
- case token_type::word: os << '\'' << t.value << '\''; break;
+ case token_type::eos:
+ {
+ if (!r)
+ os <<"<end of file>";
+
+ break;
+ }
+ case token_type::newline:
+ {
+ os << (r ? "\n" : "<newline>");
+ break;
+ }
+ case token_type::pair_separator:
+ {
+ if (r)
+ os << t.value[0];
+ else
+ os << "<pair separator " << t.value[0] << ">";
+
+ break;
+ }
+ case token_type::word:
+ {
+ if (r)
+ os << t.value;
+ else
+ os << '\'' << t.value << '\'';
+
+ break;
+ }
case token_type::colon: os << q << ':' << q; break;
case token_type::dollar: os << q << '$' << q; break;
diff --git a/libbuild2/token.hxx b/libbuild2/token.hxx
index c950ea3..c486193 100644
--- a/libbuild2/token.hxx
+++ b/libbuild2/token.hxx
@@ -84,13 +84,30 @@ namespace build2
class token;
+ enum class print_mode
+ {
+ // Print eos, newline, and pair separator in the <name> form and other
+ // tokens as literals, single-quoting the word token.
+ //
+ normal,
+
+ // Same as normal but all literals are quoted.
+ //
+ diagnostics,
+
+ // Print all tokens as literals with newline represented as '\n' and eos
+ // as an empty string.
+ //
+ raw
+ };
+
LIBBUILD2_SYMEXPORT void
- token_printer (ostream&, const token&, bool);
+ token_printer (ostream&, const token&, print_mode);
class token
{
public:
- using printer_type = void (ostream&, const token&, bool diag);
+ using printer_type = void (ostream&, const token&, print_mode);
token_type type;
bool separated; // Whitespace-separated from the previous token.
@@ -145,7 +162,11 @@ namespace build2
// Output the token value in a format suitable for diagnostics.
//
inline ostream&
- operator<< (ostream& o, const token& t) {t.printer (o, t, true); return o;}
+ operator<< (ostream& o, const token& t)
+ {
+ t.printer (o, t, print_mode::diagnostics);
+ return o;
+ }
// Context-dependent lexing (see lexer_mode for details).
//