mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 19:08:55 -04:00
cppparser: support directives __LINE__, __FILE__, __has_include
This commit is contained in:
parent
fa851ae5ac
commit
40ea0ab786
@ -809,6 +809,8 @@ expand_manifests(const string &input_expr, bool expand_undefined,
|
|||||||
// Here's an identifier. Is it "defined"?
|
// Here's an identifier. Is it "defined"?
|
||||||
if (ident == "defined") {
|
if (ident == "defined") {
|
||||||
expand_defined_function(expr, q, p);
|
expand_defined_function(expr, q, p);
|
||||||
|
} else if (expand_undefined && ident == "__has_include") {
|
||||||
|
expand_has_include_function(expr, q, p, loc);
|
||||||
} else {
|
} else {
|
||||||
// Is it a manifest?
|
// Is it a manifest?
|
||||||
Manifests::const_iterator mi = _manifests.find(ident);
|
Manifests::const_iterator mi = _manifests.find(ident);
|
||||||
@ -817,6 +819,20 @@ expand_manifests(const string &input_expr, bool expand_undefined,
|
|||||||
expand_manifest_inline(expr, q, p, manifest);
|
expand_manifest_inline(expr, q, p, manifest);
|
||||||
manifest_found = true;
|
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") {
|
} else if (expand_undefined && ident != "true" && ident != "false") {
|
||||||
// It is not found. Expand it to 0, but only if we are currently
|
// It is not found. Expand it to 0, but only if we are currently
|
||||||
// parsing an #if expression.
|
// parsing an #if expression.
|
||||||
@ -1486,31 +1502,22 @@ handle_undef_directive(const string &args, const YYLTYPE &loc) {
|
|||||||
*/
|
*/
|
||||||
void CPPPreprocessor::
|
void CPPPreprocessor::
|
||||||
handle_ifdef_directive(const string &args, const YYLTYPE &loc) {
|
handle_ifdef_directive(const string &args, const YYLTYPE &loc) {
|
||||||
Manifests::const_iterator mi = _manifests.find(args);
|
if (!is_manifest_defined(args)) {
|
||||||
if (mi != _manifests.end()) {
|
|
||||||
// The macro is defined. We continue.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The macro is undefined. Skip stuff.
|
// The macro is undefined. Skip stuff.
|
||||||
skip_false_if_block(true);
|
skip_false_if_block(true);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void CPPPreprocessor::
|
void CPPPreprocessor::
|
||||||
handle_ifndef_directive(const string &args, const YYLTYPE &loc) {
|
handle_ifndef_directive(const string &args, const YYLTYPE &loc) {
|
||||||
Manifests::const_iterator mi = _manifests.find(args);
|
if (is_manifest_defined(args)) {
|
||||||
if (mi == _manifests.end()) {
|
|
||||||
// The macro is undefined. We continue.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The macro is defined. Skip stuff.
|
// The macro is defined. Skip stuff.
|
||||||
skip_false_if_block(true);
|
skip_false_if_block(true);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -1593,6 +1600,8 @@ handle_include_directive(const string &args, const YYLTYPE &loc) {
|
|||||||
_angle_includes.insert(filename);
|
_angle_includes.insert(filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
warning("Ignoring invalid #include directive", loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
filename.set_text();
|
filename.set_text();
|
||||||
@ -1600,49 +1609,9 @@ handle_include_directive(const string &args, const YYLTYPE &loc) {
|
|||||||
|
|
||||||
// Now look for the filename. If we didn't use angle quotes, look first in
|
// Now look for the filename. If we didn't use angle quotes, look first in
|
||||||
// the current directory.
|
// the current directory.
|
||||||
bool found_file = false;
|
|
||||||
CPPFile::Source source = CPPFile::S_none;
|
CPPFile::Source source = CPPFile::S_none;
|
||||||
|
|
||||||
if (okflag) {
|
if (find_include(filename, angle_quotes, source)) {
|
||||||
found_file = false;
|
|
||||||
|
|
||||||
// Search the current directory.
|
|
||||||
if (!angle_quotes && !found_file && filename.exists()) {
|
|
||||||
found_file = true;
|
|
||||||
source = CPPFile::S_local;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search the same directory as the includer.
|
|
||||||
if (!angle_quotes && !found_file) {
|
|
||||||
Filename match(get_file()._filename.get_dirname(), filename);
|
|
||||||
if (match.exists()) {
|
|
||||||
filename = match;
|
|
||||||
found_file = true;
|
|
||||||
source = CPPFile::S_alternate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now search the angle-include-path
|
|
||||||
if (angle_quotes && !found_file && filename.resolve_filename(_angle_include_path)) {
|
|
||||||
found_file = true;
|
|
||||||
source = CPPFile::S_system;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now search the quote-include-path
|
|
||||||
if (!angle_quotes && !found_file) {
|
|
||||||
for (size_t dir=0; dir<_quote_include_path.get_num_directories(); dir++) {
|
|
||||||
Filename match(_quote_include_path.get_directory(dir), filename);
|
|
||||||
if (match.exists()) {
|
|
||||||
filename = match;
|
|
||||||
found_file = true;
|
|
||||||
source = _quote_include_kind[dir];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found_file) {
|
|
||||||
warning("Cannot find " + filename.get_fullpath(), loc);
|
|
||||||
} else {
|
|
||||||
_last_c = '\0';
|
_last_c = '\0';
|
||||||
|
|
||||||
// If it was explicitly named on the command-line, mark it S_local.
|
// If it was explicitly named on the command-line, mark it S_local.
|
||||||
@ -1662,9 +1631,8 @@ handle_include_directive(const string &args, const YYLTYPE &loc) {
|
|||||||
if (!push_file(file)) {
|
if (!push_file(file)) {
|
||||||
warning("Unable to read " + filename.get_fullpath(), loc);
|
warning("Unable to read " + filename.get_fullpath(), loc);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
warning("Ignoring invalid #include directive", loc);
|
warning("Cannot find " + filename.get_fullpath(), loc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1779,6 +1747,69 @@ skip_false_if_block(bool consider_elifs) {
|
|||||||
_save_comments = true;
|
_save_comments = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the given manifest is defined.
|
||||||
|
*/
|
||||||
|
bool CPPPreprocessor::
|
||||||
|
is_manifest_defined(const string &manifest_name) {
|
||||||
|
Manifests::const_iterator mi = _manifests.find(manifest_name);
|
||||||
|
if (mi != _manifests.end()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (manifest_name == "__has_include" ||
|
||||||
|
manifest_name == "__FILE__" ||
|
||||||
|
manifest_name == "__LINE__") {
|
||||||
|
// Special built-in directives that are considered "defined".
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locates the given filename. Changes the first argument to the full path.
|
||||||
|
*/
|
||||||
|
bool CPPPreprocessor::
|
||||||
|
find_include(Filename &filename, bool angle_quotes, CPPFile::Source &source) {
|
||||||
|
// Now look for the filename. If we didn't use angle quotes, look first in
|
||||||
|
// the current directory.
|
||||||
|
if (!angle_quotes && filename.exists()) {
|
||||||
|
source = CPPFile::S_local;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search the same directory as the includer.
|
||||||
|
if (!angle_quotes) {
|
||||||
|
Filename match(get_file()._filename.get_dirname(), filename);
|
||||||
|
if (match.exists()) {
|
||||||
|
filename = match;
|
||||||
|
source = CPPFile::S_alternate;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now search the angle-include-path
|
||||||
|
if (angle_quotes && filename.resolve_filename(_angle_include_path)) {
|
||||||
|
source = CPPFile::S_system;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now search the quote-include-path
|
||||||
|
if (!angle_quotes) {
|
||||||
|
for (size_t dir = 0; dir < _quote_include_path.get_num_directories(); ++dir) {
|
||||||
|
Filename match(_quote_include_path.get_directory(dir), filename);
|
||||||
|
if (match.exists()) {
|
||||||
|
filename = match;
|
||||||
|
source = _quote_include_kind[dir];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@ -1885,6 +1916,14 @@ get_identifier(int c) {
|
|||||||
if (mi != _manifests.end() && !should_ignore_manifest((*mi).second)) {
|
if (mi != _manifests.end() && !should_ignore_manifest((*mi).second)) {
|
||||||
return expand_manifest((*mi).second);
|
return expand_manifest((*mi).second);
|
||||||
}
|
}
|
||||||
|
if (name == "__FILE__") {
|
||||||
|
return get_literal(SIMPLE_STRING, loc, loc.file._filename_as_referenced);
|
||||||
|
}
|
||||||
|
if (name == "__LINE__") {
|
||||||
|
YYSTYPE result;
|
||||||
|
result.u.integer = loc.first_line;
|
||||||
|
return CPPToken(INTEGER, loc, "", result);
|
||||||
|
}
|
||||||
|
|
||||||
// Check for keywords.
|
// Check for keywords.
|
||||||
int kw = check_keyword(name);
|
int kw = check_keyword(name);
|
||||||
@ -2227,9 +2266,7 @@ expand_defined_function(string &expr, size_t q, size_t &p) {
|
|||||||
vector_string args;
|
vector_string args;
|
||||||
extract_manifest_args_inline("defined", 1, -1, args, expr, p);
|
extract_manifest_args_inline("defined", 1, -1, args, expr, p);
|
||||||
if (args.size() >= 1) {
|
if (args.size() >= 1) {
|
||||||
const string &manifest_name = args[0];
|
if (is_manifest_defined(args[0])) {
|
||||||
Manifests::const_iterator mi = _manifests.find(manifest_name);
|
|
||||||
if (mi != _manifests.end()) {
|
|
||||||
// The macro is defined; the result is "1".
|
// The macro is defined; the result is "1".
|
||||||
result = "1";
|
result = "1";
|
||||||
} else {
|
} else {
|
||||||
@ -2242,6 +2279,70 @@ expand_defined_function(string &expr, size_t q, size_t &p) {
|
|||||||
p = q + result.size();
|
p = q + result.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expands the __has_include(manifest) function to either 1 or 0, depending on
|
||||||
|
* whether the include file exists.
|
||||||
|
*/
|
||||||
|
void CPPPreprocessor::
|
||||||
|
expand_has_include_function(string &expr, size_t q, size_t &p, YYLTYPE loc) {
|
||||||
|
bool found_file = false;
|
||||||
|
|
||||||
|
// Skip whitespace till paren.
|
||||||
|
while (p < expr.size() && isspace(expr[p])) {
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
size_t args_begin = p + 1;
|
||||||
|
|
||||||
|
vector_string args;
|
||||||
|
extract_manifest_args_inline("__has_include", 1, -1, args, expr, p);
|
||||||
|
|
||||||
|
if (!args.empty() && args[0].size() >= 2) {
|
||||||
|
Filename filename;
|
||||||
|
bool angle_quotes = false;
|
||||||
|
|
||||||
|
string inc = args[0];
|
||||||
|
|
||||||
|
// Just to play things safe, since our manifest-expansion logic might not
|
||||||
|
// filter out quotes and angle brackets properly, we'll only expand
|
||||||
|
// manifests if we don't begin with a quote or bracket.
|
||||||
|
if (!inc.empty() && (inc[0] != '"' && inc[0] != '<')) {
|
||||||
|
inc = expand_manifests(inc, false, loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inc[0] == '"' && inc[inc.size() - 1] == '"') {
|
||||||
|
filename = inc.substr(1, inc.size() - 2);
|
||||||
|
} else if (inc[0] == '<' && inc[inc.size() - 1] == '>') {
|
||||||
|
filename = inc.substr(1, inc.size() - 2);
|
||||||
|
if (!_noangles) {
|
||||||
|
// If _noangles is true, we don't make a distinction between angle
|
||||||
|
// brackets and quote marks--all #inc statements are treated the
|
||||||
|
// same, as if they used quote marks.
|
||||||
|
angle_quotes = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
loc.last_column += loc.first_column + p - 2;
|
||||||
|
loc.first_column += args_begin;
|
||||||
|
warning("invalid argument for __has_include() directive", loc);
|
||||||
|
expr = expr.substr(0, q) + "0" + expr.substr(p);
|
||||||
|
p = q + 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
filename.set_text();
|
||||||
|
|
||||||
|
CPPFile::Source source = CPPFile::S_none;
|
||||||
|
found_file = find_include(filename, angle_quotes, source);
|
||||||
|
} else {
|
||||||
|
loc.last_column += loc.first_column + p - 2;
|
||||||
|
loc.first_column += args_begin;
|
||||||
|
warning("invalid argument for __has_include() directive", loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
string result = found_file ? "1" : "0";
|
||||||
|
expr = expr.substr(0, q) + result + expr.substr(p);
|
||||||
|
p = q + result.size();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -143,6 +143,8 @@ private:
|
|||||||
void handle_error_directive(const string &args, const YYLTYPE &loc);
|
void handle_error_directive(const string &args, const YYLTYPE &loc);
|
||||||
|
|
||||||
void skip_false_if_block(bool consider_elifs);
|
void skip_false_if_block(bool consider_elifs);
|
||||||
|
bool is_manifest_defined(const string &manifest_name);
|
||||||
|
bool find_include(Filename &filename, bool angle_quotes, CPPFile::Source &source);
|
||||||
|
|
||||||
CPPToken get_quoted_char(int c);
|
CPPToken get_quoted_char(int c);
|
||||||
CPPToken get_quoted_string(int c);
|
CPPToken get_quoted_string(int c);
|
||||||
@ -153,6 +155,7 @@ private:
|
|||||||
void extract_manifest_args(const string &name, int num_args,
|
void extract_manifest_args(const string &name, int num_args,
|
||||||
int va_arg, vector_string &args);
|
int va_arg, vector_string &args);
|
||||||
void expand_defined_function(string &expr, size_t q, size_t &p);
|
void expand_defined_function(string &expr, size_t q, size_t &p);
|
||||||
|
void expand_has_include_function(string &expr, size_t q, size_t &p, YYLTYPE loc);
|
||||||
void expand_manifest_inline(string &expr, size_t q, size_t &p,
|
void expand_manifest_inline(string &expr, size_t q, size_t &p,
|
||||||
const CPPManifest *manifest);
|
const CPPManifest *manifest);
|
||||||
void extract_manifest_args_inline(const string &name, int num_args,
|
void extract_manifest_args_inline(const string &name, int num_args,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user