diff --git a/dtool/src/cppparser/cppPreprocessor.cxx b/dtool/src/cppparser/cppPreprocessor.cxx index 15c6daecaf..74d2803e5c 100644 --- a/dtool/src/cppparser/cppPreprocessor.cxx +++ b/dtool/src/cppparser/cppPreprocessor.cxx @@ -439,10 +439,11 @@ get_verbose() const { */ void CPPPreprocessor:: copy_filepos(const CPPPreprocessor &other) { - assert(!_files.empty()); - _files.back()._file = other.get_file(); - _files.back()._line_number = other.get_line_number(); - _files.back()._col_number = other.get_col_number(); + InputFile *infile = _infile; + assert(infile != nullptr); + infile->_file = other.get_file(); + 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:: get_file() const { - if (_files.empty()) { + InputFile *infile = _infile; + if (infile != nullptr) { + return infile->_file; + } else { return CPPFile(""); } - return _files.back()._file; } /** @@ -461,10 +464,12 @@ get_file() const { */ int CPPPreprocessor:: get_line_number() const { - if (_files.empty()) { + InputFile *infile = _infile; + if (infile != nullptr) { + return infile->_line_number; + } else { return 0; } - return _files.back()._line_number; } /** @@ -472,10 +477,12 @@ get_line_number() const { */ int CPPPreprocessor:: get_col_number() const { - if (_files.empty()) { + InputFile *infile = _infile; + if (infile != nullptr) { + return infile->_col_number; + } else { return 0; } - return _files.back()._col_number; } /** @@ -486,7 +493,7 @@ get_next_token() { #ifdef CPP_VERBOSE_LEX CPPToken tok = get_next_token0(); - indent(cerr, _files.size() * 2) + indent(cerr, get_file_depth() * 2) << _token_index++ << ". " << tok << "\n"; return tok; } @@ -668,7 +675,7 @@ void CPPPreprocessor:: warning(const string &message, const YYLTYPE &loc) const { if (_verbose >= 2) { if (_verbose >= 3) { - indent(cerr, _files.size() * 2); + indent(cerr, get_file_depth() * 2); } if (!loc.file.empty()) { @@ -717,7 +724,7 @@ error(const string &message, const YYLTYPE &loc) const { if (_verbose >= 1) { if (_verbose >= 3) { - indent(cerr, _files.size() * 2); + indent(cerr, get_file_depth() * 2); } if (!loc.file.empty()) { @@ -734,31 +741,31 @@ error(const string &message, const YYLTYPE &loc) const { cerr << " error: " << message << "\n"; show_line(loc); - if (!_files.empty() && !loc.file.empty()) { - Files::const_reverse_iterator rit; - for (rit = _files.rbegin(); - rit != _files.rend() && (*rit)._file == loc.file && (*rit)._manifest != nullptr; - ++rit) { + InputFile *infile = _infile; + if (infile != nullptr && !loc.file.empty()) { + // Add all the expansions to a vector for easy reverse iteration. + std::vector infiles; + while (infile != nullptr && infile->_file == loc.file && infile->_manifest != nullptr) { + infiles.push_back(infile); + infile = infile->_parent; } - if (rit != _files.rbegin() && rit != _files.rend()) { - --rit; - const InputFile &infile = *rit; + if (!infiles.empty()) { + auto rit = infiles.rbegin(); if (_verbose >= 3) { - cerr << "Expansion of " << infile._manifest->_name << ":\n"; - cerr << " -> " << trim_blanks(infile._input) << "\n"; - while (rit != _files.rbegin()) { - --rit; - const InputFile &infile = *rit; - cerr << " -> " << trim_blanks(infile._input) << "\n"; + cerr << "Expansion of " << (*rit)->_manifest->_name << ":\n"; + while (rit != infiles.rend()) { + cerr << " -> " << trim_blanks((*rit)->_input) << "\n"; + ++rit; } } else { - cerr << "with " << infile._manifest->_name; - if (infile._manifest->_has_parameters) { + cerr << "with " << (*rit)->_manifest->_name; + if ((*rit)->_manifest->_has_parameters) { 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; if (_verbose >= 3) { - indent_level = _files.size() * 2; + indent_level = get_file_depth() * 2; } // Seek to the offending line in the file. @@ -940,25 +947,26 @@ init_type(const string &type) { bool CPPPreprocessor:: push_file(const CPPFile &file) { if (_verbose >= 3) { - indent(cerr, _files.size() * 2) + indent(cerr, get_file_depth() * 2) << "Reading " << file << "\n"; } assert(_last_c == 0); - _files.push_back(InputFile()); - InputFile &infile = _files.back(); + InputFile *infile = new InputFile; + 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. _parsed_files.insert(file); - infile._prev_last_c = _last_c; + infile->_prev_last_c = _last_c; _last_c = '\0'; _start_of_line = true; return true; } - _files.pop_back(); + delete infile; return false; } @@ -968,25 +976,26 @@ push_file(const CPPFile &file) { bool CPPPreprocessor:: push_string(const string &input) { #ifdef CPP_VERBOSE_LEX - indent(cerr, _files.size() * 2) + indent(cerr, get_file_depth() * 2) << "Pushing to string \"" << input << "\"\n"; #endif - _files.push_back(InputFile()); - InputFile &infile = _files.back(); - if (infile.connect_input(input)) { - infile._prev_last_c = _last_c; + InputFile *infile = new InputFile; + if (infile->connect_input(input)) { + infile->_prev_last_c = _last_c; + infile->_parent = _infile; + _infile = infile; _last_c = '\0'; return true; } #ifdef CPP_VERBOSE_LEX - indent(cerr, _files.size() * 2) + indent(cerr, get_file_depth() * 2) << "Unable to read string\n"; #endif - _files.pop_back(); + delete infile; return false; } @@ -996,37 +1005,38 @@ push_string(const string &input) { bool CPPPreprocessor:: push_expansion(const string &input, const CPPManifest *manifest, const YYLTYPE &loc) { #ifdef CPP_VERBOSE_LEX - indent(cerr, _files.size() * 2) + indent(cerr, get_file_depth() * 2) << "Pushing to expansion \"" << input << "\"\n"; #endif - _files.push_back(InputFile()); - InputFile &infile = _files.back(); - if (infile.connect_input(input)) { - infile._manifest = manifest; - infile._file = loc.file; - infile._line_number = loc.first_line; - infile._col_number = loc.first_column; - infile._lock_position = true; + InputFile *infile = new InputFile; + if (infile->connect_input(input)) { + infile->_manifest = manifest; + infile->_file = loc.file; + infile->_line_number = loc.first_line; + infile->_col_number = loc.first_column; + infile->_lock_position = true; if (!manifest->_has_parameters) { // If the manifest does not use arguments, then disallow recursive // 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'; return true; } #ifdef CPP_VERBOSE_LEX - indent(cerr, _files.size() * 2) + indent(cerr, get_file_depth() * 2) << "Unable to read expansion\n"; #endif - _files.pop_back(); + delete infile; return false; } @@ -1647,7 +1657,7 @@ process_directive(int c) { loc.last_column = 0; #ifdef CPP_VERBOSE_LEX - indent(cerr, _files.size() * 2) + indent(cerr, get_file_depth() * 2) << "#" << command << " " << args << "\n"; #endif @@ -1870,7 +1880,7 @@ handle_include_directive(const string &args, const YYLTYPE &loc) { if (expr[0] == '"' && expr[expr.size() - 1] == '"') { 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 // directive. We don't need to record includes from included files. _quote_includes.insert(filename); @@ -1884,7 +1894,7 @@ handle_include_directive(const string &args, const YYLTYPE &loc) { angle_quotes = true; } - if (_files.size() == 1) { + if (_infile->_parent == nullptr) { // If we're currently processing a top-level file, record the include // directive. We don't need to record includes from included files. _angle_includes.insert(filename); @@ -2470,17 +2480,19 @@ expand_manifest(const CPPManifest *manifest, const YYLTYPE &loc) { CPPManifest::Ignores ignores; ignores.insert(manifest); - for (const InputFile &infile : _files) { - if (infile._ignore_manifest) { - ignores.insert(infile._manifest); + InputFile *infile = _infile; + while (infile != nullptr) { + if (infile->_ignore_manifest) { + ignores.insert(infile->_manifest); } + infile = infile->_parent; } string expanded = " " + manifest->expand(args, false, ignores) + " "; push_expansion(expanded, manifest, loc); #ifdef CPP_VERBOSE_LEX - indent(cerr, _files.size() * 2) + indent(cerr, get_file_depth() * 2) << "Expanding " << manifest->_name << " to " << expanded << "\n"; #endif @@ -3006,10 +3018,12 @@ scan_raw(int c) { */ bool CPPPreprocessor:: should_ignore_manifest(const CPPManifest *manifest) const { - for (const InputFile &infile : _files) { - if (infile._ignore_manifest && infile._manifest == manifest) { + InputFile *infile = _infile; + while (infile != nullptr) { + if (infile->_ignore_manifest && infile->_manifest == manifest) { return true; } + infile = infile->_parent; } return false; @@ -3021,10 +3035,12 @@ should_ignore_manifest(const CPPManifest *manifest) const { */ bool CPPPreprocessor:: should_ignore_preprocessor() const { - for (const InputFile &infile : _files) { - if (infile._ignore_manifest) { + InputFile *infile = _infile; + while (infile != nullptr) { + if (infile->_ignore_manifest) { return true; } + infile = infile->_parent; } return false; @@ -3041,18 +3057,21 @@ get() { return c; } - if (_files.empty()) { + if (UNLIKELY(_infile == nullptr)) { 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 - indent(cerr, _files.size() * 2) + indent(cerr, get_file_depth() * 2) << "End of input stream, restoring to previous input\n"; #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 // one. @@ -3077,21 +3096,21 @@ peek() { return _unget; } - if (_files.empty()) { + InputFile *infile = _infile; + if (UNLIKELY(infile == nullptr)) { return EOF; } - Files::reverse_iterator it = _files.rbegin(); - int c = (*it).peek(); + int c = infile->peek(); - while (c == EOF && it != _files.rend()) { - int last_c = (*it)._prev_last_c; - ++it; + while (UNLIKELY(c == EOF && infile != nullptr)) { + int last_c = infile->_prev_last_c; + infile = infile->_parent; if (last_c != '\0') { c = last_c; - } else if (it != _files.rend()) { - c = (*it).peek(); + } else if (infile != nullptr) { + c = infile->peek(); } } @@ -3117,7 +3136,7 @@ unget(int c) { CPPTemplateParameterList *CPPPreprocessor:: nested_parse_template_instantiation(CPPTemplateScope *scope) { #ifdef CPP_VERBOSE_LEX - indent(cerr, _files.size() * 2) + indent(cerr, get_file_depth() * 2) << "Beginning nested parse\n"; #endif assert(scope != nullptr); @@ -3206,7 +3225,7 @@ nested_parse_template_instantiation(CPPTemplateScope *scope) { _parsing_template_params = old_parsing_params; #ifdef CPP_VERBOSE_LEX - indent(cerr, _files.size() * 2) + indent(cerr, get_file_depth() * 2) << "Ending nested parse\n"; #endif return actual_params; @@ -3222,7 +3241,7 @@ nested_parse_template_instantiation(CPPTemplateScope *scope) { void CPPPreprocessor:: skip_to_end_nested() { #ifdef CPP_VERBOSE_LEX - indent(cerr, _files.size() * 2) + indent(cerr, get_file_depth() * 2) << "Skipping tokens:\n"; #endif @@ -3236,7 +3255,7 @@ skip_to_end_nested() { } #ifdef CPP_VERBOSE_LEX - indent(cerr, _files.size() * 2) + indent(cerr, get_file_depth() * 2) << "Done skipping tokens.\n"; #endif } @@ -3249,7 +3268,7 @@ skip_to_end_nested() { void CPPPreprocessor:: skip_to_angle_bracket() { #ifdef CPP_VERBOSE_LEX - indent(cerr, _files.size() * 2) + indent(cerr, get_file_depth() * 2) << "Skipping tokens:\n"; #endif @@ -3266,7 +3285,21 @@ skip_to_angle_bracket() { } #ifdef CPP_VERBOSE_LEX - indent(cerr, _files.size() * 2) + indent(cerr, get_file_depth() * 2) << "Done skipping tokens.\n"; #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; +} diff --git a/dtool/src/cppparser/cppPreprocessor.h b/dtool/src/cppparser/cppPreprocessor.h index 4a43463caf..0e509e9b1b 100644 --- a/dtool/src/cppparser/cppPreprocessor.h +++ b/dtool/src/cppparser/cppPreprocessor.h @@ -182,6 +182,8 @@ private: void skip_to_end_nested(); void skip_to_angle_bracket(); + int get_file_depth() const; + class InputFile { public: InputFile(); @@ -203,12 +205,11 @@ private: bool _lock_position; bool _ignore_manifest; int _prev_last_c; + + InputFile *_parent = nullptr; }; - // This must be a list and not a vector because we don't have a good copy - // constructor defined for InputFile. - typedef std::list Files; - Files _files; + InputFile *_infile = nullptr; enum State { S_normal, S_eof, S_nested, S_end_nested