summaryrefslogtreecommitdiffstats
path: root/Source/cmGccDepfileLexerHelper.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmGccDepfileLexerHelper.cxx')
-rw-r--r--Source/cmGccDepfileLexerHelper.cxx126
1 files changed, 126 insertions, 0 deletions
diff --git a/Source/cmGccDepfileLexerHelper.cxx b/Source/cmGccDepfileLexerHelper.cxx
new file mode 100644
index 0000000..957896f
--- /dev/null
+++ b/Source/cmGccDepfileLexerHelper.cxx
@@ -0,0 +1,126 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmGccDepfileLexerHelper.h"
+
+#include <cstdio>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "cmGccDepfileReaderTypes.h"
+
+#include "LexerParser/cmGccDepfileLexer.h"
+
+#ifdef _WIN32
+# include "cmsys/Encoding.h"
+#endif
+
+bool cmGccDepfileLexerHelper::readFile(const char* filePath)
+{
+#ifdef _WIN32
+ wchar_t* wpath = cmsysEncoding_DupToWide(filePath);
+ FILE* file = _wfopen(wpath, L"rb");
+ free(wpath);
+#else
+ FILE* file = fopen(filePath, "r");
+#endif
+ if (!file) {
+ return false;
+ }
+ newEntry();
+ yyscan_t scanner;
+ cmGccDepfile_yylex_init(&scanner);
+ cmGccDepfile_yyset_extra(this, scanner);
+ cmGccDepfile_yyrestart(file, scanner);
+ cmGccDepfile_yylex(scanner);
+ cmGccDepfile_yylex_destroy(scanner);
+ sanitizeContent();
+ fclose(file);
+ return true;
+}
+
+void cmGccDepfileLexerHelper::newEntry()
+{
+ this->HelperState = State::Rule;
+ this->Content.emplace_back();
+ newRule();
+}
+
+void cmGccDepfileLexerHelper::newRule()
+{
+ auto& entry = this->Content.back();
+ if (entry.rules.empty() || !entry.rules.back().empty()) {
+ entry.rules.emplace_back();
+ }
+}
+
+void cmGccDepfileLexerHelper::newDependency()
+{
+ // printf("NEW DEP\n");
+ this->HelperState = State::Dependency;
+ if (this->Content.back().paths.empty() ||
+ !this->Content.back().paths.back().empty()) {
+ this->Content.back().paths.emplace_back();
+ }
+}
+
+void cmGccDepfileLexerHelper::newRuleOrDependency()
+{
+ if (this->HelperState == State::Rule) {
+ newRule();
+ } else {
+ newDependency();
+ }
+}
+
+void cmGccDepfileLexerHelper::addToCurrentPath(const char* s)
+{
+ if (this->Content.empty()) {
+ return;
+ }
+ cmGccStyleDependency* dep = &this->Content.back();
+ std::string* dst = nullptr;
+ switch (this->HelperState) {
+ case State::Rule: {
+ if (dep->rules.empty()) {
+ return;
+ }
+ dst = &dep->rules.back();
+ } break;
+ case State::Dependency: {
+ if (dep->paths.empty()) {
+ return;
+ }
+ dst = &dep->paths.back();
+ } break;
+ }
+ dst->append(s);
+}
+
+void cmGccDepfileLexerHelper::sanitizeContent()
+{
+ for (auto it = this->Content.begin(); it != this->Content.end();) {
+ // Remove empty rules
+ for (auto rit = it->rules.begin(); rit != it->rules.end();) {
+ if (rit->empty()) {
+ rit = it->rules.erase(rit);
+ } else {
+ ++rit;
+ }
+ }
+ // Remove the entry if rules are empty
+ if (it->rules.empty()) {
+ it = this->Content.erase(it);
+ } else {
+ // Remove empty paths
+ for (auto pit = it->paths.begin(); pit != it->paths.end();) {
+ if (pit->empty()) {
+ pit = it->paths.erase(pit);
+ } else {
+ ++pit;
+ }
+ }
+ ++it;
+ }
+ }
+}