1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
|
/***************************************************************************
Copyright 2006 David Nolden <david.nolden.kdevelop@art-master.de>
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "cpppreprocessenvironment.h"
#include <language/interfaces/iproblem.h>
#include <parser/rpp/macrorepository.h>
bool onlyRecordImportantMacroUses = true;
void CppPreprocessEnvironment::setRecordOnlyImportantString(bool onlyImportant) {
onlyRecordImportantMacroUses = onlyImportant;
}
CppPreprocessEnvironment::CppPreprocessEnvironment( rpp::pp* preprocessor, KSharedPtr<Cpp::EnvironmentFile> environmentFile ) : Environment(preprocessor), m_identityOffsetRestriction(0), m_identityOffsetRestrictionEnabled(false), m_finished(false), m_environmentFile(environmentFile) {
//If this is included from another preprocessed file, take the current macro-set from there.
///NOTE: m_environmentFile may be zero, this must be treated
}
CppPreprocessEnvironment::~CppPreprocessEnvironment() {
finishEnvironment();
}
void CppPreprocessEnvironment::finishEnvironment(bool leaveEnvironmentFile) {
if(!m_finished) {
if(m_environmentFile && !leaveEnvironmentFile)
m_environmentFile->addStrings(m_strings);
m_finished = true;
m_strings.clear();
}
}
void CppPreprocessEnvironment::removeMacro(KDevelop::IndexedString macroName) {
m_macroNameSet.remove(macroName);
rpp::pp_macro* m = new rpp::pp_macro;
m->name = macroName;
m->defined = false;
rpp::Environment::setMacro(m);
}
void CppPreprocessEnvironment::removeString(KDevelop::IndexedString str) {
m_strings.erase(str.index());
}
rpp::pp_macro* CppPreprocessEnvironment::retrieveMacro(const KDevelop::IndexedString& name, bool isImportant) const {
//note all strings that can be affected by macros
if( !m_environmentFile || (onlyRecordImportantMacroUses && !isImportant) )
return rpp::Environment::retrieveMacro(name, isImportant);
//kDebug() << "retrieving macro" << name.str();
rpp::pp_macro* ret = rpp::Environment::retrieveMacro(name, isImportant);
if( !ret || (!m_environmentFile->definedMacroNames().contains(name) && !m_environmentFile->unDefinedMacroNames().contains(name)) )
m_strings.insert(name.index());
if( ret )
m_environmentFile->usingMacro(*ret);
return ret;
}
KSharedPtr<Cpp::EnvironmentFile> CppPreprocessEnvironment::environmentFile() const {
return m_environmentFile;
}
void CppPreprocessEnvironment::setEnvironmentFile( const KSharedPtr<Cpp::EnvironmentFile>& environmentFile ) {
m_environmentFile = environmentFile;
m_finished = false;
}
void CppPreprocessEnvironment::swapMacros( rpp::Environment* parentEnvironment ) {
CppPreprocessEnvironment* env = dynamic_cast<CppPreprocessEnvironment*>(parentEnvironment);
Q_ASSERT(env);
qSwap(m_macroNameSet, env->m_macroNameSet);
rpp::Environment::swapMacros(parentEnvironment);
}
/**
* Merges the given set of macros into the environment. Does not modify m_environmentFile
* */
void CppPreprocessEnvironment::merge( const Cpp::ReferenceCountedMacroSet& macros ) {
for( Cpp::ReferenceCountedMacroSet::Iterator it(macros.iterator()); it; ++it ) {
rpp::Environment::setMacro(const_cast<rpp::pp_macro*>(&it.ref())); //Do not use our overridden setMacro(..), because addDefinedMacro(..) is not needed(macro-sets should be merged separately)
if( !it.ref().isUndef() )
m_macroNameSet.insert(it.ref().name);
else
m_macroNameSet.remove(it.ref().name);
}
}
void CppPreprocessEnvironment::merge( const Cpp::EnvironmentFile* file, bool mergeEnvironment ) {
Cpp::ReferenceCountedMacroSet addedMacros = file->definedMacros() - m_environmentFile->definedMacros();
if(mergeEnvironment)
m_environmentFile->merge(*file, this);
for( Cpp::ReferenceCountedMacroSet::Iterator it(addedMacros.iterator()); it; ++it )
rpp::Environment::setMacro(const_cast<rpp::pp_macro*>(&it.ref())); //Do not use our overridden setMacro(..), because addDefinedMacro(..) is not needed(macro-sets should be merged separately)
//We don't have to care about efficiency too much here, unDefinedMacros should be a rather small set
for( Cpp::ReferenceCountedStringSet::Iterator it = file->unDefinedMacroNames().iterator(); it; ++it ) {
rpp::pp_macro* m = new rpp::pp_macro(*it);
m->defined = false;
m->m_valueHashValid = false;
rpp::Environment::setMacro(m); //Do not use our overridden setMacro(..), because addDefinedMacro(..) is not needed(macro-sets should be merged separately)
}
m_macroNameSet += file->definedMacroNames();
m_macroNameSet -= file->unDefinedMacroNames();
}
void CppPreprocessEnvironment::setMacro(rpp::pp_macro* macro) {
rpp::pp_macro* hadMacro = retrieveStoredMacro(macro->name);
if(hadMacro && hadMacro->fixed) {
if(hadMacro->defineOnOverride && (hadMacro->file.isEmpty() ||
(macro->file.length() >= hadMacro->file.length() &&
memcmp(macro->file.c_str() + (macro->file.length() - hadMacro->file.length()),
hadMacro->file.c_str(),
hadMacro->file.length()) == 0)))
{
// We have to define the macro now, as it is being overridden
rpp::pp_macro* definedMacro = new rpp::pp_macro(*hadMacro);
definedMacro->defined = true;
if(!macro->isRepositoryMacro())
delete macro;
macro = definedMacro;
}else{
// A fixed macro exists, simply ignore the added macro
if(!macro->isRepositoryMacro())
delete macro;
return;
}
}
//kDebug() << "setting macro" << macro->name.str() << "with body" << macro->definition << "is undef:" << macro->isUndef();
//Note defined macros
if( m_environmentFile )
m_environmentFile->addDefinedMacro(*macro, hadMacro);
if( !macro->isUndef() )
m_macroNameSet.insert(macro->name);
else
m_macroNameSet.remove(macro->name);
rpp::Environment::setMacro(macro);
}
int CppPreprocessEnvironment::type() const {
return KDevelop::CppParsingEnvironment;
}
const Cpp::ReferenceCountedStringSet& CppPreprocessEnvironment::macroNameSet() const {
return m_macroNameSet;
}
void CppPreprocessEnvironment::setIdentityOffsetRestriction(uint value) {
m_identityOffsetRestriction = value;
m_identityOffsetRestrictionEnabled = true;
}
void CppPreprocessEnvironment::disableIdentityOffsetRestriction() {
m_identityOffsetRestrictionEnabled = false;
}
bool CppPreprocessEnvironment::identityOffsetRestrictionEnabled() const {
return m_identityOffsetRestrictionEnabled;
}
uint CppPreprocessEnvironment::identityOffsetRestriction() const {
return m_identityOffsetRestriction;
}
|