cppparser: Minor performance improvements

This commit is contained in:
rdb 2024-03-29 16:04:04 +01:00
parent 12a188b116
commit 4430f16cda
2 changed files with 125 additions and 91 deletions

View File

@ -439,10 +439,11 @@ get_verbose() const {
*/ */
void CPPPreprocessor:: void CPPPreprocessor::
copy_filepos(const CPPPreprocessor &other) { copy_filepos(const CPPPreprocessor &other) {
assert(!_files.empty()); InputFile *infile = _infile;
_files.back()._file = other.get_file(); assert(infile != nullptr);
_files.back()._line_number = other.get_line_number(); infile->_file = other.get_file();
_files.back()._col_number = other.get_col_number(); infile->_line_number = other.get_line_number();
infile->_col_number = other.get_col_number();
} }
/** /**
@ -450,10 +451,12 @@ copy_filepos(const CPPPreprocessor &other) {
*/ */
CPPFile CPPPreprocessor:: CPPFile CPPPreprocessor::
get_file() const { get_file() const {
if (_files.empty()) { InputFile *infile = _infile;
if (infile != nullptr) {
return infile->_file;
} else {
return CPPFile(""); return CPPFile("");
} }
return _files.back()._file;
} }
/** /**
@ -461,10 +464,12 @@ get_file() const {
*/ */
int CPPPreprocessor:: int CPPPreprocessor::
get_line_number() const { get_line_number() const {
if (_files.empty()) { InputFile *infile = _infile;
if (infile != nullptr) {
return infile->_line_number;
} else {
return 0; return 0;
} }
return _files.back()._line_number;
} }
/** /**
@ -472,10 +477,12 @@ get_line_number() const {
*/ */
int CPPPreprocessor:: int CPPPreprocessor::
get_col_number() const { get_col_number() const {
if (_files.empty()) { InputFile *infile = _infile;
if (infile != nullptr) {
return infile->_col_number;
} else {
return 0; return 0;
} }
return _files.back()._col_number;
} }
/** /**
@ -486,7 +493,7 @@ get_next_token() {
#ifdef CPP_VERBOSE_LEX #ifdef CPP_VERBOSE_LEX
CPPToken tok = get_next_token0(); CPPToken tok = get_next_token0();
indent(cerr, _files.size() * 2) indent(cerr, get_file_depth() * 2)
<< _token_index++ << ". " << tok << "\n"; << _token_index++ << ". " << tok << "\n";
return tok; return tok;
} }
@ -668,7 +675,7 @@ void CPPPreprocessor::
warning(const string &message, const YYLTYPE &loc) const { warning(const string &message, const YYLTYPE &loc) const {
if (_verbose >= 2) { if (_verbose >= 2) {
if (_verbose >= 3) { if (_verbose >= 3) {
indent(cerr, _files.size() * 2); indent(cerr, get_file_depth() * 2);
} }
if (!loc.file.empty()) { if (!loc.file.empty()) {
@ -717,7 +724,7 @@ error(const string &message, const YYLTYPE &loc) const {
if (_verbose >= 1) { if (_verbose >= 1) {
if (_verbose >= 3) { if (_verbose >= 3) {
indent(cerr, _files.size() * 2); indent(cerr, get_file_depth() * 2);
} }
if (!loc.file.empty()) { if (!loc.file.empty()) {
@ -734,31 +741,31 @@ error(const string &message, const YYLTYPE &loc) const {
cerr << " error: " << message << "\n"; cerr << " error: " << message << "\n";
show_line(loc); show_line(loc);
if (!_files.empty() && !loc.file.empty()) { InputFile *infile = _infile;
Files::const_reverse_iterator rit; if (infile != nullptr && !loc.file.empty()) {
for (rit = _files.rbegin(); // Add all the expansions to a vector for easy reverse iteration.
rit != _files.rend() && (*rit)._file == loc.file && (*rit)._manifest != nullptr; std::vector<InputFile *> infiles;
++rit) { while (infile != nullptr && infile->_file == loc.file && infile->_manifest != nullptr) {
infiles.push_back(infile);
infile = infile->_parent;
} }
if (rit != _files.rbegin() && rit != _files.rend()) { if (!infiles.empty()) {
--rit; auto rit = infiles.rbegin();
const InputFile &infile = *rit;
if (_verbose >= 3) { if (_verbose >= 3) {
cerr << "Expansion of " << infile._manifest->_name << ":\n"; cerr << "Expansion of " << (*rit)->_manifest->_name << ":\n";
cerr << " -> " << trim_blanks(infile._input) << "\n"; while (rit != infiles.rend()) {
while (rit != _files.rbegin()) { cerr << " -> " << trim_blanks((*rit)->_input) << "\n";
--rit; ++rit;
const InputFile &infile = *rit;
cerr << " -> " << trim_blanks(infile._input) << "\n";
} }
} }
else { else {
cerr << "with " << infile._manifest->_name; cerr << "with " << (*rit)->_manifest->_name;
if (infile._manifest->_has_parameters) { if ((*rit)->_manifest->_has_parameters) {
cerr << "()"; cerr << "()";
} }
cerr << " expanded to: " << trim_blanks(_files.back()._input) << "\n"; cerr << " expanded to: " << trim_blanks(_infile->_input) << "\n";
} }
cerr << std::endl;
} }
} }
@ -781,7 +788,7 @@ show_line(const YYLTYPE &loc) const {
int indent_level = 0; int indent_level = 0;
if (_verbose >= 3) { if (_verbose >= 3) {
indent_level = _files.size() * 2; indent_level = get_file_depth() * 2;
} }
// Seek to the offending line in the file. // Seek to the offending line in the file.
@ -940,25 +947,26 @@ init_type(const string &type) {
bool CPPPreprocessor:: bool CPPPreprocessor::
push_file(const CPPFile &file) { push_file(const CPPFile &file) {
if (_verbose >= 3) { if (_verbose >= 3) {
indent(cerr, _files.size() * 2) indent(cerr, get_file_depth() * 2)
<< "Reading " << file << "\n"; << "Reading " << file << "\n";
} }
assert(_last_c == 0); assert(_last_c == 0);
_files.push_back(InputFile()); InputFile *infile = new InputFile;
InputFile &infile = _files.back(); if (infile->open(file)) {
infile->_parent = _infile;
_infile = infile;
if (infile.open(file)) {
// Record the fact that we opened the file for the benefit of user code. // Record the fact that we opened the file for the benefit of user code.
_parsed_files.insert(file); _parsed_files.insert(file);
infile._prev_last_c = _last_c; infile->_prev_last_c = _last_c;
_last_c = '\0'; _last_c = '\0';
_start_of_line = true; _start_of_line = true;
return true; return true;
} }
_files.pop_back(); delete infile;
return false; return false;
} }
@ -968,25 +976,26 @@ push_file(const CPPFile &file) {
bool CPPPreprocessor:: bool CPPPreprocessor::
push_string(const string &input) { push_string(const string &input) {
#ifdef CPP_VERBOSE_LEX #ifdef CPP_VERBOSE_LEX
indent(cerr, _files.size() * 2) indent(cerr, get_file_depth() * 2)
<< "Pushing to string \"" << input << "Pushing to string \"" << input
<< "\"\n"; << "\"\n";
#endif #endif
_files.push_back(InputFile());
InputFile &infile = _files.back();
if (infile.connect_input(input)) { InputFile *infile = new InputFile;
infile._prev_last_c = _last_c; if (infile->connect_input(input)) {
infile->_prev_last_c = _last_c;
infile->_parent = _infile;
_infile = infile;
_last_c = '\0'; _last_c = '\0';
return true; return true;
} }
#ifdef CPP_VERBOSE_LEX #ifdef CPP_VERBOSE_LEX
indent(cerr, _files.size() * 2) indent(cerr, get_file_depth() * 2)
<< "Unable to read string\n"; << "Unable to read string\n";
#endif #endif
_files.pop_back(); delete infile;
return false; return false;
} }
@ -996,37 +1005,38 @@ push_string(const string &input) {
bool CPPPreprocessor:: bool CPPPreprocessor::
push_expansion(const string &input, const CPPManifest *manifest, const YYLTYPE &loc) { push_expansion(const string &input, const CPPManifest *manifest, const YYLTYPE &loc) {
#ifdef CPP_VERBOSE_LEX #ifdef CPP_VERBOSE_LEX
indent(cerr, _files.size() * 2) indent(cerr, get_file_depth() * 2)
<< "Pushing to expansion \"" << input << "Pushing to expansion \"" << input
<< "\"\n"; << "\"\n";
#endif #endif
_files.push_back(InputFile());
InputFile &infile = _files.back();
if (infile.connect_input(input)) { InputFile *infile = new InputFile;
infile._manifest = manifest; if (infile->connect_input(input)) {
infile._file = loc.file; infile->_manifest = manifest;
infile._line_number = loc.first_line; infile->_file = loc.file;
infile._col_number = loc.first_column; infile->_line_number = loc.first_line;
infile._lock_position = true; infile->_col_number = loc.first_column;
infile->_lock_position = true;
if (!manifest->_has_parameters) { if (!manifest->_has_parameters) {
// If the manifest does not use arguments, then disallow recursive // If the manifest does not use arguments, then disallow recursive
// expansion. // expansion.
infile._ignore_manifest = true; infile->_ignore_manifest = true;
} }
infile._prev_last_c = _last_c; infile->_prev_last_c = _last_c;
infile->_parent = _infile;
_infile = infile;
_last_c = '\0'; _last_c = '\0';
return true; return true;
} }
#ifdef CPP_VERBOSE_LEX #ifdef CPP_VERBOSE_LEX
indent(cerr, _files.size() * 2) indent(cerr, get_file_depth() * 2)
<< "Unable to read expansion\n"; << "Unable to read expansion\n";
#endif #endif
_files.pop_back(); delete infile;
return false; return false;
} }
@ -1647,7 +1657,7 @@ process_directive(int c) {
loc.last_column = 0; loc.last_column = 0;
#ifdef CPP_VERBOSE_LEX #ifdef CPP_VERBOSE_LEX
indent(cerr, _files.size() * 2) indent(cerr, get_file_depth() * 2)
<< "#" << command << " " << args << "\n"; << "#" << command << " " << args << "\n";
#endif #endif
@ -1870,7 +1880,7 @@ handle_include_directive(const string &args, const YYLTYPE &loc) {
if (expr[0] == '"' && expr[expr.size() - 1] == '"') { if (expr[0] == '"' && expr[expr.size() - 1] == '"') {
filename = expr.substr(1, expr.size() - 2); filename = expr.substr(1, expr.size() - 2);
if (_files.size() == 1) { if (_infile->_parent == nullptr) {
// If we're currently processing a top-level file, record the include // If we're currently processing a top-level file, record the include
// directive. We don't need to record includes from included files. // directive. We don't need to record includes from included files.
_quote_includes.insert(filename); _quote_includes.insert(filename);
@ -1884,7 +1894,7 @@ handle_include_directive(const string &args, const YYLTYPE &loc) {
angle_quotes = true; angle_quotes = true;
} }
if (_files.size() == 1) { if (_infile->_parent == nullptr) {
// If we're currently processing a top-level file, record the include // If we're currently processing a top-level file, record the include
// directive. We don't need to record includes from included files. // directive. We don't need to record includes from included files.
_angle_includes.insert(filename); _angle_includes.insert(filename);
@ -2470,17 +2480,19 @@ expand_manifest(const CPPManifest *manifest, const YYLTYPE &loc) {
CPPManifest::Ignores ignores; CPPManifest::Ignores ignores;
ignores.insert(manifest); ignores.insert(manifest);
for (const InputFile &infile : _files) { InputFile *infile = _infile;
if (infile._ignore_manifest) { while (infile != nullptr) {
ignores.insert(infile._manifest); if (infile->_ignore_manifest) {
ignores.insert(infile->_manifest);
} }
infile = infile->_parent;
} }
string expanded = " " + manifest->expand(args, false, ignores) + " "; string expanded = " " + manifest->expand(args, false, ignores) + " ";
push_expansion(expanded, manifest, loc); push_expansion(expanded, manifest, loc);
#ifdef CPP_VERBOSE_LEX #ifdef CPP_VERBOSE_LEX
indent(cerr, _files.size() * 2) indent(cerr, get_file_depth() * 2)
<< "Expanding " << manifest->_name << " to " << expanded << "\n"; << "Expanding " << manifest->_name << " to " << expanded << "\n";
#endif #endif
@ -3006,10 +3018,12 @@ scan_raw(int c) {
*/ */
bool CPPPreprocessor:: bool CPPPreprocessor::
should_ignore_manifest(const CPPManifest *manifest) const { should_ignore_manifest(const CPPManifest *manifest) const {
for (const InputFile &infile : _files) { InputFile *infile = _infile;
if (infile._ignore_manifest && infile._manifest == manifest) { while (infile != nullptr) {
if (infile->_ignore_manifest && infile->_manifest == manifest) {
return true; return true;
} }
infile = infile->_parent;
} }
return false; return false;
@ -3021,10 +3035,12 @@ should_ignore_manifest(const CPPManifest *manifest) const {
*/ */
bool CPPPreprocessor:: bool CPPPreprocessor::
should_ignore_preprocessor() const { should_ignore_preprocessor() const {
for (const InputFile &infile : _files) { InputFile *infile = _infile;
if (infile._ignore_manifest) { while (infile != nullptr) {
if (infile->_ignore_manifest) {
return true; return true;
} }
infile = infile->_parent;
} }
return false; return false;
@ -3041,18 +3057,21 @@ get() {
return c; return c;
} }
if (_files.empty()) { if (UNLIKELY(_infile == nullptr)) {
return EOF; return EOF;
} }
int c = _files.back().get(); int c = _infile->get();
while (c == EOF && !_files.empty()) { while (UNLIKELY(c == EOF && _infile != nullptr)) {
#ifdef CPP_VERBOSE_LEX #ifdef CPP_VERBOSE_LEX
indent(cerr, _files.size() * 2) indent(cerr, get_file_depth() * 2)
<< "End of input stream, restoring to previous input\n"; << "End of input stream, restoring to previous input\n";
#endif #endif
_files.pop_back(); // Pop the last file off the end.
InputFile *infile = _infile;
_infile = infile->_parent;
delete infile;
// Synthesize a newline, just in case the file doesn't already end with // Synthesize a newline, just in case the file doesn't already end with
// one. // one.
@ -3077,21 +3096,21 @@ peek() {
return _unget; return _unget;
} }
if (_files.empty()) { InputFile *infile = _infile;
if (UNLIKELY(infile == nullptr)) {
return EOF; return EOF;
} }
Files::reverse_iterator it = _files.rbegin(); int c = infile->peek();
int c = (*it).peek();
while (c == EOF && it != _files.rend()) { while (UNLIKELY(c == EOF && infile != nullptr)) {
int last_c = (*it)._prev_last_c; int last_c = infile->_prev_last_c;
++it; infile = infile->_parent;
if (last_c != '\0') { if (last_c != '\0') {
c = last_c; c = last_c;
} else if (it != _files.rend()) { } else if (infile != nullptr) {
c = (*it).peek(); c = infile->peek();
} }
} }
@ -3117,7 +3136,7 @@ unget(int c) {
CPPTemplateParameterList *CPPPreprocessor:: CPPTemplateParameterList *CPPPreprocessor::
nested_parse_template_instantiation(CPPTemplateScope *scope) { nested_parse_template_instantiation(CPPTemplateScope *scope) {
#ifdef CPP_VERBOSE_LEX #ifdef CPP_VERBOSE_LEX
indent(cerr, _files.size() * 2) indent(cerr, get_file_depth() * 2)
<< "Beginning nested parse\n"; << "Beginning nested parse\n";
#endif #endif
assert(scope != nullptr); assert(scope != nullptr);
@ -3206,7 +3225,7 @@ nested_parse_template_instantiation(CPPTemplateScope *scope) {
_parsing_template_params = old_parsing_params; _parsing_template_params = old_parsing_params;
#ifdef CPP_VERBOSE_LEX #ifdef CPP_VERBOSE_LEX
indent(cerr, _files.size() * 2) indent(cerr, get_file_depth() * 2)
<< "Ending nested parse\n"; << "Ending nested parse\n";
#endif #endif
return actual_params; return actual_params;
@ -3222,7 +3241,7 @@ nested_parse_template_instantiation(CPPTemplateScope *scope) {
void CPPPreprocessor:: void CPPPreprocessor::
skip_to_end_nested() { skip_to_end_nested() {
#ifdef CPP_VERBOSE_LEX #ifdef CPP_VERBOSE_LEX
indent(cerr, _files.size() * 2) indent(cerr, get_file_depth() * 2)
<< "Skipping tokens:\n"; << "Skipping tokens:\n";
#endif #endif
@ -3236,7 +3255,7 @@ skip_to_end_nested() {
} }
#ifdef CPP_VERBOSE_LEX #ifdef CPP_VERBOSE_LEX
indent(cerr, _files.size() * 2) indent(cerr, get_file_depth() * 2)
<< "Done skipping tokens.\n"; << "Done skipping tokens.\n";
#endif #endif
} }
@ -3249,7 +3268,7 @@ skip_to_end_nested() {
void CPPPreprocessor:: void CPPPreprocessor::
skip_to_angle_bracket() { skip_to_angle_bracket() {
#ifdef CPP_VERBOSE_LEX #ifdef CPP_VERBOSE_LEX
indent(cerr, _files.size() * 2) indent(cerr, get_file_depth() * 2)
<< "Skipping tokens:\n"; << "Skipping tokens:\n";
#endif #endif
@ -3266,7 +3285,21 @@ skip_to_angle_bracket() {
} }
#ifdef CPP_VERBOSE_LEX #ifdef CPP_VERBOSE_LEX
indent(cerr, _files.size() * 2) indent(cerr, get_file_depth() * 2)
<< "Done skipping tokens.\n"; << "Done skipping tokens.\n";
#endif #endif
} }
/**
* Returns the number of files on the _infile list.
*/
int CPPPreprocessor::
get_file_depth() const{
int depth = 0;
InputFile *infile = _infile;
while (infile != nullptr) {
++depth;
infile = infile->_parent;
}
return depth;
}

View File

@ -182,6 +182,8 @@ private:
void skip_to_end_nested(); void skip_to_end_nested();
void skip_to_angle_bracket(); void skip_to_angle_bracket();
int get_file_depth() const;
class InputFile { class InputFile {
public: public:
InputFile(); InputFile();
@ -203,12 +205,11 @@ private:
bool _lock_position; bool _lock_position;
bool _ignore_manifest; bool _ignore_manifest;
int _prev_last_c; int _prev_last_c;
InputFile *_parent = nullptr;
}; };
// This must be a list and not a vector because we don't have a good copy InputFile *_infile = nullptr;
// constructor defined for InputFile.
typedef std::list<InputFile> Files;
Files _files;
enum State { enum State {
S_normal, S_eof, S_nested, S_end_nested S_normal, S_eof, S_nested, S_end_nested