diff --git a/passes/techmap/libparse.cc b/passes/techmap/libparse.cc index bc7758cbd..5594d5443 100644 --- a/passes/techmap/libparse.cc +++ b/passes/techmap/libparse.cc @@ -75,7 +75,7 @@ bool LibertyInputStream::extend_buffer_once() buffer.resize(buf_end + chunk_size); } - size_t read_size = f.rdbuf()->sgetn(buffer.data() + buf_end, chunk_size); + size_t read_size = f.rdbuf()->sgetn((char *)buffer.data() + buf_end, chunk_size); buf_end += read_size; if (read_size < chunk_size) eof = true; @@ -436,6 +436,9 @@ void LibertyParser::report_unexpected_token(int tok) eReport += "'."; error(eReport); break; + case EOF: + error("Unexpected end of file"); + break; default: eReport = "Unexpected token: "; eReport += static_cast(tok); @@ -484,7 +487,7 @@ void LibertyParser::parse_vector_range(int tok) } } -LibertyAst *LibertyParser::parse() +LibertyAst *LibertyParser::parse(bool top_level) { std::string str; @@ -498,7 +501,13 @@ LibertyAst *LibertyParser::parse() while ((tok == 'n') || (tok == ';')) tok = lexer(str); - if (tok == '}' || tok < 0) + if (tok == EOF) { + if (top_level) + return NULL; + report_unexpected_token(tok); + } + + if (tok == '}') return NULL; if (tok != 'v') { @@ -571,12 +580,18 @@ LibertyAst *LibertyParser::parse() } if (tok == '{') { + bool terminated = false; while (1) { - LibertyAst *child = parse(); - if (child == NULL) + LibertyAst *child = parse(false); + if (child == NULL) { + terminated = true; break; + } ast->children.push_back(child); } + if (!terminated) { + report_unexpected_token(EOF); + } break; } diff --git a/passes/techmap/libparse.h b/passes/techmap/libparse.h index 3ba381fdf..61dc83867 100644 --- a/passes/techmap/libparse.h +++ b/passes/techmap/libparse.h @@ -92,7 +92,7 @@ namespace Yosys class LibertyInputStream { std::istream &f; - std::vector buffer; + std::vector buffer; size_t buf_pos = 0; size_t buf_end = 0; bool eof = false; @@ -107,7 +107,7 @@ namespace Yosys LibertyInputStream(std::istream &f) : f(f) {} size_t buffered_size() { return buf_end - buf_pos; } - const char *buffered_data() { return buffer.data() + buf_pos; } + const unsigned char *buffered_data() { return buffer.data() + buf_pos; } int get() { if (buf_pos == buf_end) @@ -165,7 +165,7 @@ namespace Yosys void report_unexpected_token(int tok); void parse_vector_range(int tok); - LibertyAst *parse(); + LibertyAst *parse(bool top_level); void error() const; void error(const std::string &str) const; @@ -174,18 +174,29 @@ namespace Yosys const LibertyAst *ast = nullptr; LibertyParser(std::istream &f) : f(f), line(1) { - shared_ast.reset(parse()); + shared_ast.reset(parse(true)); ast = shared_ast.get(); + if (!ast) { +#ifdef FILTERLIB + fprintf(stderr, "No entries found in liberty file.\n"); + exit(1); +#else + log_error("No entries found in liberty file.\n"); +#endif + } } #ifndef FILTERLIB LibertyParser(std::istream &f, const std::string &fname) : f(f), line(1) { shared_ast = LibertyAstCache::instance.cached_ast(fname); if (!shared_ast) { - shared_ast.reset(parse()); + shared_ast.reset(parse(true)); LibertyAstCache::instance.parsed_ast(fname, shared_ast); } ast = shared_ast.get(); + if (!ast) { + log_error("No entries found in liberty file `%s'.\n", fname.c_str()); + } } #endif }; diff --git a/tests/liberty/non-ascii.lib b/tests/liberty/non-ascii.lib new file mode 100644 index 000000000..1ac636e34 --- /dev/null +++ b/tests/liberty/non-ascii.lib @@ -0,0 +1,14 @@ +// The parser used to choke on the copyright symbol even in comments +// © ® ø Φ +library(dummy) { + cell(buffer) { + area : 1 ; + pin(A) { + direction : input ; + } + pin(Y) { + direction : output ; + function : "A" ; + } + } +} \ No newline at end of file diff --git a/tests/liberty/non-ascii.lib.filtered.ok b/tests/liberty/non-ascii.lib.filtered.ok new file mode 100644 index 000000000..f03f725f7 --- /dev/null +++ b/tests/liberty/non-ascii.lib.filtered.ok @@ -0,0 +1,12 @@ +library(dummy) { + cell(buffer) { + area : 1 ; + pin(A) { + direction : input ; + } + pin(Y) { + direction : output ; + function : "A" ; + } + } +} diff --git a/tests/liberty/non-ascii.lib.verilogsim.ok b/tests/liberty/non-ascii.lib.verilogsim.ok new file mode 100644 index 000000000..de5e2e5f3 --- /dev/null +++ b/tests/liberty/non-ascii.lib.verilogsim.ok @@ -0,0 +1,5 @@ +module buffer (A, Y); + input A; + output Y; + assign Y = A; // "A" +endmodule