Support push_macro and pop_macro in cppparser

This commit is contained in:
rdb 2016-12-05 02:02:25 +01:00
parent 6dc6b05409
commit a056543d5a
2 changed files with 35 additions and 1 deletions

View File

@ -1461,7 +1461,6 @@ handle_define_directive(const string &args, const YYLTYPE &loc) {
CPPManifest *other = result.first->second;
warning("redefinition of macro '" + manifest->_name + "'", loc);
warning("previous definition is here", other->_loc);
delete other;
result.first->second = manifest;
}
}
@ -1679,6 +1678,38 @@ handle_pragma_directive(const string &args, const YYLTYPE &loc) {
assert(it != _parsed_files.end());
it->_pragma_once = true;
}
char macro[64];
if (sscanf(args.c_str(), "push_macro ( \"%63[^\"]\" )", macro) == 1) {
// We just mark it as pushed for now, so that the next time someone tries
// to override it, we save the old value.
Manifests::iterator mi = _manifests.find(macro);
if (mi != _manifests.end()) {
_manifest_stack[macro].push_back(mi->second);
} else {
_manifest_stack[macro].push_back(NULL);
}
} else if (sscanf(args.c_str(), "pop_macro ( \"%63[^\"]\" )", macro) == 1) {
ManifestStack &stack = _manifest_stack[macro];
if (stack.size() > 0) {
CPPManifest *manifest = stack.back();
stack.pop_back();
Manifests::iterator mi = _manifests.find(macro);
if (manifest == NULL) {
// It was undefined when it was pushed, so make it undefined again.
if (mi != _manifests.end()) {
_manifests.erase(mi);
}
} else if (mi != _manifests.end()) {
mi->second = manifest;
} else {
_manifests.insert(Manifests::value_type(macro, manifest));
}
} else {
warning("pop_macro without matching push_macro", loc);
}
}
}
/**

View File

@ -72,6 +72,9 @@ public:
typedef map<string, CPPManifest *> Manifests;
Manifests _manifests;
typedef pvector<CPPManifest *> ManifestStack;
map<string, ManifestStack> _manifest_stack;
pvector<CPPFile::Source> _quote_include_kind;
DSearchPath _quote_include_path;
DSearchPath _angle_include_path;