Cppcheck
projectfile.cpp
Go to the documentation of this file.
1 /*
2  * Cppcheck - A tool for static C/C++ code analysis
3  * Copyright (C) 2007-2024 Cppcheck team.
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include "projectfile.h"
20 
21 #include "common.h"
22 #include "config.h"
23 #include "importproject.h"
24 #include "settings.h"
25 #include "utils.h"
26 
27 #include <utility>
28 
29 #include <QFile>
30 #include <QDir>
31 #include <QIODevice>
32 #include <QLatin1String>
33 #include <QRegularExpression>
34 #include <QXmlStreamAttributes>
35 #include <QXmlStreamReader>
36 #include <QXmlStreamWriter>
37 
38 #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
39 #include <QStringRef>
40 #endif
41 
43 
44 ProjectFile::ProjectFile(QObject *parent) :
45  QObject(parent)
46 {
47  clear();
48 }
49 
50 ProjectFile::ProjectFile(QString filename, QObject *parent) :
51  QObject(parent),
52  mFilename(std::move(filename))
53 {
54  clear();
55  read();
56 }
57 
59 {
60  const Settings settings;
61  clangParser = false;
63  mRootPath.clear();
64  mBuildDir.clear();
65  mImportProject.clear();
66  mIncludeDirs.clear();
67  mDefines.clear();
68  mUndefines.clear();
69  mPaths.clear();
70  mExcludedPaths.clear();
71  mLibraries.clear();
72  mPlatform.clear();
73  mProjectName.clear();
74  mSuppressions.clear();
75  mAddons.clear();
76  mClangAnalyzer = mClangTidy = false;
77  mAnalyzeAllVsConfigs = false;
78  mCheckHeaders = true;
79  mCheckUnusedTemplates = true;
80  mMaxCtuDepth = settings.maxCtuDepth;
83  safeChecks.clear();
84  mVsConfigurations.clear();
85  mTags.clear();
86  mWarningTags.clear();
87 
88  // Premium
89  mBughunting = false;
91  mCodingStandards.clear();
92 }
93 
94 bool ProjectFile::read(const QString &filename)
95 {
96  if (!filename.isEmpty())
97  mFilename = filename;
98 
99  QFile file(mFilename);
100  if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
101  return false;
102 
103  clear();
104 
105  QXmlStreamReader xmlReader(&file);
106  bool insideProject = false;
107  bool projectTagFound = false;
108  while (!xmlReader.atEnd()) {
109  switch (xmlReader.readNext()) {
110  case QXmlStreamReader::StartElement:
111  if (xmlReader.name() == QString(CppcheckXml::ProjectElementName)) {
112  insideProject = true;
113  projectTagFound = true;
114  break;
115  }
116  if (!insideProject)
117  break;
118 
119  // Read root path from inside project element
120  if (xmlReader.name() == QString(CppcheckXml::RootPathName))
121  readRootPath(xmlReader);
122 
123  // Read root path from inside project element
124  if (xmlReader.name() == QString(CppcheckXml::BuildDirElementName))
125  readBuildDir(xmlReader);
126 
127  // Find paths to check from inside project element
128  if (xmlReader.name() == QString(CppcheckXml::PathsElementName))
129  readCheckPaths(xmlReader);
130 
131  if (xmlReader.name() == QString(CppcheckXml::ImportProjectElementName))
132  readImportProject(xmlReader);
133 
134  if (xmlReader.name() == QString(CppcheckXml::AnalyzeAllVsConfigsElementName))
135  mAnalyzeAllVsConfigs = readBool(xmlReader);
136 
137  if (xmlReader.name() == QString(CppcheckXml::Parser))
138  clangParser = true;
139 
140  if (xmlReader.name() == QString(CppcheckXml::CheckHeadersElementName))
141  mCheckHeaders = readBool(xmlReader);
142 
143  if (xmlReader.name() == QString(CppcheckXml::CheckUnusedTemplatesElementName))
144  mCheckUnusedTemplates = readBool(xmlReader);
145 
146  if (xmlReader.name() == QString(CppcheckXml::CheckLevelExhaustiveElementName))
148 
149  // Find include directory from inside project element
150  if (xmlReader.name() == QString(CppcheckXml::IncludeDirElementName))
151  readIncludeDirs(xmlReader);
152 
153  // Find preprocessor define from inside project element
154  if (xmlReader.name() == QString(CppcheckXml::DefinesElementName))
155  readDefines(xmlReader);
156 
157  // Find preprocessor define from inside project element
158  if (xmlReader.name() == QString(CppcheckXml::UndefinesElementName))
160 
161  // Find exclude list from inside project element
162  if (xmlReader.name() == QString(CppcheckXml::ExcludeElementName))
163  readExcludes(xmlReader);
164 
165  // Find ignore list from inside project element
166  // These are read for compatibility
167  if (xmlReader.name() == QString(CppcheckXml::IgnoreElementName))
168  readExcludes(xmlReader);
169 
170  // Find libraries list from inside project element
171  if (xmlReader.name() == QString(CppcheckXml::LibrariesElementName))
173 
174  if (xmlReader.name() == QString(CppcheckXml::PlatformElementName))
175  readPlatform(xmlReader);
176 
177  // Find suppressions list from inside project element
178  if (xmlReader.name() == QString(CppcheckXml::SuppressionsElementName))
179  readSuppressions(xmlReader);
180 
181  // Unknown function return values
182  if (xmlReader.name() == QString(CppcheckXml::CheckUnknownFunctionReturn))
184 
185  // check all function parameter values
186  if (xmlReader.name() == QString(Settings::SafeChecks::XmlRootName))
187  safeChecks.loadFromXml(xmlReader);
188 
189  // Addons
190  if (xmlReader.name() == QString(CppcheckXml::AddonsElementName))
192 
193  // Tools
194  if (xmlReader.name() == QString(CppcheckXml::ToolsElementName)) {
195  QStringList tools;
196  readStringList(tools, xmlReader, CppcheckXml::ToolElementName);
197  mClangAnalyzer = tools.contains(CLANG_ANALYZER);
198  mClangTidy = tools.contains(CLANG_TIDY);
199  }
200 
201  if (xmlReader.name() == QString(CppcheckXml::TagsElementName))
203 
204  if (xmlReader.name() == QString(CppcheckXml::TagWarningsElementName))
205  readTagWarnings(xmlReader, xmlReader.attributes().value(QString(), CppcheckXml::TagAttributeName).toString());
206 
207  if (xmlReader.name() == QString(CppcheckXml::MaxCtuDepthElementName))
208  mMaxCtuDepth = readInt(xmlReader, mMaxCtuDepth);
209 
210  if (xmlReader.name() == QString(CppcheckXml::MaxTemplateRecursionElementName))
212 
213  // VSConfiguration
214  if (xmlReader.name() == QString(CppcheckXml::VSConfigurationElementName))
215  readVsConfigurations(xmlReader);
216 
217  // Cppcheck Premium
218  if (xmlReader.name() == QString(CppcheckXml::BughuntingElementName))
219  mBughunting = true;
220  if (xmlReader.name() == QString(CppcheckXml::CodingStandardsElementName))
222  if (xmlReader.name() == QString(CppcheckXml::CertIntPrecisionElementName))
223  mCertIntPrecision = readInt(xmlReader, 0);
224  if (xmlReader.name() == QString(CppcheckXml::ProjectNameElementName))
225  mProjectName = readString(xmlReader);
226 
227  break;
228 
229  case QXmlStreamReader::EndElement:
230  if (xmlReader.name() == QString(CppcheckXml::ProjectElementName))
231  insideProject = false;
232  break;
233 
234  // Not handled
235  case QXmlStreamReader::NoToken:
236  case QXmlStreamReader::Invalid:
237  case QXmlStreamReader::StartDocument:
238  case QXmlStreamReader::EndDocument:
239  case QXmlStreamReader::Characters:
240  case QXmlStreamReader::Comment:
241  case QXmlStreamReader::DTD:
242  case QXmlStreamReader::EntityReference:
243  case QXmlStreamReader::ProcessingInstruction:
244  break;
245  }
246  }
247 
248  file.close();
249  return projectTagFound;
250 }
251 
252 void ProjectFile::readRootPath(const QXmlStreamReader &reader)
253 {
254  QXmlStreamAttributes attribs = reader.attributes();
255  QString name = attribs.value(QString(), CppcheckXml::RootPathNameAttrib).toString();
256  if (!name.isEmpty())
257  mRootPath = name;
258 }
259 
260 void ProjectFile::readBuildDir(QXmlStreamReader &reader)
261 {
262  mBuildDir.clear();
263  do {
264  const QXmlStreamReader::TokenType type = reader.readNext();
265  switch (type) {
266  case QXmlStreamReader::Characters:
267  mBuildDir = reader.text().toString();
268  FALLTHROUGH;
269  case QXmlStreamReader::EndElement:
270  return;
271  // Not handled
272  case QXmlStreamReader::StartElement:
273  case QXmlStreamReader::NoToken:
274  case QXmlStreamReader::Invalid:
275  case QXmlStreamReader::StartDocument:
276  case QXmlStreamReader::EndDocument:
277  case QXmlStreamReader::Comment:
278  case QXmlStreamReader::DTD:
279  case QXmlStreamReader::EntityReference:
280  case QXmlStreamReader::ProcessingInstruction:
281  break;
282  }
283  } while (true);
284 }
285 
286 void ProjectFile::readImportProject(QXmlStreamReader &reader)
287 {
288  mImportProject.clear();
289  do {
290  const QXmlStreamReader::TokenType type = reader.readNext();
291  switch (type) {
292  case QXmlStreamReader::Characters:
293  mImportProject = reader.text().toString();
294  FALLTHROUGH;
295  case QXmlStreamReader::EndElement:
296  return;
297  // Not handled
298  case QXmlStreamReader::StartElement:
299  case QXmlStreamReader::NoToken:
300  case QXmlStreamReader::Invalid:
301  case QXmlStreamReader::StartDocument:
302  case QXmlStreamReader::EndDocument:
303  case QXmlStreamReader::Comment:
304  case QXmlStreamReader::DTD:
305  case QXmlStreamReader::EntityReference:
306  case QXmlStreamReader::ProcessingInstruction:
307  break;
308  }
309  } while (true);
310 }
311 
312 bool ProjectFile::readBool(QXmlStreamReader &reader)
313 {
314  bool ret = false;
315  do {
316  const QXmlStreamReader::TokenType type = reader.readNext();
317  switch (type) {
318  case QXmlStreamReader::Characters:
319  ret = (reader.text().toString() == "true");
320  FALLTHROUGH;
321  case QXmlStreamReader::EndElement:
322  return ret;
323  // Not handled
324  case QXmlStreamReader::StartElement:
325  case QXmlStreamReader::NoToken:
326  case QXmlStreamReader::Invalid:
327  case QXmlStreamReader::StartDocument:
328  case QXmlStreamReader::EndDocument:
329  case QXmlStreamReader::Comment:
330  case QXmlStreamReader::DTD:
331  case QXmlStreamReader::EntityReference:
332  case QXmlStreamReader::ProcessingInstruction:
333  break;
334  }
335  } while (true);
336 }
337 
338 int ProjectFile::readInt(QXmlStreamReader &reader, int defaultValue)
339 {
340  int ret = defaultValue;
341  do {
342  const QXmlStreamReader::TokenType type = reader.readNext();
343  switch (type) {
344  case QXmlStreamReader::Characters:
345  ret = reader.text().toString().toInt();
346  FALLTHROUGH;
347  case QXmlStreamReader::EndElement:
348  return ret;
349  // Not handled
350  case QXmlStreamReader::StartElement:
351  case QXmlStreamReader::NoToken:
352  case QXmlStreamReader::Invalid:
353  case QXmlStreamReader::StartDocument:
354  case QXmlStreamReader::EndDocument:
355  case QXmlStreamReader::Comment:
356  case QXmlStreamReader::DTD:
357  case QXmlStreamReader::EntityReference:
358  case QXmlStreamReader::ProcessingInstruction:
359  break;
360  }
361  } while (true);
362 }
363 
364 QString ProjectFile::readString(QXmlStreamReader &reader)
365 {
366  QString ret;
367  do {
368  const QXmlStreamReader::TokenType type = reader.readNext();
369  switch (type) {
370  case QXmlStreamReader::Characters:
371  ret = reader.text().toString();
372  FALLTHROUGH;
373  case QXmlStreamReader::EndElement:
374  return ret;
375  // Not handled
376  case QXmlStreamReader::StartElement:
377  case QXmlStreamReader::NoToken:
378  case QXmlStreamReader::Invalid:
379  case QXmlStreamReader::StartDocument:
380  case QXmlStreamReader::EndDocument:
381  case QXmlStreamReader::Comment:
382  case QXmlStreamReader::DTD:
383  case QXmlStreamReader::EntityReference:
384  case QXmlStreamReader::ProcessingInstruction:
385  break;
386  }
387  } while (true);
388 }
389 
390 void ProjectFile::readIncludeDirs(QXmlStreamReader &reader)
391 {
392  bool allRead = false;
393  do {
394  QXmlStreamReader::TokenType type = reader.readNext();
395  switch (type) {
396  case QXmlStreamReader::StartElement:
397 
398  // Read dir-elements
399  if (reader.name().toString() == CppcheckXml::DirElementName) {
400  QXmlStreamAttributes attribs = reader.attributes();
401  QString name = attribs.value(QString(), CppcheckXml::DirNameAttrib).toString();
402  if (!name.isEmpty())
403  mIncludeDirs << name;
404  }
405  break;
406 
407  case QXmlStreamReader::EndElement:
408  if (reader.name().toString() == CppcheckXml::IncludeDirElementName)
409  allRead = true;
410  break;
411 
412  // Not handled
413  case QXmlStreamReader::NoToken:
414  case QXmlStreamReader::Invalid:
415  case QXmlStreamReader::StartDocument:
416  case QXmlStreamReader::EndDocument:
417  case QXmlStreamReader::Characters:
418  case QXmlStreamReader::Comment:
419  case QXmlStreamReader::DTD:
420  case QXmlStreamReader::EntityReference:
421  case QXmlStreamReader::ProcessingInstruction:
422  break;
423  }
424  } while (!allRead);
425 }
426 
427 void ProjectFile::readDefines(QXmlStreamReader &reader)
428 {
429  bool allRead = false;
430  do {
431  QXmlStreamReader::TokenType type = reader.readNext();
432  switch (type) {
433  case QXmlStreamReader::StartElement:
434  // Read define-elements
435  if (reader.name().toString() == CppcheckXml::DefineName) {
436  QXmlStreamAttributes attribs = reader.attributes();
437  QString name = attribs.value(QString(), CppcheckXml::DefineNameAttrib).toString();
438  if (!name.isEmpty())
439  mDefines << name;
440  }
441  break;
442 
443  case QXmlStreamReader::EndElement:
444  if (reader.name().toString() == CppcheckXml::DefinesElementName)
445  allRead = true;
446  break;
447 
448  // Not handled
449  case QXmlStreamReader::NoToken:
450  case QXmlStreamReader::Invalid:
451  case QXmlStreamReader::StartDocument:
452  case QXmlStreamReader::EndDocument:
453  case QXmlStreamReader::Characters:
454  case QXmlStreamReader::Comment:
455  case QXmlStreamReader::DTD:
456  case QXmlStreamReader::EntityReference:
457  case QXmlStreamReader::ProcessingInstruction:
458  break;
459  }
460  } while (!allRead);
461 }
462 
463 void ProjectFile::readCheckPaths(QXmlStreamReader &reader)
464 {
465  bool allRead = false;
466  do {
467  QXmlStreamReader::TokenType type = reader.readNext();
468  switch (type) {
469  case QXmlStreamReader::StartElement:
470 
471  // Read dir-elements
472  if (reader.name().toString() == CppcheckXml::PathName) {
473  QXmlStreamAttributes attribs = reader.attributes();
474  QString name = attribs.value(QString(), CppcheckXml::PathNameAttrib).toString();
475  if (!name.isEmpty())
476  mPaths << name;
477  }
478  break;
479 
480  case QXmlStreamReader::EndElement:
481  if (reader.name().toString() == CppcheckXml::PathsElementName)
482  allRead = true;
483  break;
484 
485  // Not handled
486  case QXmlStreamReader::NoToken:
487  case QXmlStreamReader::Invalid:
488  case QXmlStreamReader::StartDocument:
489  case QXmlStreamReader::EndDocument:
490  case QXmlStreamReader::Characters:
491  case QXmlStreamReader::Comment:
492  case QXmlStreamReader::DTD:
493  case QXmlStreamReader::EntityReference:
494  case QXmlStreamReader::ProcessingInstruction:
495  break;
496  }
497  } while (!allRead);
498 }
499 
500 void ProjectFile::readExcludes(QXmlStreamReader &reader)
501 {
502  bool allRead = false;
503  do {
504  QXmlStreamReader::TokenType type = reader.readNext();
505  switch (type) {
506  case QXmlStreamReader::StartElement:
507  // Read exclude-elements
508  if (reader.name().toString() == CppcheckXml::ExcludePathName) {
509  QXmlStreamAttributes attribs = reader.attributes();
510  QString name = attribs.value(QString(), CppcheckXml::ExcludePathNameAttrib).toString();
511  if (!name.isEmpty())
512  mExcludedPaths << name;
513  }
514  // Read ignore-elements - deprecated but support reading them
515  else if (reader.name().toString() == CppcheckXml::IgnorePathName) {
516  QXmlStreamAttributes attribs = reader.attributes();
517  QString name = attribs.value(QString(), CppcheckXml::IgnorePathNameAttrib).toString();
518  if (!name.isEmpty())
519  mExcludedPaths << name;
520  }
521  break;
522 
523  case QXmlStreamReader::EndElement:
524  if (reader.name().toString() == CppcheckXml::IgnoreElementName)
525  allRead = true;
526  if (reader.name().toString() == CppcheckXml::ExcludeElementName)
527  allRead = true;
528  break;
529 
530  // Not handled
531  case QXmlStreamReader::NoToken:
532  case QXmlStreamReader::Invalid:
533  case QXmlStreamReader::StartDocument:
534  case QXmlStreamReader::EndDocument:
535  case QXmlStreamReader::Characters:
536  case QXmlStreamReader::Comment:
537  case QXmlStreamReader::DTD:
538  case QXmlStreamReader::EntityReference:
539  case QXmlStreamReader::ProcessingInstruction:
540  break;
541  }
542  } while (!allRead);
543 }
544 
545 void ProjectFile::readVsConfigurations(QXmlStreamReader &reader)
546 {
547  do {
548  QXmlStreamReader::TokenType type = reader.readNext();
549  switch (type) {
550  case QXmlStreamReader::StartElement:
551  // Read library-elements
552  if (reader.name().toString() == CppcheckXml::VSConfigurationName) {
553  QString config;
554  type = reader.readNext();
555  if (type == QXmlStreamReader::Characters) {
556  config = reader.text().toString();
557  }
558  mVsConfigurations << config;
559  }
560  break;
561 
562  case QXmlStreamReader::EndElement:
563  if (reader.name().toString() != CppcheckXml::VSConfigurationName)
564  return;
565  break;
566 
567  // Not handled
568  case QXmlStreamReader::NoToken:
569  case QXmlStreamReader::Invalid:
570  case QXmlStreamReader::StartDocument:
571  case QXmlStreamReader::EndDocument:
572  case QXmlStreamReader::Characters:
573  case QXmlStreamReader::Comment:
574  case QXmlStreamReader::DTD:
575  case QXmlStreamReader::EntityReference:
576  case QXmlStreamReader::ProcessingInstruction:
577  break;
578  }
579  } while (true);
580 }
581 
582 void ProjectFile::readPlatform(QXmlStreamReader &reader)
583 {
584  do {
585  const QXmlStreamReader::TokenType type = reader.readNext();
586  switch (type) {
587  case QXmlStreamReader::Characters:
588  mPlatform = reader.text().toString();
589  FALLTHROUGH;
590  case QXmlStreamReader::EndElement:
591  return;
592  // Not handled
593  case QXmlStreamReader::StartElement:
594  case QXmlStreamReader::NoToken:
595  case QXmlStreamReader::Invalid:
596  case QXmlStreamReader::StartDocument:
597  case QXmlStreamReader::EndDocument:
598  case QXmlStreamReader::Comment:
599  case QXmlStreamReader::DTD:
600  case QXmlStreamReader::EntityReference:
601  case QXmlStreamReader::ProcessingInstruction:
602  break;
603  }
604  } while (true);
605 }
606 
607 
608 void ProjectFile::readSuppressions(QXmlStreamReader &reader)
609 {
610  do {
611  QXmlStreamReader::TokenType type = reader.readNext();
612  switch (type) {
613  case QXmlStreamReader::StartElement:
614  // Read library-elements
615  if (reader.name().toString() == CppcheckXml::SuppressionElementName) {
616  SuppressionList::Suppression suppression;
617  if (reader.attributes().hasAttribute(QString(),"fileName"))
618  suppression.fileName = reader.attributes().value(QString(),"fileName").toString().toStdString();
619  if (reader.attributes().hasAttribute(QString(),"lineNumber"))
620  suppression.lineNumber = reader.attributes().value(QString(),"lineNumber").toInt();
621  if (reader.attributes().hasAttribute(QString(),"symbolName"))
622  suppression.symbolName = reader.attributes().value(QString(),"symbolName").toString().toStdString();
623  if (reader.attributes().hasAttribute(QString(),"hash"))
624  suppression.hash = reader.attributes().value(QString(),"hash").toULongLong();
625  type = reader.readNext();
626  if (type == QXmlStreamReader::Characters) {
627  suppression.errorId = reader.text().toString().toStdString();
628  }
629  mSuppressions << suppression;
630  }
631  break;
632 
633  case QXmlStreamReader::EndElement:
634  if (reader.name().toString() != CppcheckXml::SuppressionElementName)
635  return;
636  break;
637 
638  // Not handled
639  case QXmlStreamReader::NoToken:
640  case QXmlStreamReader::Invalid:
641  case QXmlStreamReader::StartDocument:
642  case QXmlStreamReader::EndDocument:
643  case QXmlStreamReader::Characters:
644  case QXmlStreamReader::Comment:
645  case QXmlStreamReader::DTD:
646  case QXmlStreamReader::EntityReference:
647  case QXmlStreamReader::ProcessingInstruction:
648  break;
649  }
650  } while (true);
651 }
652 
653 
654 void ProjectFile::readTagWarnings(QXmlStreamReader &reader, const QString &tag)
655 {
656  do {
657  QXmlStreamReader::TokenType type = reader.readNext();
658  switch (type) {
659  case QXmlStreamReader::StartElement:
660  // Read library-elements
661  if (reader.name().toString() == CppcheckXml::WarningElementName) {
662  const std::size_t hash = reader.attributes().value(QString(), CppcheckXml::HashAttributeName).toULongLong();
663  mWarningTags[hash] = tag;
664  }
665  break;
666 
667  case QXmlStreamReader::EndElement:
668  if (reader.name().toString() != CppcheckXml::WarningElementName)
669  return;
670  break;
671 
672  // Not handled
673  case QXmlStreamReader::NoToken:
674  case QXmlStreamReader::Invalid:
675  case QXmlStreamReader::StartDocument:
676  case QXmlStreamReader::EndDocument:
677  case QXmlStreamReader::Characters:
678  case QXmlStreamReader::Comment:
679  case QXmlStreamReader::DTD:
680  case QXmlStreamReader::EntityReference:
681  case QXmlStreamReader::ProcessingInstruction:
682  break;
683  }
684  } while (true);
685 }
686 
687 
688 void ProjectFile::readStringList(QStringList &stringlist, QXmlStreamReader &reader, const char elementname[])
689 {
690  bool allRead = false;
691  do {
692  QXmlStreamReader::TokenType type = reader.readNext();
693  switch (type) {
694  case QXmlStreamReader::StartElement:
695  // Read library-elements
696  if (reader.name().toString() == elementname) {
697  type = reader.readNext();
698  if (type == QXmlStreamReader::Characters) {
699  QString text = reader.text().toString();
700  stringlist << text;
701  }
702  }
703  break;
704 
705  case QXmlStreamReader::EndElement:
706  if (reader.name().toString() != elementname)
707  allRead = true;
708  break;
709 
710  // Not handled
711  case QXmlStreamReader::NoToken:
712  case QXmlStreamReader::Invalid:
713  case QXmlStreamReader::StartDocument:
714  case QXmlStreamReader::EndDocument:
715  case QXmlStreamReader::Characters:
716  case QXmlStreamReader::Comment:
717  case QXmlStreamReader::DTD:
718  case QXmlStreamReader::EntityReference:
719  case QXmlStreamReader::ProcessingInstruction:
720  break;
721  }
722  } while (!allRead);
723 }
724 
725 void ProjectFile::setIncludes(const QStringList &includes)
726 {
727  mIncludeDirs = includes;
728 }
729 
730 void ProjectFile::setDefines(const QStringList &defines)
731 {
732  mDefines = defines;
733 }
734 
735 void ProjectFile::setUndefines(const QStringList &undefines)
736 {
737  mUndefines = undefines;
738 }
739 
740 void ProjectFile::setCheckPaths(const QStringList &paths)
741 {
742  mPaths = paths;
743 }
744 
745 void ProjectFile::setExcludedPaths(const QStringList &paths)
746 {
747  mExcludedPaths = paths;
748 }
749 
750 void ProjectFile::setLibraries(const QStringList &libraries)
751 {
752  mLibraries = libraries;
753 }
754 
755 void ProjectFile::setPlatform(const QString &platform)
756 {
757  mPlatform = platform;
758 }
759 
760 QList<SuppressionList::Suppression> ProjectFile::getCheckingSuppressions() const
761 {
762  const QRegularExpression re1("^[a-zA-Z0-9_\\-]+/.*");
763  const QRegularExpression re2("^[^/]+$");
764  QList<SuppressionList::Suppression> result;
765  for (SuppressionList::Suppression suppression : mSuppressions) {
766  if (re1.match(suppression.fileName.c_str()).hasMatch() || re2.match(suppression.fileName.c_str()).hasMatch()) {
767  if (suppression.fileName[0] != '*')
768  suppression.fileName = QFileInfo(mFilename).absolutePath().toStdString() + "/" + suppression.fileName;
769  }
770  result << suppression;
771  }
772  return result;
773 }
774 
775 void ProjectFile::setSuppressions(const QList<SuppressionList::Suppression> &suppressions)
776 {
777  mSuppressions = suppressions;
778 }
779 
781 {
782  mSuppressions.append(suppression);
783 }
784 
785 void ProjectFile::setAddons(const QStringList &addons)
786 {
787  mAddons = addons;
788 }
789 
790 void ProjectFile::setVSConfigurations(const QStringList &vsConfigs)
791 {
792  mVsConfigurations = vsConfigs;
793 }
794 
796 {
797  mCheckLevel = checkLevel;
798 }
799 
801 {
803 }
804 
805 void ProjectFile::setWarningTags(std::size_t hash, const QString& tags)
806 {
807  if (tags.isEmpty())
808  mWarningTags.erase(hash);
809  else if (hash > 0)
810  mWarningTags[hash] = tags;
811 }
812 
813 QString ProjectFile::getWarningTags(std::size_t hash) const
814 {
815  auto it = mWarningTags.find(hash);
816  return (it != mWarningTags.end()) ? it->second : QString();
817 }
818 
819 bool ProjectFile::write(const QString &filename)
820 {
821  if (!filename.isEmpty())
822  mFilename = filename;
823 
824  QFile file(mFilename);
825  if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
826  return false;
827 
828  QXmlStreamWriter xmlWriter(&file);
829  xmlWriter.setAutoFormatting(true);
830  xmlWriter.writeStartDocument("1.0");
831  xmlWriter.writeStartElement(CppcheckXml::ProjectElementName);
833 
834  if (!mRootPath.isEmpty()) {
835  xmlWriter.writeStartElement(CppcheckXml::RootPathName);
836  xmlWriter.writeAttribute(CppcheckXml::RootPathNameAttrib, mRootPath);
837  xmlWriter.writeEndElement();
838  }
839 
840  if (!mBuildDir.isEmpty()) {
841  xmlWriter.writeStartElement(CppcheckXml::BuildDirElementName);
842  xmlWriter.writeCharacters(mBuildDir);
843  xmlWriter.writeEndElement();
844  }
845 
846  if (!mPlatform.isEmpty()) {
847  xmlWriter.writeStartElement(CppcheckXml::PlatformElementName);
848  xmlWriter.writeCharacters(mPlatform);
849  xmlWriter.writeEndElement();
850  }
851 
852  if (!mImportProject.isEmpty()) {
853  xmlWriter.writeStartElement(CppcheckXml::ImportProjectElementName);
854  xmlWriter.writeCharacters(mImportProject);
855  xmlWriter.writeEndElement();
856  }
857 
858  xmlWriter.writeStartElement(CppcheckXml::AnalyzeAllVsConfigsElementName);
859  xmlWriter.writeCharacters(bool_to_string(mAnalyzeAllVsConfigs));
860  xmlWriter.writeEndElement();
861 
862  if (clangParser) {
863  xmlWriter.writeStartElement(CppcheckXml::Parser);
864  xmlWriter.writeCharacters("clang");
865  xmlWriter.writeEndElement();
866  }
867 
868  xmlWriter.writeStartElement(CppcheckXml::CheckHeadersElementName);
869  xmlWriter.writeCharacters(bool_to_string(mCheckHeaders));
870  xmlWriter.writeEndElement();
871 
872  xmlWriter.writeStartElement(CppcheckXml::CheckUnusedTemplatesElementName);
873  xmlWriter.writeCharacters(bool_to_string(mCheckUnusedTemplates));
874  xmlWriter.writeEndElement();
875 
876  xmlWriter.writeStartElement(CppcheckXml::MaxCtuDepthElementName);
877  xmlWriter.writeCharacters(QString::number(mMaxCtuDepth));
878  xmlWriter.writeEndElement();
879 
880  xmlWriter.writeStartElement(CppcheckXml::MaxTemplateRecursionElementName);
881  xmlWriter.writeCharacters(QString::number(mMaxTemplateRecursion));
882  xmlWriter.writeEndElement();
883 
884  if (!mIncludeDirs.isEmpty()) {
885  xmlWriter.writeStartElement(CppcheckXml::IncludeDirElementName);
886  for (const QString& incdir : mIncludeDirs) {
887  xmlWriter.writeStartElement(CppcheckXml::DirElementName);
888  xmlWriter.writeAttribute(CppcheckXml::DirNameAttrib, incdir);
889  xmlWriter.writeEndElement();
890  }
891  xmlWriter.writeEndElement();
892  }
893 
894  if (!mDefines.isEmpty()) {
895  xmlWriter.writeStartElement(CppcheckXml::DefinesElementName);
896  for (const QString& define : mDefines) {
897  xmlWriter.writeStartElement(CppcheckXml::DefineName);
898  xmlWriter.writeAttribute(CppcheckXml::DefineNameAttrib, define);
899  xmlWriter.writeEndElement();
900  }
901  xmlWriter.writeEndElement();
902  }
903 
904  if (!mVsConfigurations.isEmpty()) {
905  writeStringList(xmlWriter,
909  }
910 
911  writeStringList(xmlWriter,
912  mUndefines,
915 
916  if (!mPaths.isEmpty()) {
917  xmlWriter.writeStartElement(CppcheckXml::PathsElementName);
918  for (const QString& path : mPaths) {
919  xmlWriter.writeStartElement(CppcheckXml::PathName);
920  xmlWriter.writeAttribute(CppcheckXml::PathNameAttrib, path);
921  xmlWriter.writeEndElement();
922  }
923  xmlWriter.writeEndElement();
924  }
925 
926  if (!mExcludedPaths.isEmpty()) {
927  xmlWriter.writeStartElement(CppcheckXml::ExcludeElementName);
928  for (const QString& path : mExcludedPaths) {
929  xmlWriter.writeStartElement(CppcheckXml::ExcludePathName);
930  xmlWriter.writeAttribute(CppcheckXml::ExcludePathNameAttrib, path);
931  xmlWriter.writeEndElement();
932  }
933  xmlWriter.writeEndElement();
934  }
935 
936  writeStringList(xmlWriter,
937  mLibraries,
940 
941  if (!mSuppressions.isEmpty()) {
942  xmlWriter.writeStartElement(CppcheckXml::SuppressionsElementName);
943  for (const SuppressionList::Suppression &suppression : mSuppressions) {
944  xmlWriter.writeStartElement(CppcheckXml::SuppressionElementName);
945  if (!suppression.fileName.empty())
946  xmlWriter.writeAttribute("fileName", QString::fromStdString(suppression.fileName));
947  if (suppression.lineNumber > 0)
948  xmlWriter.writeAttribute("lineNumber", QString::number(suppression.lineNumber));
949  if (!suppression.symbolName.empty())
950  xmlWriter.writeAttribute("symbolName", QString::fromStdString(suppression.symbolName));
951  if (suppression.hash > 0)
952  xmlWriter.writeAttribute(CppcheckXml::HashAttributeName, QString::number(suppression.hash));
953  if (!suppression.errorId.empty())
954  xmlWriter.writeCharacters(QString::fromStdString(suppression.errorId));
955  xmlWriter.writeEndElement();
956  }
957  xmlWriter.writeEndElement();
958  }
959 
960  writeStringList(xmlWriter,
964 
965  safeChecks.saveToXml(xmlWriter);
966 
967  writeStringList(xmlWriter,
968  mAddons,
971 
972  QStringList tools;
973  if (mClangAnalyzer)
974  tools << CLANG_ANALYZER;
975  if (mClangTidy)
976  tools << CLANG_TIDY;
977  writeStringList(xmlWriter,
978  tools,
981 
983  if (!mWarningTags.empty()) {
984  QStringList tags;
985  for (const auto& wt: mWarningTags) {
986  if (!tags.contains(wt.second))
987  tags.append(wt.second);
988  }
989  for (const QString &tag: tags) {
990  xmlWriter.writeStartElement(CppcheckXml::TagWarningsElementName);
991  xmlWriter.writeAttribute(CppcheckXml::TagAttributeName, tag);
992  for (const auto& wt: mWarningTags) {
993  if (wt.second == tag) {
994  xmlWriter.writeStartElement(CppcheckXml::WarningElementName);
995  xmlWriter.writeAttribute(CppcheckXml::HashAttributeName, QString::number(wt.first));
996  xmlWriter.writeEndElement();
997  }
998  }
999  xmlWriter.writeEndElement();
1000  }
1001  }
1002 
1004  xmlWriter.writeStartElement(CppcheckXml::CheckLevelExhaustiveElementName);
1005  xmlWriter.writeEndElement();
1006  }
1007 
1008  // Cppcheck Premium
1009  if (mBughunting) {
1010  xmlWriter.writeStartElement(CppcheckXml::BughuntingElementName);
1011  xmlWriter.writeEndElement();
1012  }
1013 
1014  writeStringList(xmlWriter,
1018 
1019  if (mCertIntPrecision > 0) {
1020  xmlWriter.writeStartElement(CppcheckXml::CertIntPrecisionElementName);
1021  xmlWriter.writeCharacters(QString::number(mCertIntPrecision));
1022  xmlWriter.writeEndElement();
1023  }
1024 
1025  if (!mProjectName.isEmpty()) {
1026  xmlWriter.writeStartElement(CppcheckXml::ProjectNameElementName);
1027  xmlWriter.writeCharacters(mProjectName);
1028  xmlWriter.writeEndElement();
1029  }
1030 
1031  xmlWriter.writeEndDocument();
1032  file.close();
1033  return true;
1034 }
1035 
1036 void ProjectFile::writeStringList(QXmlStreamWriter &xmlWriter, const QStringList &stringlist, const char startelementname[], const char stringelementname[])
1037 {
1038  if (stringlist.isEmpty())
1039  return;
1040 
1041  xmlWriter.writeStartElement(startelementname);
1042  for (const QString& str : stringlist) {
1043  xmlWriter.writeStartElement(stringelementname);
1044  xmlWriter.writeCharacters(str);
1045  xmlWriter.writeEndElement();
1046  }
1047  xmlWriter.writeEndElement();
1048 }
1049 
1050 QStringList ProjectFile::fromNativeSeparators(const QStringList &paths)
1051 {
1052  QStringList ret;
1053  for (const QString &path : paths)
1054  ret << QDir::fromNativeSeparators(path);
1055  return ret;
1056 }
1057 
1059 {
1060  QStringList ret(mAddons);
1061  if (mClangAnalyzer)
1062  ret << CLANG_ANALYZER;
1063  if (mClangTidy)
1064  ret << CLANG_TIDY;
1065  return ret;
1066 }
1067 
1068 void ProjectFile::SafeChecks::loadFromXml(QXmlStreamReader &xmlReader)
1069 {
1071 
1072  int level = 0;
1073 
1074  do {
1075  const QXmlStreamReader::TokenType type = xmlReader.readNext();
1076  switch (type) {
1077  case QXmlStreamReader::StartElement:
1078  ++level;
1079  if (xmlReader.name() == QString(Settings::SafeChecks::XmlClasses))
1080  classes = true;
1081  else if (xmlReader.name() == QString(Settings::SafeChecks::XmlExternalFunctions))
1082  externalFunctions = true;
1083  else if (xmlReader.name() == QString(Settings::SafeChecks::XmlInternalFunctions))
1084  internalFunctions = true;
1085  else if (xmlReader.name() == QString(Settings::SafeChecks::XmlExternalVariables))
1086  externalVariables = true;
1087  break;
1088  case QXmlStreamReader::EndElement:
1089  if (level <= 0)
1090  return;
1091  level--;
1092  break;
1093  // Not handled
1094  case QXmlStreamReader::Characters:
1095  case QXmlStreamReader::NoToken:
1096  case QXmlStreamReader::Invalid:
1097  case QXmlStreamReader::StartDocument:
1098  case QXmlStreamReader::EndDocument:
1099  case QXmlStreamReader::Comment:
1100  case QXmlStreamReader::DTD:
1101  case QXmlStreamReader::EntityReference:
1102  case QXmlStreamReader::ProcessingInstruction:
1103  break;
1104  }
1105  } while (true);
1106 }
1107 
1108 void ProjectFile::SafeChecks::saveToXml(QXmlStreamWriter &xmlWriter) const
1109 {
1110  if (!classes && !externalFunctions && !internalFunctions && !externalVariables)
1111  return;
1112  xmlWriter.writeStartElement(QString(Settings::SafeChecks::XmlRootName));
1113  if (classes) {
1114  xmlWriter.writeStartElement(QString(Settings::SafeChecks::XmlClasses));
1115  xmlWriter.writeEndElement();
1116  }
1117  if (externalFunctions) {
1118  xmlWriter.writeStartElement(QString(Settings::SafeChecks::XmlExternalFunctions));
1119  xmlWriter.writeEndElement();
1120  }
1121  if (internalFunctions) {
1122  xmlWriter.writeStartElement(QString(Settings::SafeChecks::XmlInternalFunctions));
1123  xmlWriter.writeEndElement();
1124  }
1125  if (externalVariables) {
1126  xmlWriter.writeStartElement(QString(Settings::SafeChecks::XmlExternalVariables));
1127  xmlWriter.writeEndElement();
1128  }
1129  xmlWriter.writeEndElement();
1130 }
1131 
1132 QString ProjectFile::getAddonFilePath(QString filesDir, const QString &addon)
1133 {
1134  if (QFile(addon).exists())
1135  return addon;
1136 
1137  if (!filesDir.endsWith("/"))
1138  filesDir += "/";
1139 
1140  QStringList searchPaths;
1141  searchPaths << filesDir << (filesDir + "addons/") << (filesDir + "../addons/")
1142 #ifdef FILESDIR
1143  << (QLatin1String(FILESDIR) + "/addons/")
1144 #endif
1145  ;
1146 
1147  for (const QString& path : searchPaths) {
1148  QString f = path + addon + ".py";
1149  if (QFile(f).exists())
1150  return f;
1151  }
1152 
1153  return QString();
1154 }
void loadFromXml(QXmlStreamReader &xmlReader)
void saveToXml(QXmlStreamWriter &xmlWriter) const
A class that reads and writes project files.
Definition: projectfile.h:46
std::map< std::size_t, QString > mWarningTags
Warning tags.
Definition: projectfile.h:635
SafeChecks safeChecks
Definition: projectfile.h:414
QStringList getAddonsAndTools() const
Get list of addons and tools.
bool mClangTidy
Execute clang-tidy?
Definition: projectfile.h:625
bool clangParser
Use Clang parser.
Definition: projectfile.h:427
static ProjectFile * mActiveProject
Definition: projectfile.h:645
QList< SuppressionList::Suppression > getCheckingSuppressions() const
Get "checking" suppressions.
void setCheckPaths(const QStringList &paths)
Set list of paths to check.
void setCheckLevel(CheckLevel checkLevel)
CheckLevel: normal/exhaustive.
QStringList mTags
Tags.
Definition: projectfile.h:630
void readDefines(QXmlStreamReader &reader)
Read list of defines from XML.
bool isCheckLevelExhaustive() const
ProjectFile(QObject *parent=nullptr)
Definition: projectfile.cpp:44
QString mFilename
Filename (+path) of the project file.
Definition: projectfile.h:528
QList< SuppressionList::Suppression > mSuppressions
List of suppressions.
Definition: projectfile.h:598
void readBuildDir(QXmlStreamReader &reader)
QStringList mExcludedPaths
Paths excluded from the check.
Definition: projectfile.h:583
QStringList mVsConfigurations
Check only a selected VS configuration.
Definition: projectfile.h:552
void clear()
Definition: projectfile.cpp:58
void readSuppressions(QXmlStreamReader &reader)
Read suppressions.
void readExcludes(QXmlStreamReader &reader)
Read lists of excluded paths.
static int readInt(QXmlStreamReader &reader, int defaultValue)
bool mCheckUnusedTemplates
Check code in unused templates.
Definition: projectfile.h:558
QStringList mCheckUnknownFunctionReturn
Definition: projectfile.h:643
void setExcludedPaths(const QStringList &paths)
Set list of paths to exclude from the check.
int mCertIntPrecision
Cppcheck Premium: This value is passed to the Cert C checker if that is enabled.
Definition: projectfile.h:619
void setVSConfigurations(const QStringList &vsConfigs)
Set list of Visual Studio configurations to be checked.
QStringList mDefines
List of defines.
Definition: projectfile.h:568
QString mImportProject
Visual studio project/solution , compile database.
Definition: projectfile.h:542
QString mRootPath
Root path (optional) for the project.
Definition: projectfile.h:536
QStringList mCodingStandards
List of coding standards, checked by Cppcheck Premium.
Definition: projectfile.h:613
void setDefines(const QStringList &defines)
Set list of defines.
void readTagWarnings(QXmlStreamReader &reader, const QString &tag)
Read tag warnings, what warnings are tagged with a specific tag.
static bool readBool(QXmlStreamReader &reader)
QString mPlatform
Platform.
Definition: projectfile.h:593
QString getWarningTags(std::size_t hash) const
Get tags for a warning.
static QStringList fromNativeSeparators(const QStringList &paths)
Convert paths.
void readCheckPaths(QXmlStreamReader &reader)
Read list paths to check.
static void writeStringList(QXmlStreamWriter &xmlWriter, const QStringList &stringlist, const char startelementname[], const char stringelementname[])
Write string list.
void setUndefines(const QStringList &undefines)
Set list of undefines.
bool mAnalyzeAllVsConfigs
Should all visual studio configurations be analyzed? If this is false then only the Debug configurati...
Definition: projectfile.h:549
void setIncludes(const QStringList &includes)
Set list of includes.
static void readStringList(QStringList &stringlist, QXmlStreamReader &reader, const char elementname[])
Read string list.
void readVsConfigurations(QXmlStreamReader &reader)
Read lists of Visual Studio configurations.
QStringList mAddons
List of addons.
Definition: projectfile.h:603
QStringList mUndefines
List of undefines.
Definition: projectfile.h:573
void setWarningTags(std::size_t hash, const QString &tags)
Set tags for a warning.
void setLibraries(const QStringList &libraries)
Set list of libraries.
static QString getAddonFilePath(QString filesDir, const QString &addon)
Get path to addon python script.
bool read(const QString &filename=QString())
Read the project file.
Definition: projectfile.cpp:94
void readIncludeDirs(QXmlStreamReader &reader)
Read list of include directories from XML.
QStringList mPaths
List of paths to check.
Definition: projectfile.h:578
bool mBughunting
Definition: projectfile.h:605
int mMaxTemplateRecursion
Max template instantiation recursion.
Definition: projectfile.h:641
void setAddons(const QStringList &addons)
Set list of addons.
void setPlatform(const QString &platform)
Set platform.
void addSuppression(const SuppressionList::Suppression &suppression)
Add suppression.
void readRootPath(const QXmlStreamReader &reader)
Read optional root path from XML.
QString mBuildDir
Cppcheck build dir.
Definition: projectfile.h:539
QStringList mIncludeDirs
List of include directories used to search include files.
Definition: projectfile.h:563
void readPlatform(QXmlStreamReader &reader)
Read platform text.
int mMaxCtuDepth
Max CTU depth.
Definition: projectfile.h:638
QStringList mLibraries
List of libraries.
Definition: projectfile.h:588
bool mClangAnalyzer
Execute clang analyzer?
Definition: projectfile.h:622
bool write(const QString &filename=QString())
Write project file (to disk).
static QString readString(QXmlStreamReader &reader)
void readImportProject(QXmlStreamReader &reader)
Read importproject from XML.
void setSuppressions(const QList< SuppressionList::Suppression > &suppressions)
Set list of suppressions.
bool mCheckHeaders
Check code in headers.
Definition: projectfile.h:555
QString mProjectName
Project name, used when generating compliance report.
Definition: projectfile.h:616
CheckLevel mCheckLevel
Should Cppcheck run normal or exhaustive analysis?
Definition: projectfile.h:608
This is just a container for general settings so that we don't need to pass individual values to func...
Definition: settings.h:95
int maxCtuDepth
–max-ctu-depth
Definition: settings.h:247
int maxTemplateRecursion
max template recursion
Definition: settings.h:250
std::string toString(Color c)
Definition: color.cpp:54
#define FALLTHROUGH
Definition: config.h:91
#define CLANG_TIDY
Definition: common.h:29
#define CLANG_ANALYZER
Definition: common.h:28
static constexpr char RootPathName[]
static constexpr char VSConfigurationName[]
static constexpr char DirElementName[]
static constexpr char DefineName[]
static constexpr char ExcludePathNameAttrib[]
static constexpr char PathsElementName[]
static constexpr char DefinesElementName[]
static constexpr char LibrariesElementName[]
static constexpr char ToolsElementName[]
static constexpr char IncludeDirElementName[]
static constexpr char ExcludeElementName[]
static constexpr char ProjectElementName[]
static constexpr char CertIntPrecisionElementName[]
static constexpr char PlatformElementName[]
static constexpr char TagsElementName[]
static constexpr char RootPathNameAttrib[]
static constexpr char CodingStandardElementName[]
static constexpr char IgnorePathNameAttrib[]
static constexpr char CodingStandardsElementName[]
static constexpr char AddonsElementName[]
static constexpr char UndefinesElementName[]
static constexpr char ImportProjectElementName[]
static constexpr char Parser[]
static constexpr char BughuntingElementName[]
static constexpr char AddonElementName[]
static constexpr char ProjectVersionAttrib[]
static constexpr char CheckUnknownFunctionReturn[]
static constexpr char TagWarningsElementName[]
static constexpr char TagAttributeName[]
static constexpr char WarningElementName[]
static constexpr char DefineNameAttrib[]
static constexpr char AnalyzeAllVsConfigsElementName[]
static constexpr char TagElementName[]
static constexpr char ProjectNameElementName[]
static constexpr char BuildDirElementName[]
static constexpr char MaxTemplateRecursionElementName[]
static constexpr char ExcludePathName[]
static constexpr char CheckUnusedTemplatesElementName[]
static constexpr char VSConfigurationElementName[]
static constexpr char CheckLevelExhaustiveElementName[]
static constexpr char DirNameAttrib[]
static constexpr char MaxCtuDepthElementName[]
static constexpr char UndefineName[]
static constexpr char HashAttributeName[]
static constexpr char SuppressionElementName[]
static constexpr char Name[]
static constexpr char IgnoreElementName[]
static constexpr char IgnorePathName[]
static constexpr char ProjectFileVersion[]
static constexpr char ToolElementName[]
static constexpr char SuppressionsElementName[]
static constexpr char CheckHeadersElementName[]
static constexpr char PathName[]
static constexpr char PathNameAttrib[]
static constexpr char LibraryElementName[]
bool classes
Public interface of classes.
Definition: settings.h:334
static const char XmlExternalFunctions[]
Definition: settings.h:320
static const char XmlInternalFunctions[]
Definition: settings.h:321
bool externalVariables
Global variables that can be modified outside the TU.
Definition: settings.h:353
static const char XmlClasses[]
Definition: settings.h:319
static const char XmlRootName[]
Definition: settings.h:318
static const char XmlExternalVariables[]
Definition: settings.h:322
bool externalFunctions
External functions.
Definition: settings.h:341
bool internalFunctions
Experimental: assume that internal functions can be used in any way This is only available in the GUI...
Definition: settings.h:347
static const char * bool_to_string(bool b)
Definition: utils.h:345