| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323 | 
							- /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
 
-    file LICENSE.rst or https://cmake.org/licensing for details.  */
 
- #include "cmConfigureLog.h"
 
- #include <cassert>
 
- #include <cstdio>
 
- #include <iterator>
 
- #include <sstream>
 
- #include <utility>
 
- #include <cmext/algorithm>
 
- #include <cmext/string_view>
 
- #include <cm3p/json/writer.h>
 
- #include "cm_utf8.h"
 
- #include "cmListFileCache.h"
 
- #include "cmMakefile.h"
 
- #include "cmRange.h"
 
- #include "cmStringAlgorithms.h"
 
- #include "cmSystemTools.h"
 
- #include "cmake.h"
 
- cmConfigureLog::cmConfigureLog(std::string logDir,
 
-                                std::vector<unsigned int> logVersions)
 
-   : LogDir(std::move(logDir))
 
-   , LogVersions(std::move(logVersions))
 
- {
 
-   // Always emit events for the latest log version.
 
-   static unsigned int const LatestLogVersion = 1;
 
-   if (!cm::contains(this->LogVersions, LatestLogVersion)) {
 
-     this->LogVersions.emplace_back(LatestLogVersion);
 
-   }
 
-   Json::StreamWriterBuilder builder;
 
-   this->Encoder.reset(builder.newStreamWriter());
 
- }
 
- cmConfigureLog::~cmConfigureLog()
 
- {
 
-   if (this->Opened) {
 
-     this->EndObject();
 
-     this->Stream << "...\n";
 
-   }
 
- }
 
- bool cmConfigureLog::IsAnyLogVersionEnabled(
 
-   std::vector<unsigned int> const& v) const
 
- {
 
-   // Both input lists are sorted.  Look for a matching element.
 
-   auto i1 = v.cbegin();
 
-   auto i2 = this->LogVersions.cbegin();
 
-   while (i1 != v.cend() && i2 != this->LogVersions.cend()) {
 
-     if (*i1 < *i2) {
 
-       ++i1;
 
-     } else if (*i2 < *i1) {
 
-       ++i2;
 
-     } else {
 
-       return true;
 
-     }
 
-   }
 
-   return false;
 
- }
 
- void cmConfigureLog::WriteBacktrace(cmMakefile const& mf)
 
- {
 
-   std::vector<std::string> backtrace;
 
-   auto root = mf.GetCMakeInstance()->GetHomeDirectory();
 
-   for (auto bt = mf.GetBacktrace(); !bt.Empty(); bt = bt.Pop()) {
 
-     auto t = bt.Top();
 
-     if (!t.Name.empty() || t.Line == cmListFileContext::DeferPlaceholderLine) {
 
-       t.FilePath = cmSystemTools::RelativeIfUnder(root, t.FilePath);
 
-       std::ostringstream s;
 
-       s << t;
 
-       backtrace.emplace_back(s.str());
 
-     }
 
-   }
 
-   this->WriteValue("backtrace"_s, backtrace);
 
- }
 
- void cmConfigureLog::WriteChecks(cmMakefile const& mf)
 
- {
 
-   if (!mf.GetCMakeInstance()->HasCheckInProgress()) {
 
-     return;
 
-   }
 
-   this->BeginObject("checks"_s);
 
-   for (auto const& value :
 
-        cmReverseRange(mf.GetCMakeInstance()->GetCheckInProgressMessages())) {
 
-     this->BeginLine() << "- ";
 
-     this->Encoder->write(value, &this->Stream);
 
-     this->EndLine();
 
-   }
 
-   this->EndObject();
 
- }
 
- void cmConfigureLog::EnsureInit()
 
- {
 
-   if (this->Opened) {
 
-     return;
 
-   }
 
-   assert(!this->Stream.is_open());
 
-   std::string name = cmStrCat(this->LogDir, "/CMakeConfigureLog.yaml");
 
-   this->Stream.open(name.c_str(), std::ios::out | std::ios::app);
 
-   this->Opened = true;
 
-   this->Stream << "\n---\n";
 
-   this->BeginObject("events"_s);
 
- }
 
- cmsys::ofstream& cmConfigureLog::BeginLine()
 
- {
 
-   for (unsigned i = 0; i < this->Indent; ++i) {
 
-     this->Stream << "  ";
 
-   }
 
-   return this->Stream;
 
- }
 
- void cmConfigureLog::EndLine()
 
- {
 
-   this->Stream << std::endl;
 
- }
 
- void cmConfigureLog::BeginArray()
 
- {
 
-   ++this->Indent;
 
- }
 
- void cmConfigureLog::NextArrayElement()
 
- {
 
-   assert(this->Indent);
 
-   --this->Indent;
 
-   this->BeginLine() << '-';
 
-   this->EndLine();
 
-   ++this->Indent;
 
- }
 
- void cmConfigureLog::EndArray()
 
- {
 
-   assert(this->Indent);
 
-   --this->Indent;
 
- }
 
- void cmConfigureLog::BeginObject(cm::string_view key)
 
- {
 
-   this->BeginLine() << key << ':';
 
-   this->EndLine();
 
-   ++this->Indent;
 
- }
 
- void cmConfigureLog::EndObject()
 
- {
 
-   assert(this->Indent);
 
-   --this->Indent;
 
- }
 
- void cmConfigureLog::BeginEvent(std::string const& kind, cmMakefile const& mf)
 
