From 861555876837449fd8fc480845f642dab4a68b1e Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Tue, 12 Nov 2019 15:59:58 +0300 Subject: Use path_name in cc::lexer class --- libbuild2/cc/compile-rule.cxx | 2 +- libbuild2/cc/lexer+char-literal.test.testscript | 2 +- libbuild2/cc/lexer+comment.test.testscript | 2 +- libbuild2/cc/lexer+preprocessor.test.testscript | 4 +- .../cc/lexer+raw-string-literal.test.testscript | 10 +-- libbuild2/cc/lexer+string-literal.test.testscript | 2 +- libbuild2/cc/lexer.cxx | 73 +++++++++++++++------- libbuild2/cc/lexer.hxx | 23 ++++--- libbuild2/cc/lexer.test.cxx | 17 +++-- libbuild2/cc/parser+module.test.testscript | 14 ++--- libbuild2/cc/parser.cxx | 4 +- libbuild2/cc/parser.hxx | 2 +- libbuild2/cc/parser.test.cxx | 12 ++-- libbuild2/test/script/parser.cxx | 2 +- libbuild2/test/script/script.hxx | 14 ++++- 15 files changed, 119 insertions(+), 64 deletions(-) diff --git a/libbuild2/cc/compile-rule.cxx b/libbuild2/cc/compile-rule.cxx index 98b78e1..f3b2c0d 100644 --- a/libbuild2/cc/compile-rule.cxx +++ b/libbuild2/cc/compile-rule.cxx @@ -4218,7 +4218,7 @@ namespace build2 fdstream_mode::binary | fdstream_mode::skip); parser p; - unit tu (p.parse (is, *sp)); + unit tu (p.parse (is, path_name (*sp))); is.close (); diff --git a/libbuild2/cc/lexer+char-literal.test.testscript b/libbuild2/cc/lexer+char-literal.test.testscript index afd16dd..e7a44d9 100644 --- a/libbuild2/cc/lexer+char-literal.test.testscript +++ b/libbuild2/cc/lexer+char-literal.test.testscript @@ -63,5 +63,5 @@ EOO : unterminated : $* <"'a" 2>>EOE != 0 -stdin:1:1: error: unterminated character literal +:1:1: error: unterminated character literal EOE diff --git a/libbuild2/cc/lexer+comment.test.testscript b/libbuild2/cc/lexer+comment.test.testscript index bfcc440..5c29af0 100644 --- a/libbuild2/cc/lexer+comment.test.testscript +++ b/libbuild2/cc/lexer+comment.test.testscript @@ -41,7 +41,7 @@ $* <>EOE != 0 /* comment EOI -stdin:1:2: error: unterminated comment +:1:2: error: unterminated comment EOE : cxx-unterminated diff --git a/libbuild2/cc/lexer+preprocessor.test.testscript b/libbuild2/cc/lexer+preprocessor.test.testscript index e33eb90..3403588 100644 --- a/libbuild2/cc/lexer+preprocessor.test.testscript +++ b/libbuild2/cc/lexer+preprocessor.test.testscript @@ -46,7 +46,7 @@ $* -l <>EOO # 5 "test.cxx" ; EOI -';' stdin:1:1 +';' :1:1 ';' test.cxx:1:1 ';' test.cxx:2:3 ';' test.cxx:4:1 @@ -60,7 +60,7 @@ EOO $* <>EOE != 0 #include EOI -stdin:1:1: error: unexpected #include directive +:1:1: error: unexpected #include directive EOE : nested diff --git a/libbuild2/cc/lexer+raw-string-literal.test.testscript b/libbuild2/cc/lexer+raw-string-literal.test.testscript index 93cddc1..beab7b4 100644 --- a/libbuild2/cc/lexer+raw-string-literal.test.testscript +++ b/libbuild2/cc/lexer+raw-string-literal.test.testscript @@ -62,29 +62,29 @@ EOO : invalid-no-paren : $* <'R"a"' 2>>EOE != 0 -stdin:1:2: error: invalid raw string literal +:1:2: error: invalid raw string literal EOE : invalid-paren : $* <'R")()("' 2>>EOE != 0 -stdin:1:2: error: invalid raw string literal +:1:2: error: invalid raw string literal EOE : invalid-unterminated-paren : $* <'R"(abc"' 2>>EOE != 0 -stdin:1:2: error: invalid raw string literal +:1:2: error: invalid raw string literal EOE : invalid-unterminated-delimiter : $* <'R"X(abc)"' 2>>EOE != 0 -stdin:1:2: error: invalid raw string literal +:1:2: error: invalid raw string literal EOE : invalid-unterminated-quote : $* <'R"X(abc)X' 2>>EOE != 0 -stdin:1:2: error: invalid raw string literal +:1:2: error: invalid raw string literal EOE diff --git a/libbuild2/cc/lexer+string-literal.test.testscript b/libbuild2/cc/lexer+string-literal.test.testscript index a2509c9..22ddff8 100644 --- a/libbuild2/cc/lexer+string-literal.test.testscript +++ b/libbuild2/cc/lexer+string-literal.test.testscript @@ -61,5 +61,5 @@ EOO : unterminated : $* <'"ab' 2>>EOE != 0 -stdin:1:1: error: unterminated string literal +:1:1: error: unterminated string literal EOE diff --git a/libbuild2/cc/lexer.cxx b/libbuild2/cc/lexer.cxx index 6eba57e..540e48c 100644 --- a/libbuild2/cc/lexer.cxx +++ b/libbuild2/cc/lexer.cxx @@ -38,7 +38,7 @@ namespace butl // ADL using namespace build2; assert (data != nullptr); // E.g., must be &lexer::name_. - return location (static_cast (data), c.line, c.column); + return location (*static_cast (data), c.line, c.column); } } @@ -146,7 +146,7 @@ namespace build2 { for (;; c = skip_spaces ()) { - t.file = log_file_; + t.file = &log_file_; t.line = log_line_ ? *log_line_ : c.line; t.column = c.column; @@ -156,7 +156,7 @@ namespace build2 return; } - const location l (&name_, c.line, c.column); + const location l (name_, c.line, c.column); // Hash the token's line. The reason is debug info. In fact, doing // this will make quite a few "noop" changes (like adding a newline @@ -646,7 +646,7 @@ namespace build2 { // note: c is hashed - const location l (&name_, c.line, c.column); + const location l (name_, c.line, c.column); for (char p (c);;) // Previous character (see below). { @@ -677,7 +677,7 @@ namespace build2 { // note: c is hashed - const location l (&name_, c.line, c.column); + const location l (name_, c.line, c.column); for (char p (c);;) // Previous character (see below). { @@ -736,7 +736,7 @@ namespace build2 // Note that the are not processed in any way, not even // for line continuations. // - const location l (&name_, c.line, c.column); + const location l (name_, c.line, c.column); // As a first step, parse the delimiter (including the openning paren). // @@ -830,7 +830,7 @@ namespace build2 if (c == '\"') { - const location l (&name_, c.line, c.column); + const location l (name_, c.line, c.column); // It is common to have a large number of #line directives that don't // change the file (they seem to be used to track macro locations or @@ -895,15 +895,42 @@ namespace build2 } } - if (log_file_.string () == s) - return; + try + { + if (s.empty ()) + throw invalid_path (""); - // Swap the two string buffers. - // + // Handle special names (, , etc). + // + if (s.front () == '<' && s.back () == '>') + { + if (log_file_.name) + { + if (*log_file_.name == s) + return; + + log_file_.name->swap (s); + } + else + log_file_.name = move (s); + + log_file_.path.clear (); + } + else + { + if (log_file_.path.string () == s) + return; + + string r (move (log_file_.path).string ()); // Move string rep out. + r.swap (s); + log_file_.path = path (move (r)); // Move back in. + + log_file_.name = nullopt; + } + } + catch (const invalid_path&) { - string r (move (log_file_).string ()); // Move string rep out. - r.swap (s); - log_file_ = path (move (r)); // Move back in. + fail (l) << "invalid path in #line directive"; } // If the path is relative, then prefix it with the current working @@ -926,17 +953,19 @@ namespace build2 // the part starting from the project root which is immutable. Plus // we will need -ffile-prefix-map to deal with __FILE__. // - if (!log_file_.to_directory ()) - cs_.append (log_file_.string ()); + if (!log_file_.path.to_directory ()) // Also covers special names. + cs_.append (log_file_.name + ? *log_file_.name + : log_file_.path.string ()); #if 0 { - using tr = path::traits; - const string& f (log_file_.string ()); + using tr = path::traits_type; + const string& f (log_file_.path.string ()); - if (f.find (':') != string::npos || - (f.front () == '<' && f.back () == '>') || - log_file_.absolute ()) - cs_.append (f); + if (log_file_.name || + f.find (':') != string::npos || + log_file_.path.absolute ()) + cs_.append (log_file_.name ? *log_file_.name : f); else { // This gets complicated and slow: the path may contain '..' and diff --git a/libbuild2/cc/lexer.hxx b/libbuild2/cc/lexer.hxx index cb2b3a5..c7da135 100644 --- a/libbuild2/cc/lexer.hxx +++ b/libbuild2/cc/lexer.hxx @@ -63,9 +63,12 @@ namespace build2 // Logical position. // - path file; - uint64_t line = 0; - uint64_t column = 0; + // Note that file is a shallow pointer to the state maintained by the + // lexer. + // + const path_name* file = nullptr; + uint64_t line = 0; + uint64_t column = 0; // Physical position in the stream, currently only for identifiers. // @@ -80,13 +83,15 @@ namespace build2 class lexer: protected butl::char_scanner { public: - lexer (ifdstream& is, const path& name) + lexer (ifdstream& is, const path_name& name) : char_scanner (is, false), name_ (name), fail ("error", &name_), - log_file_ (name) {} + log_file_ (name) + { + } - const path& + const path_name& name () const {return name_;} string @@ -164,13 +169,13 @@ namespace build2 geth (const xchar& peeked); private: - const path name_; + const path_name& name_; const fail_mark fail; // Logical file and line as set by the #line directives. Note that the // lexer diagnostics still uses the physical file/lines. // - path log_file_; + path_name_value log_file_; optional log_line_; string tmp_file_; @@ -182,7 +187,7 @@ namespace build2 inline location get_location (const token& t, const void* = nullptr) { - return location (&t.file, t.line, t.column); + return location (*t.file, t.line, t.column); } } } diff --git a/libbuild2/cc/lexer.test.cxx b/libbuild2/cc/lexer.test.cxx index 0aeadba..68bb152 100644 --- a/libbuild2/cc/lexer.test.cxx +++ b/libbuild2/cc/lexer.test.cxx @@ -23,7 +23,7 @@ namespace build2 main (int argc, char* argv[]) { bool loc (false); - const char* file (nullptr); + path file; for (int i (1); i != argc; ++i) { @@ -33,23 +33,28 @@ namespace build2 loc = true; else { - file = argv[i]; + file = path (argv[i]); break; } } try { + path_name in; ifdstream is; - if (file != nullptr) + + if (!file.empty ()) + { + in = path_name (file); is.open (file); + } else { - file = "stdin"; + in = path_name (""); is.open (fddup (stdin_fd ())); } - lexer l (is, path (file)); + lexer l (is, in); // No use printing eos since we will either get it or loop forever. // @@ -58,7 +63,7 @@ namespace build2 cout << t; if (loc) - cout << ' ' << t.file << ':' << t.line << ':' << t.column; + cout << ' ' << *t.file << ':' << t.line << ':' << t.column; cout << endl; } diff --git a/libbuild2/cc/parser+module.test.testscript b/libbuild2/cc/parser+module.test.testscript index d51ac0a..e935180 100644 --- a/libbuild2/cc/parser+module.test.testscript +++ b/libbuild2/cc/parser+module.test.testscript @@ -89,7 +89,7 @@ export module foo; } EOI -stdin:8:1: error: {}-imbalance detected +:8:1: error: {}-imbalance detected EOE : brace-stray @@ -103,7 +103,7 @@ export } module foo; EOI -stdin:6:1: error: {}-imbalance detected +:6:1: error: {}-imbalance detected EOE : import-missing-name @@ -111,7 +111,7 @@ EOE $* <>EOE != 0 import ; EOI -stdin:1:8: error: module or header name expected instead of ';' +:1:8: error: module or header name expected instead of ';' EOE : module-missing-name @@ -119,7 +119,7 @@ EOE $* <>EOE != 0 module ; EOI -stdin:1:1: error: module declaration expected after leading module marker +:1:1: error: module declaration expected after leading module marker EOE : import-missing-semi @@ -127,7 +127,7 @@ EOE $* <>EOE != 0 import foo EOI -stdin:2:1: error: ';' expected instead of +:2:1: error: ';' expected instead of EOE : module-missing-semi @@ -135,7 +135,7 @@ EOE $* <>EOE != 0 export module foo EOI -stdin:2:1: error: ';' expected instead of +:2:1: error: ';' expected instead of EOE : import-missing-header @@ -143,5 +143,5 @@ EOE $* <>EOE != 0 import ' expected after header name +:2:1: error: closing '>' expected after header name EOE diff --git a/libbuild2/cc/parser.cxx b/libbuild2/cc/parser.cxx index 179043e..abfe5bd 100644 --- a/libbuild2/cc/parser.cxx +++ b/libbuild2/cc/parser.cxx @@ -16,9 +16,9 @@ namespace build2 using type = token_type; unit parser:: - parse (ifdstream& is, const path& name) + parse (ifdstream& is, const path_name& in) { - lexer l (is, name); + lexer l (is, in); l_ = &l; unit u; diff --git a/libbuild2/cc/parser.hxx b/libbuild2/cc/parser.hxx index 324b62a..cc2eaa3 100644 --- a/libbuild2/cc/parser.hxx +++ b/libbuild2/cc/parser.hxx @@ -25,7 +25,7 @@ namespace build2 { public: unit - parse (ifdstream&, const path& name); + parse (ifdstream&, const path_name&); private: void diff --git a/libbuild2/cc/parser.test.cxx b/libbuild2/cc/parser.test.cxx index 82c68d1..9d90653 100644 --- a/libbuild2/cc/parser.test.cxx +++ b/libbuild2/cc/parser.test.cxx @@ -24,22 +24,26 @@ namespace build2 { try { - const char* file; + path file; + path_name in; ifdstream is; + if (argc > 1) { - file = argv[1]; + file = path (argv[1]); + + in = path_name (file); is.open (file); } else { - file = "stdin"; + in = path_name (""); is.open (fddup (stdin_fd ())); } parser p; - unit u (p.parse (is, path (file))); + unit u (p.parse (is, in)); unit_type ut (u.type); for (const module_import& m: u.module_info.imports) diff --git a/libbuild2/test/script/parser.cxx b/libbuild2/test/script/parser.cxx index 376d68f..f3f6ffa 100644 --- a/libbuild2/test/script/parser.cxx +++ b/libbuild2/test/script/parser.cxx @@ -1028,7 +1028,7 @@ namespace build2 }; const path_name_value& pn (enter_path (move (n))); - const path& p (*pn.path); + const path& p (pn.path); if (include_set_->insert (p).second || !once) { diff --git a/libbuild2/test/script/script.hxx b/libbuild2/test/script/script.hxx index f4ef32a..73fd696 100644 --- a/libbuild2/test/script/script.hxx +++ b/libbuild2/test/script/script.hxx @@ -548,7 +548,19 @@ namespace build2 // Testscript file paths. Specifically, replay_token::file points to // these path names. // - std::set paths_; + struct compare_paths + { + bool operator() (const path_name_value& x, + const path_name_value& y) const + { + // Note that these path names are always paths, so we compare them + // as paths. + // + return x.path < y.path; + } + }; + + std::set paths_; }; } } -- cgit v1.1