From 4d7ad625b28befdf09255504472ff3ac78c0f536 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Thu, 25 May 2017 16:55:39 -0400
Subject: [PATCH 21/38] FIXME: read checker stdout direct from a pipe

---
 gcc/checkers.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++----------
 gcc/selftest.c | 16 ++++++++--
 gcc/selftest.h |  4 +++
 3 files changed, 99 insertions(+), 19 deletions(-)

diff --git a/gcc/checkers.c b/gcc/checkers.c
index a5bae51..38a8067 100644
--- a/gcc/checkers.c
+++ b/gcc/checkers.c
@@ -245,6 +245,9 @@ class checker
   void run ();
 
   char *m_executable;
+
+ private:
+  void make_args (auto_argvec &out) const;
 };
 
 /* FIXME.  */
@@ -292,35 +295,87 @@ checker::from_json (const json::value *jv, char *&out_err)
   return ch;
 }
 
+#if 0
+
+class pex_wrapper
+{
+ public:
+  pex_wrapper (int flags, const char *pname, const char *tempbase);
+  ~pex_wrapper ();
+
+ private:
+  pex_wrapper_obj *m_obj;
+};
+
+/* FIXME.  */
+
+pex_wrapper::pex_wrapper (int flags, const char *pname, const char *tempbase)
+{
+  m_obj = pex_init (flags, pname, tempbase);
+}
+
+/* FIXME.  */
+
+pex_wrapper::~pex_wrapper ()
+{
+  pex_free (m_obj);
+}
+
+#endif
+
 /* FIXME.  */
 
 void
 checker::run ()
 {
   auto_argvec argvec;
-#define ADD_ARG(arg) argvec.safe_push (xstrdup (arg))
 
-  ADD_ARG (m_executable);
-  ADD_ARG ("-B."); // FIXME
-  // FIXME: supply at least -I and -D args
-  ADD_ARG ("-c");
-  ADD_ARG (main_input_filename);
+  make_args (argvec);
 
   /* pex argv arrays are NULL-terminated.  */
   argvec.safe_push (NULL);
 
+  struct pex_obj *obj;
   const char *errmsg;
   int exit_status = 0;
   int err = 0;
+
+  obj = pex_init (0, progname, NULL);
+
   /* FIXME: avoid using known filename; read direct from stdout.  */
-  errmsg = pex_one (PEX_SEARCH | PEX_LAST, /* int flags, */
-		    m_executable,
-		    const_cast <char *const *> (argvec.address ()),
-		    progname, /* const char *pname */
-		    "temp.json", /* const char *outname */
+  //char *outname = ;
+
+  errmsg = pex_run (obj,
+		    PEX_SEARCH | PEX_USE_PIPES, /* int flags, */
+		    m_executable, /* const char *executable, */
+		    const_cast <char *const *> (argvec.address ()), /* argv, */
+		    NULL, /* const char *outname */
 		    NULL, /* const char *errname */
-		    &exit_status, /* int *status */
 		    &err); /* int *err*/
+  if (errmsg == NULL)
+    {
+      if (!pex_get_status (obj, 1, &exit_status))
+	{
+	  err = 0;
+	  errmsg = "pex_get_status failed";
+	}
+    }
+
+  FILE *outf = pex_read_output (obj, 0);
+  if (!outf)
+    {
+      error_at (UNKNOWN_LOCATION, "error invoking checker %qs: %qs",
+		m_executable, "unable to read stdout");
+      return;
+    }
+  /* "outf" is owned by "obj".  */
+
+  // FIXME: use something other than a selftest API for this!
+  char *utf8_buffer = selftest::read_file (SELFTEST_LOCATION, outf,
+					   "stdout from checker");
+
+  pex_free (obj);
+
   if (errmsg)
     {
       error_at (UNKNOWN_LOCATION, "error invoking checker %qs: %qs",
@@ -335,14 +390,25 @@ checker::run ()
       return;
     }
 
-  // FIXME: use something other than a selftest for this!
-  char *utf8_buffer = selftest::read_file (SELFTEST_LOCATION,
-				      "temp.json"); // FIXME: filename
   // FIXME: error-checking
   handle_json (utf8_buffer);
   free (utf8_buffer);
+}
+
+/* FIXME.  */
+
+void
+checker::make_args (auto_argvec &out) const
+{
+#define ADD_ARG(arg) out.safe_push (xstrdup (arg))
+
+  ADD_ARG (m_executable);
+  ADD_ARG ("-B."); // FIXME
+  // FIXME: supply at least -I and -D args
+  ADD_ARG ("-c");
+  ADD_ARG (main_input_filename);
 
-  // FIXME: capture clang version in metadata
+#undef ADD_ARG
 }
 
 /* FIXME.  */
diff --git a/gcc/selftest.c b/gcc/selftest.c
index b41b9f5..a6674be 100644
--- a/gcc/selftest.c
+++ b/gcc/selftest.c
@@ -162,7 +162,19 @@ read_file (const location &loc, const char *path)
   FILE *f_in = fopen (path, "r");
   if (!f_in)
     fail_formatted (loc, "unable to open file: %s", path);
+  char *result = read_file (loc, f_in, path);
+  fclose (f_in);
+  return result;
+}
+
+/* Read all of F_IN into memory, returning a 0-terminated buffer
+   that must be freed by the caller.  F_IN is *not* closed.
+   Fail (and abort) if there are any problems, with LOC as the reported
+   location of the failure, using DESC as a description of the file.  */
 
+char *
+read_file (const location &loc, FILE *f_in, const char *desc)
+{
   /* Read content, allocating FIXME.  */
   char *result = NULL;
   size_t total_sz = 0;
@@ -186,11 +198,9 @@ read_file (const location &loc, const char *path)
     }
 
   if (!feof (f_in))
-    fail_formatted (loc, "error reading from %s: %s", path,
+    fail_formatted (loc, "error reading from %s: %s", desc,
 		    xstrerror (errno));
 
-  fclose (f_in);
-
   /* 0-terminate the buffer.  */
   gcc_assert (total_sz < alloc_sz);
   result[total_sz] = '\0';
diff --git a/gcc/selftest.h b/gcc/selftest.h
index 698d361..08ed5e3 100644
--- a/gcc/selftest.h
+++ b/gcc/selftest.h
@@ -153,6 +153,10 @@ for_each_line_table_case (void (*testcase) (const line_table_case &));
 
 extern char *read_file (const location &loc, const char *path);
 
+/* FIXME.  */
+
+extern char *read_file (const location &loc, FILE *infile, const char *desc);
+
 /* A helper function for writing tests that interact with the
    garbage collector.  */
 
-- 
1.8.5.3