- {
 
-   this->EnsureInit();
 
-   this->BeginLine() << '-';
 
-   this->EndLine();
 
-   ++this->Indent;
 
-   this->WriteValue("kind"_s, kind);
 
-   this->WriteBacktrace(mf);
 
-   this->WriteChecks(mf);
 
- }
 
- void cmConfigureLog::EndEvent()
 
- {
 
-   assert(this->Indent);
 
-   --this->Indent;
 
- }
 
- void cmConfigureLog::WriteValue(cm::string_view key, std::nullptr_t)
 
- {
 
-   this->BeginLine() << key << ": null";
 
-   this->EndLine();
 
- }
 
- void cmConfigureLog::WriteValue(cm::string_view key, bool value)
 
- {
 
-   this->BeginLine() << key << ": " << (value ? "true" : "false");
 
-   this->EndLine();
 
- }
 
- void cmConfigureLog::WriteValue(cm::string_view key, int value)
 
- {
 
-   this->BeginLine() << key << ": " << value;
 
-   this->EndLine();
 
- }
 
- void cmConfigureLog::WriteValue(cm::string_view key, std::string const& value)
 
- {
 
-   this->BeginLine() << key << ": ";
 
-   this->Encoder->write(value, &this->Stream);
 
-   this->EndLine();
 
- }
 
- void cmConfigureLog::WriteValue(cm::string_view key,
 
-                                 std::vector<std::string> const& list)
 
- {
 
-   this->BeginObject(key);
 
-   for (auto const& value : list) {
 
-     this->BeginLine() << "- ";
 
-     this->Encoder->write(value, &this->Stream);
 
-     this->EndLine();
 
-   }
 
-   this->EndObject();
 
- }
 
- void cmConfigureLog::WriteValue(cm::string_view key,
 
-                                 std::map<std::string, std::string> const& map)
 
- {
 
-   static std::string const rawKeyChars = //
 
-     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"         //
 
-     "abcdefghijklmnopqrstuvwxyz"         //
 
-     "0123456789"                         //
 
-     "-_"                                 //
 
-     ;
 
-   this->BeginObject(key);
 
-   for (auto const& entry : map) {
 
-     if (entry.first.find_first_not_of(rawKeyChars) == std::string::npos) {
 
-       this->WriteValue(entry.first, entry.second);
 
-     } else {
 
-       this->BeginLine();
 
-       this->Encoder->write(entry.first, &this->Stream);
 
-       this->Stream << ": ";
 
-       this->Encoder->write(entry.second, &this->Stream);
 
-       this->EndLine();
 
-     }
 
-   }
 
-   this->EndObject();
 
- }
 
- void cmConfigureLog::WriteLiteralTextBlock(cm::string_view key,
 
-                                            cm::string_view text)
 
- {
 
-   this->BeginLine() << key << ": |";
 
-   this->EndLine();
 
-   auto const l = text.length();
 
-   if (l) {
 
-     ++this->Indent;
 
-     this->BeginLine();
 
-     auto i = decltype(l){ 0 };
 
-     while (i < l) {
 
-       // YAML allows ' ', '\t' and "printable characters", but NOT other
 
-       // ASCII whitespace; those must be escaped, as must the upper UNICODE
 
-       // control characters (U+0080 - U+009F)
 
-       static constexpr unsigned int C1_LAST = 0x9F;
 
-       auto const c = static_cast<unsigned char>(text[i]);
 
-       switch (c) {
 
-         case '\r':
 
-           // Print a carriage return only if it is not followed by a line feed.
 
-           ++i;
 
-           if (i == l || text[i] != '\n') {
 
-             this->WriteEscape(c);
 
-           }
 
-           break;
 
-         case '\n':
 
-           // Print any line feeds except the very last one
 
-           if (i + 1 < l) {
 
-             this->EndLine();
 
-             this->BeginLine();
 
-           }
 
-           ++i;
 
-           break;
 
-         case '\t':
 
-           // Print horizontal tab verbatim
 
-           this->Stream.put('\t');
 
-           ++i;
 
-           break;
 
-         case '\\':
 
-           // Escape backslash for disambiguation
 
-           this->Stream << "\\\\";
 
-           ++i;
 
-           break;
 
-         default:
 
-           if (c >= 32 && c < 127) {
 
-             // Print ascii byte.
 
-             this->Stream.put(text[i]);
 
-             ++i;
 
-             break;
 
-           } else if (c > 127) {
 
-             // Decode a UTF-8 sequence.
 
-             unsigned int c32;
 
-             auto const* const s = text.data() + i;
 
-             auto const* const e = text.data() + l;
 
-             auto const* const n = cm_utf8_decode_character(s, e, &c32);
 
-             if (n > s && c32 > C1_LAST) {
 
-               auto const k = std::distance(s, n);
 
-               this->Stream.write(s, static_cast<std::streamsize>(k));
 
-               i += static_cast<unsigned>(k);
 
-               break;
 
-             }
 
-           }
 
-           // Escape non-printable byte.
 
-           this->WriteEscape(c);
 
-           ++i;
 
-           break;
 
-       }
 
-     }
 
-     this->EndLine();
 
-     --this->Indent;
 
-   }
 
- }
 
- void cmConfigureLog::WriteEscape(unsigned char c)
 
- {
 
-   char buffer[6];
 
-   int n = snprintf(buffer, sizeof(buffer), "\\x%02x", c);
 
-   if (n > 0) {
 
-     this->Stream.write(buffer, n);
 
-   }
 
- }
 
 
  |