aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2019-11-12 15:59:58 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2019-11-13 17:30:25 +0300
commit861555876837449fd8fc480845f642dab4a68b1e (patch)
tree737992e719b5b5bee5574d3cba18e21b2ecbd912
parent1dc4b29bb57b14bfd8f700be80224b6d865f0184 (diff)
Use path_name in cc::lexer class
-rw-r--r--libbuild2/cc/compile-rule.cxx2
-rw-r--r--libbuild2/cc/lexer+char-literal.test.testscript2
-rw-r--r--libbuild2/cc/lexer+comment.test.testscript2
-rw-r--r--libbuild2/cc/lexer+preprocessor.test.testscript4
-rw-r--r--libbuild2/cc/lexer+raw-string-literal.test.testscript10
-rw-r--r--libbuild2/cc/lexer+string-literal.test.testscript2
-rw-r--r--libbuild2/cc/lexer.cxx73
-rw-r--r--libbuild2/cc/lexer.hxx23
-rw-r--r--libbuild2/cc/lexer.test.cxx17
-rw-r--r--libbuild2/cc/parser+module.test.testscript14
-rw-r--r--libbuild2/cc/parser.cxx4
-rw-r--r--libbuild2/cc/parser.hxx2
-rw-r--r--libbuild2/cc/parser.test.cxx12
-rw-r--r--libbuild2/test/script/parser.cxx2
-rw-r--r--libbuild2/test/script/script.hxx14
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
+<stdin>: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 @@ $* <<EOI 2>>EOE != 0
/*
comment
EOI
-stdin:1:2: error: unterminated comment
+<stdin>: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 <<EOI >>EOO
# 5 "test.cxx"
;
EOI
-';' stdin:1:1
+';' <stdin>:1:1
';' test.cxx:1:1
';' test.cxx:2:3
';' test.cxx:4:1
@@ -60,7 +60,7 @@ EOO
$* <<EOI 2>>EOE != 0
#include <foo/bar>
EOI
-stdin:1:1: error: unexpected #include directive
+<stdin>: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
+<stdin>:1:2: error: invalid raw string literal
EOE
: invalid-paren
:
$* <'R")()("' 2>>EOE != 0
-stdin:1:2: error: invalid raw string literal
+<stdin>:1:2: error: invalid raw string literal
EOE
: invalid-unterminated-paren
:
$* <'R"(abc"' 2>>EOE != 0
-stdin:1:2: error: invalid raw string literal
+<stdin>: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
+<stdin>: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
+<stdin>: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
+<stdin>: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<const path*> (data), c.line, c.column);
+ return location (*static_cast<const path_name*> (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 <raw_characters> 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 (<stdin>, <built-in>, 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<uint64_t> 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 ("<stdin>");
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
+<stdin>:8:1: error: {}-imbalance detected
EOE
: brace-stray
@@ -103,7 +103,7 @@ export
}
module foo;
EOI
-stdin:6:1: error: {}-imbalance detected
+<stdin>:6:1: error: {}-imbalance detected
EOE
: import-missing-name
@@ -111,7 +111,7 @@ EOE
$* <<EOI 2>>EOE != 0
import ;
EOI
-stdin:1:8: error: module or header name expected instead of ';'
+<stdin>:1:8: error: module or header name expected instead of ';'
EOE
: module-missing-name
@@ -119,7 +119,7 @@ EOE
$* <<EOI 2>>EOE != 0
module ;
EOI
-stdin:1:1: error: module declaration expected after leading module marker
+<stdin>:1:1: error: module declaration expected after leading module marker
EOE
: import-missing-semi
@@ -127,7 +127,7 @@ EOE
$* <<EOI 2>>EOE != 0
import foo
EOI
-stdin:2:1: error: ';' expected instead of <end of file>
+<stdin>:2:1: error: ';' expected instead of <end of file>
EOE
: module-missing-semi
@@ -135,7 +135,7 @@ EOE
$* <<EOI 2>>EOE != 0
export module foo
EOI
-stdin:2:1: error: ';' expected instead of <end of file>
+<stdin>:2:1: error: ';' expected instead of <end of file>
EOE
: import-missing-header
@@ -143,5 +143,5 @@ EOE
$* <<EOI 2>>EOE != 0
import <foo.h;
EOI
-stdin:2:1: error: closing '>' expected after header name
+<stdin>: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 ("<stdin>");
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<path_name_value> 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<path_name_value, compare_paths> paths_;
};
}
}