Warning, file /sdk/umbrello/lib/cppparser/macro.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-FileCopyrightText: 2006 David Nolden <david.nolden.kdevelop@art-master.de> 0003 SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 0006 #ifndef MACRO_H 0007 #define MACRO_H 0008 0009 #include <qpair.h> 0010 #include <QStringList> 0011 #include <QString> 0012 #include <qdatastream.h> 0013 #include <qmap.h> 0014 #include <qdatetime.h> 0015 #include <map> 0016 #include <set> 0017 #include <hashedstring.h> 0018 #include <kdatastream.h> 0019 #include <codemodel.h> 0020 0021 typedef signed char Q_INT8; 0022 0023 //This files should be renamed to something like "helpers.h" 0024 0025 /** 0026 * Encapsulates a problem in a piece of source code. 0027 */ 0028 class Problem 0029 { 0030 public: 0031 enum { 0032 Level_Error = 0, ///< Indicates an error that will prevent the code from compiling 0033 Level_Warning, ///< Indicates a warning 0034 Level_Todo, ///< Indicates there is still something left to do 0035 Level_Fixme ///< Indicates that something needs to be fixed 0036 }; 0037 0038 public: 0039 Problem() {} 0040 Problem(const Problem& source) 0041 : m_text(source.m_text), m_line(source.m_line), 0042 m_column(source.m_column), m_level(source.m_level), m_file(source.m_file) {} 0043 Problem(const QString& text, int line, int column, int level = Level_Error) 0044 : m_text(text), m_line(line), m_column(column), m_level(level) {} 0045 0046 Problem(const Problem& source, bool /*threadSafeClone*/) 0047 : m_text(QString::fromUtf8(source.m_text.toUtf8().data())), m_line(source.m_line), 0048 m_column(source.m_column), m_level(source.m_level), m_file(QString::fromUtf8(source.m_file.toUtf8().data())) {} 0049 0050 Problem& operator = (const Problem& source) 0051 { 0052 m_text = source.m_text; 0053 m_line = source.m_line; 0054 m_column = source.m_column; 0055 m_level = source.m_level; 0056 m_file = source.m_file; 0057 return (*this); 0058 } 0059 0060 void setFileName(const QString& fileName) 0061 { 0062 m_file = fileName; 0063 } 0064 0065 bool operator == (const Problem& p) const 0066 { 0067 return m_text == p.m_text && m_line == p.m_line && m_column == p.m_column && m_level == p.m_level && m_file == p.m_file; 0068 } 0069 0070 /** Get the filename in which the problem was encountered */ 0071 QString fileName() const 0072 { 0073 return m_file; 0074 } 0075 0076 /** Get the text for the problem */ 0077 QString text() const 0078 { 0079 return m_text; 0080 } 0081 /** Get the line number of the problem */ 0082 int line() const 0083 { 0084 return m_line; 0085 } 0086 /** Get the column of the problem */ 0087 int column() const 0088 { 0089 return m_column; 0090 } 0091 /** 0092 * Get the seriousness of the problem. There are four possibilities: 0093 * \li Error 0094 * \li Warning 0095 * \li Todo 0096 * \li Fixme 0097 */ 0098 int level() const 0099 { 0100 return m_level; 0101 } 0102 0103 private: 0104 QString m_text; 0105 int m_line; 0106 int m_column; 0107 int m_level; 0108 QString m_file; 0109 }; 0110 0111 0112 /** 0113 * A datatype that represents a preprocessor macro. 0114 * Most of the functions in this class need to be inline, so we do not have to import cppparser to many modules. The other solution would be moving macro into interfaces. 0115 */ 0116 class Macro 0117 { 0118 public: 0119 typedef QString Argument; 0120 0121 public: 0122 explicit Macro(bool hasArguments = false) 0123 : m_idHashValid(false), 0124 m_valueHashValid(false), 0125 m_idHash(0), 0126 m_valueHash(0), 0127 m_line(0), 0128 m_column(0), 0129 m_hasArguments(hasArguments), 0130 m_isUndefMacro(false) 0131 {} 0132 Macro(const QString &n, const QString &b) 0133 : m_idHashValid(false), 0134 m_valueHashValid(false), 0135 m_idHash(0), 0136 m_valueHash(0), 0137 m_name(n), 0138 m_line(0), 0139 m_column(0), 0140 m_body(b), 0141 m_hasArguments(false), 0142 m_isUndefMacro(false) 0143 {} 0144 0145 //Sorts the macros by their hash-value, then by their name. 0146 class NameArgCompare { 0147 public: 0148 bool operator () (const Macro& lhs, const Macro& rhs) const 0149 { 0150 size_t lhash = lhs.idHash(); 0151 size_t rhash = rhs.idHash(); 0152 if (lhash < rhash) return true; 0153 else if (lhash > rhash) return false; 0154 0155 int df = lhs.m_name.compare(rhs.m_name); 0156 if (df < 0) 0157 return true; 0158 if (df == 0) { 0159 if (!lhs.m_hasArguments && rhs.m_hasArguments) { 0160 return true; 0161 } else if (lhs.m_hasArguments == rhs.m_hasArguments) { 0162 return lhs.m_argumentList.count() < rhs.m_argumentList.count(); 0163 0164 } else { 0165 return false; 0166 } 0167 } 0168 return false; 0169 } 0170 }; 0171 class NameCompare { 0172 public: 0173 bool operator () (const Macro& lhs, const Macro& rhs) const 0174 { 0175 size_t lhash = lhs.idHash(); 0176 size_t rhash = rhs.idHash(); 0177 if (lhash < rhash) return true; 0178 else if (lhash > rhash) return false; 0179 0180 int df = lhs.m_name.compare(rhs.m_name); 0181 return df < 0; 0182 } 0183 }; 0184 0185 class NameArgHash { 0186 public: 0187 size_t operator () (const Macro& macro) const 0188 { 0189 return macro.idHash(); 0190 } 0191 }; 0192 0193 class NameArgEqual { 0194 public: 0195 bool operator () (const Macro& lhs, const Macro& rhs) const 0196 { 0197 int df = lhs.m_name.compare(rhs.m_name); 0198 if (df == 0) { 0199 if (lhs.m_hasArguments != rhs.m_hasArguments) { 0200 return false; 0201 } else { 0202 if (lhs.m_argumentList.count() != rhs.m_argumentList.count()) return false; 0203 /*QStringList::const_iterator it2 = rhs.m_argumentList.begin(); 0204 for(QStringList::const_iterator it = lhs.m_argumentList.begin(); it != lhs.m_argumentList.end();) { 0205 if(*it != *it2) return false; 0206 0207 ++it; 0208 ++it2; 0209 }*/ 0210 return true; 0211 0212 } 0213 } 0214 return false; 0215 } 0216 }; 0217 0218 Macro(const Macro& source) 0219 : m_idHashValid(source.m_idHashValid), 0220 m_valueHashValid(source.m_valueHashValid), 0221 m_idHash(source.m_idHash), 0222 m_valueHash(source.m_valueHash), 0223 m_name(source.m_name), 0224 m_fileName(source.m_fileName), 0225 m_line(source.m_line), 0226 m_column(source.m_column), 0227 m_body(source.m_body), 0228 m_hasArguments(source.m_hasArguments), 0229 m_argumentList(source.m_argumentList), 0230 m_isUndefMacro(source.m_isUndefMacro) 0231 {} 0232 0233 Macro& operator = (const Macro& source) 0234 { 0235 m_idHashValid = source.m_idHashValid; 0236 m_valueHashValid = source.m_valueHashValid; 0237 m_idHash = source.m_idHash; 0238 m_valueHash = source.m_valueHash; 0239 m_name = source.m_name; 0240 m_fileName = source.m_fileName; 0241 m_line = source.m_line; 0242 m_column = source.m_column; 0243 m_body = source.m_body; 0244 m_hasArguments = source.m_hasArguments; 0245 m_argumentList = source.m_argumentList; 0246 m_isUndefMacro = source.m_isUndefMacro; 0247 return *this; 0248 } 0249 0250 bool operator == (const Macro& source) const 0251 { 0252 if (!m_idHashValid || !m_valueHashValid) computeHash(); 0253 if (!source.m_idHashValid || !source.m_valueHashValid) source.computeHash(); 0254 0255 if (m_idHash != source.m_idHash) return false; 0256 if (m_valueHash != source.m_valueHash) return false; 0257 0258 return m_name == source.m_name && 0259 m_fileName == source.m_fileName && 0260 m_body == source.m_body && 0261 m_hasArguments == source.m_hasArguments && 0262 m_argumentList == source.m_argumentList && m_isUndefMacro == source.m_isUndefMacro; 0263 } 0264 0265 void read(QDataStream& stream) 0266 { 0267 Q_INT8 i; 0268 stream >> i; 0269 m_idHashValid = i; 0270 stream >> i; 0271 m_valueHashValid = i; 0272 stream >> i; 0273 m_hasArguments = i; 0274 0275 stream >> m_idHash; 0276 stream >> m_valueHash; 0277 stream >> m_name; 0278 stream >> m_line; 0279 stream >> m_column; 0280 stream >> m_body; 0281 stream >> m_fileName; 0282 stream >> m_argumentList; 0283 } 0284 0285 void write(QDataStream& stream) const 0286 { 0287 Q_INT8 i; 0288 i = m_idHashValid; 0289 stream << i; 0290 i = m_valueHashValid; 0291 stream << i; 0292 i = m_hasArguments; 0293 stream << i; 0294 0295 stream << m_idHash; 0296 stream << m_valueHash; 0297 stream << m_name; 0298 stream << m_line; 0299 stream << m_column; 0300 stream << m_body; 0301 stream << m_fileName; 0302 stream << m_argumentList; 0303 } 0304 0305 /** Get the name for this macro */ 0306 QString name() const 0307 { 0308 return m_name; 0309 } 0310 /** Set the name for this macro */ 0311 void setName(const QString& name) 0312 { 0313 m_name = name; 0314 invalidateHash(); 0315 } 0316 0317 /** Get the file name that contains this macro */ 0318 QString fileName() const 0319 { 0320 return m_fileName; 0321 } 0322 /** Set the file name that contains this macro */ 0323 void setFileName(const QString& fileName) 0324 { 0325 m_fileName = fileName; 0326 invalidateHash(); 0327 } 0328 0329 /** Get the line the macro is defined on */ 0330 int line() const 0331 { 0332 return m_line; 0333 } 0334 /** Set the line the macro is defined on */ 0335 void setLine(int line) 0336 { 0337 m_line = line; 0338 } 0339 0340 /** Get the column the macro starts at */ 0341 int column() const 0342 { 0343 return m_column; 0344 } 0345 /** Set the column the macro starts at */ 0346 void setColumn(int column) 0347 { 0348 m_column = column; 0349 } 0350 0351 /** Get the body of the macro */ 0352 QString body() const 0353 { 0354 return m_body; 0355 } 0356 /** Set the body of the macro */ 0357 void setBody(const QString& body) 0358 { 0359 m_body = body; 0360 invalidateHash(); 0361 } 0362 0363 /** This is used so the lexer does not have to remove macros that should really stay(they are just temporarily shadowed by an isUndef-macro */ 0364 bool isUndef() const 0365 { 0366 return m_isUndefMacro; 0367 }; 0368 0369 void setUndef() 0370 { 0371 m_isUndefMacro = true; 0372 invalidateHash(); 0373 }; 0374 0375 /** Check whether the macro has arguments that are passed to it */ 0376 bool hasArguments() const 0377 { 0378 return m_hasArguments; 0379 } 0380 void setHasArguments(bool hasArguments) 0381 { 0382 m_hasArguments = hasArguments; 0383 invalidateHash(); 0384 } 0385 /** Get a list of arguments passed to this macro */ 0386 QList<Argument> argumentList() const 0387 { 0388 return m_argumentList; 0389 } 0390 0391 /** Clear the list of arguments this macro has */ 0392 void clearArgumentList() 0393 { 0394 m_argumentList.clear(); 0395 m_hasArguments = false; 0396 invalidateHash(); 0397 } 0398 /** Add an argument to this macro */ 0399 void addArgument(const Argument& argument) 0400 { 0401 m_argumentList << argument; 0402 } 0403 /** Add a list of arguments to this macro */ 0404 void addArgumentList(const QList<Argument>& arguments) 0405 { 0406 m_argumentList += arguments; 0407 invalidateHash(); 0408 } 0409 0410 ///This hash respects macro-name and argument-count 0411 size_t idHash() const 0412 { 0413 if (!m_idHashValid) computeHash(); 0414 return m_idHash; 0415 } 0416 0417 ///This hash respects body and if it is an undef-macro 0418 size_t valueHash() const 0419 { 0420 if (!m_valueHashValid) computeHash(); 0421 return m_valueHash; 0422 } 0423 0424 private: 0425 inline void invalidateHash() const 0426 { 0427 m_idHashValid = m_valueHashValid = false; 0428 } 0429 0430 void computeHash() const 0431 { 0432 m_idHash = 7 * (HashedString::hashString(m_name)); 0433 int a = 1; 0434 //m_idHash += 31 * m_argumentList.count(); 0435 0436 m_valueHash = 27 * (HashedString::hashString(m_body) + (m_isUndefMacro ? 1 : 0)); 0437 0438 for (QList<Argument>::const_iterator it = m_argumentList.begin(); it != m_argumentList.end(); ++it) { 0439 a *= 19; 0440 m_valueHash += a * HashedString::hashString(*it); 0441 } 0442 m_valueHashValid = true; 0443 m_idHashValid = true; 0444 } 0445 0446 mutable bool m_idHashValid; 0447 mutable bool m_valueHashValid; 0448 mutable size_t m_idHash; //Hash that represents the ids of all macros 0449 mutable size_t m_valueHash; //Hash that represents the values of all macros 0450 0451 QString m_name; 0452 QString m_fileName; 0453 int m_line; 0454 int m_column; 0455 QString m_body; 0456 bool m_hasArguments; 0457 QStringList m_argumentList; //While identification, only the count plays a role, not the values. 0458 bool m_isUndefMacro; 0459 friend class NameCompare; 0460 friend class NameArgEqual; 0461 }; 0462 0463 class MacroSet 0464 { 0465 public: 0466 //typedef __gnu_cxx::hash_set< Macro, Macro::NameArgHash, Macro::NameArgEqual > Macros; 0467 typedef std::set< Macro, Macro::NameCompare > Macros; 0468 MacroSet() 0469 : m_idHashValid(false), 0470 m_valueHashValid(false), 0471 m_idHash(0), 0472 m_valueHash(0) 0473 { 0474 } 0475 0476 void addMacro(const Macro& macro); 0477 0478 void read(QDataStream& stream) 0479 { 0480 //stream >> m_idHashValid >> m_idHash >> m_valueHashValid >> m_valueHash; 0481 m_idHashValid = false; 0482 m_valueHashValid = false; 0483 int cnt; 0484 stream >> cnt; 0485 m_usedMacros.clear(); 0486 Macro m; 0487 for (int a = 0; a < cnt; a++) { 0488 m.read(stream); 0489 m_usedMacros.insert(m); 0490 } 0491 } 0492 0493 void write(QDataStream& stream) const 0494 { 0495 //stream << m_idHashValid << m_idHash << m_valueHashValid << m_valueHash; 0496 stream << int(m_usedMacros.size()); 0497 for (Macros::const_iterator it = m_usedMacros.begin(); it != m_usedMacros.end(); ++it) { 0498 (*it).write(stream); 0499 } 0500 } 0501 0502 bool hasMacro(const QString& name) const; 0503 bool hasMacro(const HashedString& name) const; 0504 Macro macro(const QString& name) const; 0505 0506 size_t idHash() const; 0507 size_t valueHash() const; 0508 0509 const Macros& macros() const 0510 { 0511 return m_usedMacros; 0512 } 0513 0514 void merge(const MacroSet& macros); 0515 private: 0516 void computeHash() const; 0517 Macros m_usedMacros; 0518 mutable bool m_idHashValid; 0519 mutable bool m_valueHashValid; 0520 mutable size_t m_idHash; //Hash that represents the ids of all macros 0521 mutable size_t m_valueHash; //Hash that represents the values of all macros 0522 0523 friend class Driver; 0524 }; 0525 0526 #endif