WithColor::WithColor(raw_ostream &OS, enum HighlightColor Type) : OS(OS) { // Detect color from terminal type unless the user passed the --color option. if (UseColor == cl::BOU_UNSET ? OS.has_colors() : UseColor == cl::BOU_TRUE) { switch (Type) { case Address: OS.changeColor(raw_ostream::YELLOW); break; case String: OS.changeColor(raw_ostream::GREEN); break; case Tag: OS.changeColor(raw_ostream::BLUE); break; case Attribute: OS.changeColor(raw_ostream::CYAN); break; case Enumerator: OS.changeColor(raw_ostream::MAGENTA); break; case Macro: OS.changeColor(raw_ostream::RED); break; case Error: OS.changeColor(raw_ostream::RED, true); break; case Warning: OS.changeColor(raw_ostream::MAGENTA, true); break; case Note: OS.changeColor(raw_ostream::BLACK, true); break; } } }
void SchedulerStatistics::printSchedulerStats(raw_ostream &OS) const { OS << "\n\nSchedulers - " << "number of cycles where we saw N instructions issued:\n"; OS << "[# issued], [# cycles]\n"; const auto It = std::max_element(IssuedPerCycle.begin(), IssuedPerCycle.end()); unsigned Index = std::distance(IssuedPerCycle.begin(), It); bool HasColors = OS.has_colors(); for (unsigned I = 0, E = IssuedPerCycle.size(); I < E; ++I) { unsigned IPC = IssuedPerCycle[I]; if (!IPC) continue; if (I == Index && HasColors) OS.changeColor(raw_ostream::SAVEDCOLOR, true, false); OS << " " << I << ", " << IPC << " (" << format("%.1f", ((double)IPC / NumCycles) * 100) << "%)\n"; if (HasColors) OS.resetColor(); } }
void SMDiagnostic::print(const char *ProgName, raw_ostream &S, bool ShowColors, bool ShowKindLabel) const { // Display colors only if OS supports colors. ShowColors &= S.has_colors(); if (ShowColors) S.changeColor(raw_ostream::SAVEDCOLOR, true); if (ProgName && ProgName[0]) S << ProgName << ": "; if (!Filename.empty()) { if (Filename == "-") S << "<stdin>"; else S << Filename; if (LineNo != -1) { S << ':' << LineNo; if (ColumnNo != -1) S << ':' << (ColumnNo+1); } S << ": "; } if (ShowKindLabel) { switch (Kind) { case SourceMgr::DK_Error: if (ShowColors) S.changeColor(raw_ostream::RED, true); S << "error: "; break; case SourceMgr::DK_Warning: if (ShowColors) S.changeColor(raw_ostream::MAGENTA, true); S << "warning: "; break; case SourceMgr::DK_Note: if (ShowColors) S.changeColor(raw_ostream::BLACK, true); S << "note: "; break; } if (ShowColors) { S.resetColor(); S.changeColor(raw_ostream::SAVEDCOLOR, true); } } S << Message << '\n'; if (ShowColors) S.resetColor(); if (LineNo == -1 || ColumnNo == -1) return; // FIXME: If there are multibyte or multi-column characters in the source, all // our ranges will be wrong. To do this properly, we'll need a byte-to-column // map like Clang's TextDiagnostic. For now, we'll just handle tabs by // expanding them later, and bail out rather than show incorrect ranges and // misaligned fixits for any other odd characters. if (std::find_if(LineContents.begin(), LineContents.end(), isNonASCII) != LineContents.end()) { printSourceLine(S, LineContents); return; } size_t NumColumns = LineContents.size(); // Build the line with the caret and ranges. std::string CaretLine(NumColumns+1, ' '); // Expand any ranges. for (unsigned r = 0, e = Ranges.size(); r != e; ++r) { std::pair<unsigned, unsigned> R = Ranges[r]; std::fill(&CaretLine[R.first], &CaretLine[std::min((size_t)R.second, CaretLine.size())], '~'); } // Add any fix-its. // FIXME: Find the beginning of the line properly for multibyte characters. std::string FixItInsertionLine; buildFixItLine(CaretLine, FixItInsertionLine, FixIts, makeArrayRef(Loc.getPointer() - ColumnNo, LineContents.size())); // Finally, plop on the caret. if (unsigned(ColumnNo) <= NumColumns) CaretLine[ColumnNo] = '^'; else CaretLine[NumColumns] = '^'; // ... and remove trailing whitespace so the output doesn't wrap for it. We // know that the line isn't completely empty because it has the caret in it at // least. CaretLine.erase(CaretLine.find_last_not_of(' ')+1); printSourceLine(S, LineContents); if (ShowColors) S.changeColor(raw_ostream::GREEN, true); // Print out the caret line, matching tabs in the source line. for (unsigned i = 0, e = CaretLine.size(), OutCol = 0; i != e; ++i) { if (i >= LineContents.size() || LineContents[i] != '\t') { S << CaretLine[i]; ++OutCol; continue; } // Okay, we have a tab. Insert the appropriate number of characters. do { S << CaretLine[i]; ++OutCol; } while ((OutCol % TabStop) != 0); } S << '\n'; if (ShowColors) S.resetColor(); // Print out the replacement line, matching tabs in the source line. if (FixItInsertionLine.empty()) return; for (size_t i = 0, e = FixItInsertionLine.size(), OutCol = 0; i < e; ++i) { if (i >= LineContents.size() || LineContents[i] != '\t') { S << FixItInsertionLine[i]; ++OutCol; continue; } // Okay, we have a tab. Insert the appropriate number of characters. do { S << FixItInsertionLine[i]; // FIXME: This is trying not to break up replacements, but then to re-sync // with the tabs between replacements. This will fail, though, if two // fix-it replacements are exactly adjacent, or if a fix-it contains a // space. Really we should be precomputing column widths, which we'll // need anyway for multibyte chars. if (FixItInsertionLine[i] != ' ') ++i; ++OutCol; } while (((OutCol % TabStop) != 0) && i != e); } S << '\n'; }
bool WithColor::colorsEnabled(raw_ostream &OS) { if (UseColor == cl::BOU_UNSET) return OS.has_colors(); return UseColor == cl::BOU_TRUE; }