diff --git a/dtool/src/cppparser/cppPreprocessor.cxx b/dtool/src/cppparser/cppPreprocessor.cxx index 878e1c66d0..b1d3eefef9 100644 --- a/dtool/src/cppparser/cppPreprocessor.cxx +++ b/dtool/src/cppparser/cppPreprocessor.cxx @@ -34,6 +34,7 @@ #include #include +#include using std::cerr; using std::string; @@ -796,80 +797,8 @@ expand_manifests(const string &input_expr, bool expand_undefined, // Get a copy of the expression string we can modify. string expr = input_expr; - // Repeatedly scan the expr for any manifest names or defined() function. - - bool manifest_found; - do { - manifest_found = false; - size_t p = 0; - while (p < expr.size()) { - if (isalpha(expr[p]) || expr[p] == '_') { - size_t q = p; - while (p < expr.size() && (isalnum(expr[p]) || expr[p] == '_')) { - p++; - } - string ident = expr.substr(q, p - q); - - // Here's an identifier. Is it "defined"? - if (ident == "defined") { - expand_defined_function(expr, q, p); - } else if (expand_undefined && ident == "__has_include") { - expand_has_include_function(expr, q, p, loc); - } else { - // Is it a manifest? - Manifests::const_iterator mi = _manifests.find(ident); - if (mi != _manifests.end()) { - const CPPManifest *manifest = (*mi).second; - expand_manifest_inline(expr, q, p, manifest); - manifest_found = true; - - } else if (ident == "__FILE__") { - // Special case: this is a dynamic definition. - string file = string("\"") + loc.file._filename_as_referenced.get_fullpath() + "\""; - expr = expr.substr(0, q) + file + expr.substr(p); - p = q + file.size(); - manifest_found = true; - - } else if (ident == "__LINE__") { - // So is this. - string line = format_string(loc.first_line); - expr = expr.substr(0, q) + line + expr.substr(p); - p = q + line.size(); - manifest_found = true; - - } else if (expand_undefined && ident != "true" && ident != "false") { - // It is not found. Expand it to 0, but only if we are currently - // parsing an #if expression. - expr = expr.substr(0, q) + "0" + expr.substr(p); - p = q + 1; - } - } - } else if (expr[p] == '\'' || expr[p] == '"') { - // Skip the next part until we find a closing quotation mark. - char quote = expr[p]; - p++; - while (p < expr.size() && expr[p] != quote) { - if (expr[p] == '\\') { - // This might be an escaped quote. Skip an extra char. - p++; - } - p++; - } - if (p >= expr.size()) { - // Unclosed string. - warning("missing terminating " + string(1, quote) + " character", loc); - } - p++; - } else { - p++; - } - } - - // If we expanded any manifests at all that time, then go back through the - // string and look again--we might have a manifest that expands to another - // manifest. - } while (manifest_found); - + std::set expanded; + r_expand_manifests(expr, expand_undefined, loc, expanded); return expr; } @@ -1456,6 +1385,9 @@ get_preprocessor_args(int c, string &args) { // Following the command, the rest of the line, as well as any text on // successive lines, is part of the arguments to the command. + // Check for comments first. + c = skip_comment(c); + while (c != EOF && c != '\n') { if (c == '\\') { int next_c = get(); @@ -2207,6 +2139,96 @@ expand_manifest(const CPPManifest *manifest) { return internal_get_next_token(); } +/** + * Recursive implementation of expand_manifests(). + */ +void CPPPreprocessor:: +r_expand_manifests(string &expr, bool expand_undefined, + const YYLTYPE &loc, std::set &expanded) { + size_t p = 0; + while (p < expr.size()) { + if (isalpha(expr[p]) || expr[p] == '_') { + size_t q = p; + while (p < expr.size() && (isalnum(expr[p]) || expr[p] == '_')) { + p++; + } + string ident = expr.substr(q, p - q); + + // Here's an identifier. Is it "defined"? + if (ident == "defined") { + expand_defined_function(expr, q, p); + } + else if (expand_undefined && ident == "__has_include") { + expand_has_include_function(expr, q, p, loc); + } + else { + // Is it a manifest? + Manifests::const_iterator mi = _manifests.find(ident); + if (mi != _manifests.end()) { + const CPPManifest *manifest = (*mi).second; + if (expanded.count(manifest) == 0) { + vector_string args; + if (manifest->_has_parameters) { + extract_manifest_args_inline(manifest->_name, manifest->_num_parameters, + manifest->_variadic_param, args, expr, p); + } + + string result = manifest->expand(args); + + // Recurse, but adding the manifest we just expanded to the list + // to be ignored for future expansion, to prevent recursion. + std::set ignore = expanded; + ignore.insert(manifest); + r_expand_manifests(result, expand_undefined, loc, ignore); + + expr = expr.substr(0, q) + result + expr.substr(p); + p = q + result.size(); + } + } + else if (ident == "__FILE__") { + // Special case: this is a dynamic definition. + string file = string("\"") + loc.file._filename_as_referenced.get_fullpath() + "\""; + expr = expr.substr(0, q) + file + expr.substr(p); + p = q + file.size(); + + } + else if (ident == "__LINE__") { + // So is this. + string line = format_string(loc.first_line); + expr = expr.substr(0, q) + line + expr.substr(p); + p = q + line.size(); + } + else if (expand_undefined && ident != "true" && ident != "false") { + // It is not found. Expand it to 0, but only if we are currently + // parsing an #if expression. + expr = expr.substr(0, q) + "0" + expr.substr(p); + p = q + 1; + } + } + } + else if (expr[p] == '\'' || expr[p] == '"') { + // Skip the next part until we find a closing quotation mark. + char quote = expr[p]; + p++; + while (p < expr.size() && expr[p] != quote) { + if (expr[p] == '\\') { + // This might be an escaped quote. Skip an extra char. + p++; + } + p++; + } + if (p >= expr.size()) { + // Unclosed string. + warning("missing terminating " + string(1, quote) + " character", loc); + } + p++; + } + else { + p++; + } + } +} + /** * */ diff --git a/dtool/src/cppparser/cppPreprocessor.h b/dtool/src/cppparser/cppPreprocessor.h index 92986cf4c8..81fc5d3858 100644 --- a/dtool/src/cppparser/cppPreprocessor.h +++ b/dtool/src/cppparser/cppPreprocessor.h @@ -115,7 +115,7 @@ protected: bool push_string(const std::string &input, bool lock_position); std::string expand_manifests(const std::string &input_expr, bool expand_undefined, - const YYLTYPE &loc); + const YYLTYPE &loc); CPPExpression *parse_expr(const std::string &expr, CPPScope *current_scope, CPPScope *global_scope, const YYLTYPE &loc); @@ -152,6 +152,8 @@ private: CPPToken get_literal(int token, YYLTYPE loc, const std::string &str, const YYSTYPE &result = YYSTYPE()); CPPToken expand_manifest(const CPPManifest *manifest); + void r_expand_manifests(std::string &expr, bool expand_undefined, + const YYLTYPE &loc, std::set &expanded); void extract_manifest_args(const std::string &name, int num_args, int va_arg, vector_string &args); void expand_defined_function(std::string &expr, size_t q, size_t &p); diff --git a/panda/src/pnmimagetypes/bmp.h b/panda/src/pnmimagetypes/bmp.h index 2c5a08006f..bff1668ffd 100644 --- a/panda/src/pnmimagetypes/bmp.h +++ b/panda/src/pnmimagetypes/bmp.h @@ -48,7 +48,6 @@ BMPlenfileheader(int classv) case C_WINV4: case C_WINV5: return 14; - return 14; default: pm_error(er_internal, "BMPlenfileheader"); return 0;