aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Support/GraphWriter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Support/GraphWriter.cpp')
-rw-r--r--lib/Support/GraphWriter.cpp257
1 files changed, 137 insertions, 120 deletions
diff --git a/lib/Support/GraphWriter.cpp b/lib/Support/GraphWriter.cpp
index f5b2943..e68ee43 100644
--- a/lib/Support/GraphWriter.cpp
+++ b/lib/Support/GraphWriter.cpp
@@ -68,7 +68,7 @@ StringRef llvm::DOT::getColorString(unsigned ColorNumber) {
std::string llvm::createGraphFilename(const Twine &Name, int &FD) {
FD = -1;
SmallString<128> Filename;
- error_code EC = sys::fs::createTemporaryFile(Name, "dot", FD, Filename);
+ std::error_code EC = sys::fs::createTemporaryFile(Name, "dot", FD, Filename);
if (EC) {
errs() << "Error: " << EC.message() << "\n";
return "";
@@ -78,148 +78,165 @@ std::string llvm::createGraphFilename(const Twine &Name, int &FD) {
return Filename.str();
}
-// Execute the graph viewer. Return true if successful.
-static bool LLVM_ATTRIBUTE_UNUSED
-ExecGraphViewer(StringRef ExecPath, std::vector<const char*> &args,
- StringRef Filename, bool wait, std::string &ErrMsg) {
+// Execute the graph viewer. Return true if there were errors.
+static bool ExecGraphViewer(StringRef ExecPath, std::vector<const char *> &args,
+ StringRef Filename, bool wait,
+ std::string &ErrMsg) {
+ assert(args.back() == nullptr);
if (wait) {
- if (sys::ExecuteAndWait(ExecPath, &args[0],nullptr,nullptr,0,0,&ErrMsg)) {
+ if (sys::ExecuteAndWait(ExecPath, args.data(), nullptr, nullptr, 0, 0,
+ &ErrMsg)) {
errs() << "Error: " << ErrMsg << "\n";
- return false;
+ return true;
}
sys::fs::remove(Filename);
errs() << " done. \n";
- }
- else {
- sys::ExecuteNoWait(ExecPath, &args[0],nullptr,nullptr,0,&ErrMsg);
+ } else {
+ sys::ExecuteNoWait(ExecPath, args.data(), nullptr, nullptr, 0, &ErrMsg);
errs() << "Remember to erase graph file: " << Filename.str() << "\n";
}
- return true;
+ return false;
+}
+
+struct GraphSession {
+ std::string LogBuffer;
+ bool TryFindProgram(StringRef Names, std::string &ProgramPath) {
+ raw_string_ostream Log(LogBuffer);
+ SmallVector<StringRef, 8> parts;
+ Names.split(parts, "|");
+ for (auto Name : parts) {
+ ProgramPath = sys::FindProgramByName(Name);
+ if (!ProgramPath.empty())
+ return true;
+ Log << " Tried '" << Name << "'\n";
+ }
+ return false;
+ }
+};
+
+static const char *getProgramName(GraphProgram::Name program) {
+ switch (program) {
+ case GraphProgram::DOT:
+ return "dot";
+ case GraphProgram::FDP:
+ return "fdp";
+ case GraphProgram::NEATO:
+ return "neato";
+ case GraphProgram::TWOPI:
+ return "twopi";
+ case GraphProgram::CIRCO:
+ return "circo";
+ }
+ llvm_unreachable("bad kind");
}
-void llvm::DisplayGraph(StringRef FilenameRef, bool wait,
+bool llvm::DisplayGraph(StringRef FilenameRef, bool wait,
GraphProgram::Name program) {
std::string Filename = FilenameRef;
wait &= !ViewBackground;
std::string ErrMsg;
-#if HAVE_GRAPHVIZ
- std::string Graphviz(LLVM_PATH_GRAPHVIZ);
-
- std::vector<const char*> args;
- args.push_back(Graphviz.c_str());
- args.push_back(Filename.c_str());
- args.push_back(nullptr);
-
- errs() << "Running 'Graphviz' program... ";
- if (!ExecGraphViewer(Graphviz, args, Filename, wait, ErrMsg))
- return;
-
-#elif HAVE_XDOT
- std::vector<const char*> args;
- args.push_back(LLVM_PATH_XDOT);
- args.push_back(Filename.c_str());
-
- switch (program) {
- case GraphProgram::DOT: args.push_back("-f"); args.push_back("dot"); break;
- case GraphProgram::FDP: args.push_back("-f"); args.push_back("fdp"); break;
- case GraphProgram::NEATO: args.push_back("-f"); args.push_back("neato");break;
- case GraphProgram::TWOPI: args.push_back("-f"); args.push_back("twopi");break;
- case GraphProgram::CIRCO: args.push_back("-f"); args.push_back("circo");break;
+ std::string ViewerPath;
+ GraphSession S;
+
+ // Graphviz
+ if (S.TryFindProgram("Graphviz", ViewerPath)) {
+ std::vector<const char *> args;
+ args.push_back(ViewerPath.c_str());
+ args.push_back(Filename.c_str());
+ args.push_back(nullptr);
+
+ errs() << "Running 'Graphviz' program... ";
+ return ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg);
}
- args.push_back(0);
+ // xdot
+ if (S.TryFindProgram("xdot|xdot.py", ViewerPath)) {
+ std::vector<const char *> args;
+ args.push_back(ViewerPath.c_str());
+ args.push_back(Filename.c_str());
- errs() << "Running 'xdot.py' program... ";
- if (!ExecGraphViewer(LLVM_PATH_XDOT, args, Filename, wait, ErrMsg))
- return;
+ args.push_back("-f");
+ args.push_back(getProgramName(program));
-#elif (HAVE_GV && (HAVE_DOT || HAVE_FDP || HAVE_NEATO || \
- HAVE_TWOPI || HAVE_CIRCO))
- std::string PSFilename = Filename + ".ps";
- std::string prog;
+ args.push_back(nullptr);
- // Set default grapher
-#if HAVE_CIRCO
- prog = LLVM_PATH_CIRCO;
-#endif
-#if HAVE_TWOPI
- prog = LLVM_PATH_TWOPI;
-#endif
-#if HAVE_NEATO
- prog = LLVM_PATH_NEATO;
-#endif
-#if HAVE_FDP
- prog = LLVM_PATH_FDP;
-#endif
-#if HAVE_DOT
- prog = LLVM_PATH_DOT;
-#endif
+ errs() << "Running 'xdot.py' program... ";
+ return ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg);
+ }
- // Find which program the user wants
-#if HAVE_DOT
- if (program == GraphProgram::DOT)
- prog = LLVM_PATH_DOT;
-#endif
-#if (HAVE_FDP)
- if (program == GraphProgram::FDP)
- prog = LLVM_PATH_FDP;
-#endif
-#if (HAVE_NEATO)
- if (program == GraphProgram::NEATO)
- prog = LLVM_PATH_NEATO;
-#endif
-#if (HAVE_TWOPI)
- if (program == GraphProgram::TWOPI)
- prog = LLVM_PATH_TWOPI;
-#endif
-#if (HAVE_CIRCO)
- if (program == GraphProgram::CIRCO)
- prog = LLVM_PATH_CIRCO;
+ enum PSViewerKind { PSV_None, PSV_OSXOpen, PSV_XDGOpen, PSV_Ghostview };
+ PSViewerKind PSViewer = PSV_None;
+#ifdef __APPLE__
+ if (!PSViewer && S.TryFindProgram("open", ViewerPath))
+ PSViewer = PSV_OSXOpen;
#endif
+ if (!PSViewer && S.TryFindProgram("gv", ViewerPath))
+ PSViewer = PSV_Ghostview;
+ if (!PSViewer && S.TryFindProgram("xdg-open", ViewerPath))
+ PSViewer = PSV_XDGOpen;
+
+ // PostScript graph generator + PostScript viewer
+ std::string GeneratorPath;
+ if (PSViewer &&
+ (S.TryFindProgram(getProgramName(program), GeneratorPath) ||
+ S.TryFindProgram("dot|fdp|neato|twopi|circo", GeneratorPath))) {
+ std::string PSFilename = Filename + ".ps";
+
+ std::vector<const char *> args;
+ args.push_back(GeneratorPath.c_str());
+ args.push_back("-Tps");
+ args.push_back("-Nfontname=Courier");
+ args.push_back("-Gsize=7.5,10");
+ args.push_back(Filename.c_str());
+ args.push_back("-o");
+ args.push_back(PSFilename.c_str());
+ args.push_back(nullptr);
+
+ errs() << "Running '" << GeneratorPath << "' program... ";
+
+ if (ExecGraphViewer(GeneratorPath, args, Filename, wait, ErrMsg))
+ return true;
+
+ args.clear();
+ args.push_back(ViewerPath.c_str());
+ switch (PSViewer) {
+ case PSV_OSXOpen:
+ args.push_back("-W");
+ args.push_back(PSFilename.c_str());
+ break;
+ case PSV_XDGOpen:
+ wait = false;
+ args.push_back(PSFilename.c_str());
+ break;
+ case PSV_Ghostview:
+ args.push_back("--spartan");
+ args.push_back(PSFilename.c_str());
+ break;
+ case PSV_None:
+ llvm_unreachable("Invalid viewer");
+ }
+ args.push_back(nullptr);
- std::vector<const char*> args;
- args.push_back(prog.c_str());
- args.push_back("-Tps");
- args.push_back("-Nfontname=Courier");
- args.push_back("-Gsize=7.5,10");
- args.push_back(Filename.c_str());
- args.push_back("-o");
- args.push_back(PSFilename.c_str());
- args.push_back(0);
-
- errs() << "Running '" << prog << "' program... ";
-
- if (!ExecGraphViewer(prog, args, Filename, wait, ErrMsg))
- return;
-
- std::string gv(LLVM_PATH_GV);
- args.clear();
- args.push_back(gv.c_str());
- args.push_back(PSFilename.c_str());
- args.push_back("--spartan");
- args.push_back(0);
-
- ErrMsg.clear();
- if (!ExecGraphViewer(gv, args, PSFilename, wait, ErrMsg))
- return;
-
-#elif HAVE_DOTTY
- std::string dotty(LLVM_PATH_DOTTY);
+ ErrMsg.clear();
+ return ExecGraphViewer(ViewerPath, args, PSFilename, wait, ErrMsg);
+ }
- std::vector<const char*> args;
- args.push_back(dotty.c_str());
- args.push_back(Filename.c_str());
- args.push_back(0);
+ // dotty
+ if (S.TryFindProgram("dotty", ViewerPath)) {
+ std::vector<const char *> args;
+ args.push_back(ViewerPath.c_str());
+ args.push_back(Filename.c_str());
+ args.push_back(nullptr);
// Dotty spawns another app and doesn't wait until it returns
-#if defined (__MINGW32__) || defined (_WINDOWS)
- wait = false;
-#endif
- errs() << "Running 'dotty' program... ";
- if (!ExecGraphViewer(dotty, args, Filename, wait, ErrMsg))
- return;
-#else
- (void)Filename;
- (void)ErrMsg;
+#ifdef LLVM_ON_WIN32
+ wait = false;
#endif
+ errs() << "Running 'dotty' program... ";
+ return ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg);
+ }
+
+ errs() << "Error: Couldn't find a usable graph viewer program:\n";
+ errs() << S.LogBuffer << "\n";
+ return true;
}