From d0d3619698cf2180812782ed6de189b1b724944f Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Thu, 28 Feb 2019 14:07:05 -0500
Subject: [PATCH 012/138] FIXME: add make-html.sh and various demo files (and
 mockup HTML)

---
 demo-2.html             | 216 +++++++++++++++++++++++++++++++++++++
 demo-control.c          |  44 ++++++++
 demo-direct-with-loop.c |  22 ++++
 demo-direct.c           |  31 ++++++
 demo-indirect.c         |  21 ++++
 demo.html               | 277 ++++++++++++++++++++++++++++++++++++++++++++++++
 make-html.sh            |  26 +++++
 7 files changed, 637 insertions(+)
 create mode 100644 demo-2.html
 create mode 100644 demo-control.c
 create mode 100644 demo-direct-with-loop.c
 create mode 100644 demo-direct.c
 create mode 100644 demo-indirect.c
 create mode 100644 demo.html
 create mode 100755 make-html.sh

diff --git a/demo-2.html b/demo-2.html
new file mode 100644
index 0000000..1afa046
--- /dev/null
+++ b/demo-2.html
@@ -0,0 +1,216 @@
+<!DOCTYPE html>
+<!-- see notebook p123 -->
+<html lang="en">
+<head>
+  <meta charset="UTF-8">
+
+  <!-- Bootstrap CSS -->
+  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB" crossorigin="anonymous">
+
+    <style>
+    </style>
+
+    <title>Analyzer report</title>
+</head>
+<body>
+    <div id="content">
+    <ul class="list-group">
+
+    <li class="list-group-item">
+      <div>
+	<div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c:30:1: warning: double-free</div>
+	  <pre>
+   30 | }
+      | ^
+	  </pre>
+	<ul class="list-group">
+	  <li class="list-group-item">
+	    <div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c: In function ‘test’:</div>
+	  </li>
+	</ul>
+	<ul class="list-group">
+	  <div class="stack">stack: <code>test</code></div>
+
+	  <li class="list-group-item">
+	    <pre>
+   26 | {
+   27 |   boxed_int *bi = make_boxed_int (x);
+      |                   ~~~~~~~~~~~~~~~~~~
+      |                   |
+      |                   <span class="badge badge-pill badge-info">①: calling from ‘test’ to ‘make_boxed_int’</span>
+	    </pre>
+
+	    <ul class="list-group">
+	      <li class="list-group-item">
+		<div class="stack">stack: <code>test</code> / <code>make_boxed_int</code></div>
+		<div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c: In function ‘make_boxed_int’:</div>
+		<pre>
+   13 | {
+   14 |   boxed_int *new_ptr = (boxed_int *)malloc (sizeof (boxed_int));
+      |                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+      |                                     |
+      |                                     <span class="badge badge-pill badge-info">②: ‘new_ptr’: ‘unchecked’</span>
+   15 |   new_ptr->val = val;
+   16 |   return new_ptr;
+      |          ~~~~~~~
+      |          |
+      |          <span class="badge badge-pill badge-info">③: returning ‘unchecked’</span>
+   17 | }
+		</pre>
+	      </li>
+	    </ul>
+
+	    <!-- returning to "test/" -->
+	    <div class="stack">stack: <code>test</code></div>
+
+      <div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c: In function ‘test’:</div>
+      <div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c:27:19: note: (19) returning from ‘make_boxed_int’ to ‘test’</div>
+      <pre>
+   27 |   boxed_int *bi = make_boxed_int (x);
+      |                   ^~~~~~~~~~~~~~~~~~
+      |                   |
+      |                   <span class="badge badge-pill badge-info">④: ‘bi’: ‘unchecked’</span>
+   28 |   free_boxed_int (bi);
+      |   ~~~~~~~~~~~~~~~~~~~
+      |   |
+      |   <span class="badge badge-pill badge-info">⑤: calling from ‘test’ to ‘free_boxed_int’ (‘bi’: ‘unchecked’)</span>
+      </pre>
+
+	    <ul class="list-group"> <!-- stack: "test/free_boxed_int/" -->
+	      <li class="list-group-item">
+		<div class="stack">stack: <code>test</code> / <code>free_boxed_int</code></div>
+      <div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c: In function ‘free_boxed_int’:</div>
+      <div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c:21:1: note: (NN) ‘bi’: ‘unchecked’</div>
+      <pre>
+   21 | {
+   22 |   free (victim);
+      |   ~~~~~~~~~~~~~
+      |   |
+      |   <span class="badge badge-pill badge-info">(NN): ‘unchecked’ -> ‘free’</span>
+   23 | }
+      |
+      </pre>
+	      </li>
+	    </ul>
+
+	    <!-- returning to "test/" -->
+	  </li>
+	</ul>
+
+	<div class="stack">stack: <code>test</code></div>
+      <div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c: In function ‘test’:</div>
+      <pre>
+   28 |   free_boxed_int (bi);
+      |   ^~~~~~~~~~~~~~~~~~~
+      |   |
+      |   <span class="badge badge-pill badge-info">(NN): returning from ‘free_boxed_int’ to ‘test’ (‘bi’: ‘freed’)</span>
+   29 |   free_boxed_int (bi); /* BUG: double-free.  */
+      |   ~~~~~~~~~~~~~~~~~~~
+      |   |
+      |   <span class="badge badge-pill badge-info">(NN) calling from ‘test’ to ‘free_boxed_int’ (‘bi’: ‘freed’)</span>
+      </pre>
+
+	    <ul class="list-group"> <!-- stack: "test/free_boxed_int/" -->
+	      <li class="list-group-item">
+		<div class="stack">stack: <code>test</code> / <code>free_boxed_int</code></div>
+		<div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c: In function ‘free_boxed_int’:</div>
+		<div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c:21:1: note: (35) ‘free_boxed_int’ supernode:6 sm_inst: <start, {}></div>
+		<pre>
+   21 | {
+   22 |   free (victim);
+      |   ~~~~~~~~~~~~~
+      |   |
+      |   <span class="badge badge-pill badge-danger">(N) double-free of ‘victim’</span>
+		</pre>
+	      </li>
+	    </ul>
+    </li>
+    </ul>
+
+    <li class="list-group-item">
+      <div>
+	<div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c: At top level:</div>
+	<div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c:23:1: note: END OF PATH (presumably started within ‘free_boxed_int’)</div>
+      <pre>
+   23 | }
+      | ^
+      </pre>
+      <pre>
+	<div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c: In function ‘free_boxed_int’:</div>
+	<div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c:21:1: note: (1) ‘free_boxed_int’ supernode:6 sm_inst: <start, {}></div>
+   21 | {
+      | ^
+      | |
+      | (2) taking CFG edge 0->2 within ‘free_boxed_int’ (supernode 6 -> 7)
+   22 |   free (victim);
+      |   ~~~~~~~~~~~~~
+      |   |
+      |   (5) <start, {}>; transition: ‘victim’: ‘start’ -> ‘free’
+      |   (4) on_stmt: ‘free (victim_2(D));’ <start, {}>
+      |   (3) ‘free_boxed_int’ supernode:7 sm_inst: <start, {}>
+   23 | }
+      | ~
+      | |
+      | (8) ‘free_boxed_int’ supernode:8 sm_inst: <start, {‘victim’: ‘free’}>
+      | (7) taking CFG edge 2->1 within ‘free_boxed_int’ (supernode 7 -> 8)
+      | (6) on_stmt: ‘return;’ <start, {‘victim’: ‘free’}>
+      </pre>
+    </li>
+
+
+    <li class="list-group-item">
+      <div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c: At top level:</div>
+      <div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c:17:1: note: END OF PATH (presumably started within ‘make_boxed_int’)</div>
+      <pre>
+   17 | }
+      | ^
+      </pre>
+      <div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c: In function ‘make_boxed_int’:</div>
+      <div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c:13:1: note: (1) ‘make_boxed_int’ supernode:9 sm_inst: <start, {}></div>
+      <pre>
+   13 | {
+      | ^
+      | |
+      | (2) taking CFG edge 0->2 within ‘make_boxed_int’ (supernode 9 -> 10)
+   14 |   boxed_int *new_ptr = (boxed_int *)malloc (sizeof (boxed_int));
+      |                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+      |                                     |
+      |                                     (5) <start, {}>; transition: ‘new_ptr’: ‘start’ -> ‘unchecked’
+      |                                     (4) on_stmt: ‘new_ptr_3 = malloc (4);’ <start, {}>
+      |                                     (3) ‘make_boxed_int’ supernode:10 sm_inst: <start, {}>
+   15 |   new_ptr->val = val;
+      |   ~~~~~~~~~~~~~~~~~~
+      |                |
+      |                (6) on_stmt: ‘new_ptr_3->val = val_4(D);’ <start, {‘new_ptr’: ‘unchecked’}>
+   16 |   return new_ptr;
+      |          ~~~~~~~
+      |          |
+      |          (9) ‘make_boxed_int’ supernode:11 sm_inst: <start, {‘new_ptr’: ‘unchecked’, ‘<unknown>’: ‘unchecked’}>
+      |          (8) taking CFG edge 2->3 within ‘make_boxed_int’ (supernode 10 -> 11)
+      |          (7) on_stmt: ‘_6 = new_ptr_3;’ <start, {‘new_ptr’: ‘unchecked’}>
+      </pre>
+      <div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c:16:10: note: (11) on_stmt: ‘return _6;’ <start, {‘new_ptr’: ‘unchecked’, ‘<unknown>’: ‘unchecked’}></div>
+      <pre>
+   16 |   return new_ptr;
+      |          ^~~~~~~
+      |          |
+      |          (12) taking CFG edge 3->1 within ‘make_boxed_int’ (supernode 11 -> 12)
+   17 | }
+      | ~         
+      | |
+      | (13) ‘make_boxed_int’ supernode:12 sm_inst: <start, {‘new_ptr’: ‘unchecked’, ‘<unknown>’: ‘unchecked’, ‘<return-value>’: ‘unchecked’}>
+      </pre>
+      </div>
+    </ul>
+    </div>
+
+    <div id="footer">
+    </div>
+
+    <!-- Bootstrap JS -->
+    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
+    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js" integrity="sha384-smHYKdLADwkXOn1EmN1qk/HfnUcbVRZyYmZ4qpPea6sjB/pTJ0euyQp0Mk8ck+5T" crossorigin="anonymous"></script>
+
+</body>
+</html>
diff --git a/demo-control.c b/demo-control.c
new file mode 100644
index 0000000..68b8609
--- /dev/null
+++ b/demo-control.c
@@ -0,0 +1,44 @@
+extern void __dump_constraints (void);
+
+void test_cond (int flag)
+{
+  if (flag)
+    __dump_constraints ();
+  else
+    __dump_constraints ();
+}
+
+void test_switch (int x)
+{
+  switch (x)
+    {
+    case 5 ... 10:
+      __dump_constraints ();
+      break;
+
+    case 17:
+      __dump_constraints ();
+      break;
+
+    default:
+      __dump_constraints ();
+      break;
+    }
+}
+
+extern void do_something (int i);
+
+void test_double_diamond (int flag)
+{
+  if (flag)
+    do_something (0);
+  else
+    do_something (1);
+
+  do_something (2);
+
+  if (flag)
+    __dump_constraints ();
+  else
+    __dump_constraints ();
+}
diff --git a/demo-direct-with-loop.c b/demo-direct-with-loop.c
new file mode 100644
index 0000000..446cd7e
--- /dev/null
+++ b/demo-direct-with-loop.c
@@ -0,0 +1,22 @@
+#include <stdlib.h>
+
+void test (void)
+{
+  void *ptr = malloc (1024);
+
+  int i;
+  for (i = 0; i < 1024; i++)
+    free (ptr); /* BUG: double-free, 2nd time in loop.  */
+}
+
+void test_2 (void)
+{
+  void *ptr = malloc (1024);
+
+  int i;
+  for (i = 0; i < 1024; i++)
+    foo ();
+
+  free (ptr);
+  free (ptr);
+}
diff --git a/demo-direct.c b/demo-direct.c
new file mode 100644
index 0000000..f43de69
--- /dev/null
+++ b/demo-direct.c
@@ -0,0 +1,31 @@
+#include <stdlib.h>
+
+void test (void)
+{
+  void *ptr = malloc (1024);
+  free (ptr);
+  free (ptr); /* BUG: double-free.  */
+}
+
+void test_2 (int x, int y)
+{
+  void *ptr = malloc (1024);
+  if (x)
+    free (ptr);
+  if (y)
+    free (ptr); /* BUG: double-free.  */
+  /* BUG: leak.  */
+}
+
+int test_3 (int x, int y)
+{
+  int *ptr = (int *)malloc (sizeof (int));
+  *ptr = 42;
+  if (x)
+    free (ptr);
+  *ptr = 19;
+  if (y)
+    free (ptr); /* BUG: double-free.  */
+  return *ptr;
+  /* BUG: leak.  */
+}
diff --git a/demo-indirect.c b/demo-indirect.c
new file mode 100644
index 0000000..cf4dd50
--- /dev/null
+++ b/demo-indirect.c
@@ -0,0 +1,21 @@
+#include <stdlib.h>
+
+void *
+calls_malloc (void)
+{
+  void *result = malloc (1024);
+  return result;
+}
+
+void
+calls_free (void *victim)
+{
+  free (victim);
+}
+
+void test (void)
+{
+  void *ptr = calls_malloc ();
+  calls_free (ptr);
+  calls_free (ptr); /* BUG: double-free.  */
+}
diff --git a/demo.html b/demo.html
new file mode 100644
index 0000000..981f9a0
--- /dev/null
+++ b/demo.html
@@ -0,0 +1,277 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8">
+
+  <!-- Bootstrap CSS -->
+  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB" crossorigin="anonymous">
+
+    <style>
+    </style>
+
+    <title>Analyzer report</title>
+</head>
+<body>
+    <div id="content">
+    <ul class="list-group">
+
+    <li class="list-group-item">
+      <div>
+	<div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c:30:1: warning: double-free</div>
+	  <pre>
+   30 | }
+      | ^
+	  </pre>
+	<ul class="list-group">
+	  <li class="list-group-item">
+	    <div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c: In function ‘test’:</div>
+	  </li>
+	</ul>
+	<ul class="list-group">
+	  <div class="stack">stack: <code>test</code></div>
+
+	  <li class="list-group-item">
+	    <div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c: In function ‘test’:</div>
+	    <div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c:26:1: note: (1) ‘test’ supernode:0 sm_inst: <start, {}></div>
+	    <pre>
+   26 | {
+      | ^
+      | |
+      | (2) taking CFG edge 0->2 within ‘test’ (supernode 0 -> 1)
+   27 |   boxed_int *bi = make_boxed_int (x);
+      |                   ~~~~~~~~~~~~~~~~~~
+      |                   |
+      |                   <span class="badge badge-pill badge-info">(5) calling from ‘test’ to ‘make_boxed_int’ (supernode 1 -> 9)</span>
+      |                   <span class="badge badge-pill badge-info">(4) on_stmt: ‘bi_4 = make_boxed_int (x_2(D));’ <start, {}></span>
+      |                   <span class="badge badge-pill badge-info">(3) ‘test’ supernode:1 sm_inst: <start, {}></span>
+	    </pre>
+
+	    <ul class="list-group">
+	      <li class="list-group-item">
+		<div class="stack">stack: <code>test</code> / <code>make_boxed_int</code></div>
+		<div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c: In function ‘make_boxed_int’:</div>
+		<div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c:13:1: note: (6) ‘make_boxed_int’ supernode:9 sm_inst: <start, {}></div>
+		<pre>
+   13 | {
+      | ^
+      | |
+      | (7) taking CFG edge 0->2 within ‘make_boxed_int’ (supernode 9 -> 10)
+   14 |   boxed_int *new_ptr = (boxed_int *)malloc (sizeof (boxed_int));
+      |                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+      |                                     |
+      |                                     <span class="badge badge-pill badge-info">(10) <start, {}>; transition: ‘new_ptr’: ‘start’ -> ‘unchecked’</span>
+      |                                     <span class="badge badge-pill badge-info">(9) on_stmt: ‘new_ptr_3 = malloc (4);’ <start, {}></span>
+      |                                     <span class="badge badge-pill badge-info">(8) ‘make_boxed_int’ supernode:10 sm_inst: <start, {}></span>
+   15 |   new_ptr->val = val;
+      |   ~~~~~~~~~~~~~~~~~~
+      |                |
+      |                <span class="badge badge-pill badge-info">(11) on_stmt: ‘new_ptr_3->val = val_4(D);’ <start, {‘new_ptr’: ‘unchecked’}></span>
+   16 |   return new_ptr;
+      |          ~~~~~~~
+      |          |
+      |          <span class="badge badge-pill badge-info">(14) ‘make_boxed_int’ supernode:11 sm_inst: <start, {‘new_ptr’: ‘unchecked’, ‘<unknown>’: ‘unchecked’}></span>
+      |          <span class="badge badge-pill badge-info">(13) taking CFG edge 2->3 within ‘make_boxed_int’ (supernode 10 -> 11)</span>
+      |          <span class="badge badge-pill badge-info">(12) on_stmt: ‘_6 = new_ptr_3;’ <start, {‘new_ptr’: ‘unchecked’}></span>
+      |          <span class="badge badge-pill badge-info">(16) on_stmt: ‘return _6;’ <start, {‘new_ptr’: ‘unchecked’, ‘<unknown>’: ‘unchecked’}></span>
+      |          <span class="badge badge-pill badge-info">(17) taking CFG edge 3->1 within ‘make_boxed_int’ (supernode 11 -> 12)</span>
+   17 | }
+      | ~         
+      | |
+      | (18) ‘make_boxed_int’ supernode:12 sm_inst: <start, {‘new_ptr’: ‘unchecked’, ‘<unknown>’: ‘unchecked’, ‘<return-value>’: ‘unchecked’}>
+		</pre>
+	      </li>
+	    </ul>
+
+	    <!-- returning to "test/" -->
+	    <div class="stack">stack: <code>test</code></div>
+
+      <div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c: In function ‘test’:</div>
+      <div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c:27:19: note: (19) returning from ‘make_boxed_int’ to ‘test’ (supernode 12 -> 2)</div>
+      <pre>
+   27 |   boxed_int *bi = make_boxed_int (x);
+      |                   ^~~~~~~~~~~~~~~~~~
+      |                   |
+      |                   <span class="badge badge-pill badge-info">(20) ‘test’ supernode:2 sm_inst: <start, {‘bi’: ‘unchecked’}></span>
+   28 |   free_boxed_int (bi);
+      |   ~~~~~~~~~~~~~~~~~~~
+      |   |
+      |   <span class="badge badge-pill badge-info">(22) calling from ‘test’ to ‘free_boxed_int’ (supernode 2 -> 6)</span>
+      |   <span class="badge badge-pill badge-info">(21) on_stmt: ‘free_boxed_int (bi_4);’ <start, {‘bi’: ‘unchecked’}></span>
+      </pre>
+
+	    <ul class="list-group"> <!-- stack: "test/free_boxed_int/" -->
+	      <li class="list-group-item">
+		<div class="stack">stack: <code>test</code> / <code>free_boxed_int</code></div>
+      <div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c: In function ‘free_boxed_int’:</div>
+      <div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c:21:1: note: (23) ‘free_boxed_int’ supernode:6 sm_inst: <start, {‘bi’: ‘unchecked’}></div>
+      <pre>
+   21 | {
+      | ^
+      | |
+      | <span class="badge badge-pill badge-info">(24) taking CFG edge 0->2 within ‘free_boxed_int’ (supernode 6 -> 7)</span>
+   22 |   free (victim);
+      |   ~~~~~~~~~~~~~
+      |   |
+      |   <span class="badge badge-pill badge-info">(27) <start, {‘bi’: ‘unchecked’}>; transition: ‘victim’: ‘start’ -> ‘free’</span>
+      |   <div class="badge badge-pill badge-info">(26) on_stmt: ‘free (victim_2(D));’ <start, {‘bi’: ‘unchecked’}></div>
+      |   <span class="badge badge-pill badge-info">(25) ‘free_boxed_int’ supernode:7 sm_inst: <start, {‘bi’: ‘unchecked’}></span>
+   23 | }
+      | ~
+      | |
+      | <span class="badge badge-pill badge-info">(30) ‘free_boxed_int’ supernode:8 sm_inst: <start, {‘bi’: ‘unchecked’, ‘victim’: ‘free’}></span>
+      | <span class="badge badge-pill badge-info">(29) taking CFG edge 2->1 within ‘free_boxed_int’ (supernode 7 -> 8)</span>
+      | <span class="badge badge-pill badge-info">(28) on_stmt: ‘return;’ <start, {‘bi’: ‘unchecked’, ‘victim’: ‘free’}></span>
+      </pre>
+	      </li>
+	    </ul>
+
+	    <!-- returning to "test/" -->
+	  </li>
+	</ul>
+
+	<div class="stack">stack: <code>test</code></div>
+      <div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c: In function ‘test’:</div>
+      <div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c:28:3: note: (31) returning from ‘free_boxed_int’ to ‘test’ (supernode 8 -> 3)</div>
+      <pre>
+   28 |   free_boxed_int (bi);
+      |   ^~~~~~~~~~~~~~~~~~~
+      |   |
+      |   <span class="badge badge-pill badge-info">(32) ‘test’ supernode:3 sm_inst: <start, {}></span>
+   29 |   free_boxed_int (bi); /* BUG: double-free.  */
+      |   ~~~~~~~~~~~~~~~~~~~
+      |   |
+      |   <span class="badge badge-pill badge-info">(34) calling from ‘test’ to ‘free_boxed_int’ (supernode 3 -> 6)</span>
+      |   <span class="badge badge-pill badge-info">(33) on_stmt: ‘free_boxed_int (bi_4);’ <start, {}></span>
+      </pre>
+
+	    <ul class="list-group"> <!-- stack: "test/free_boxed_int/" -->
+	      <li class="list-group-item">
+		<div class="stack">stack: <code>test</code> / <code>free_boxed_int</code></div>
+		<div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c: In function ‘free_boxed_int’:</div>
+		<div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c:21:1: note: (35) ‘free_boxed_int’ supernode:6 sm_inst: <start, {}></div>
+		<pre>
+   21 | {
+      | ^
+      | |
+      | <span class="badge badge-pill badge-info">(36) taking CFG edge 0->2 within ‘free_boxed_int’ (supernode 6 -> 7)</span>
+   22 |   free (victim);
+      |   ~~~~~~~~~~~~~
+      |   |
+      |   <span class="badge badge-pill badge-info">(39) <start, {}>; transition: ‘victim’: ‘start’ -> ‘free’</span>
+      |   <span class="badge badge-pill badge-info">(38) on_stmt: ‘free (victim_2(D));’ <start, {}></span>
+      |   <span class="badge badge-pill badge-info">(37) ‘free_boxed_int’ supernode:7 sm_inst: <start, {}></span>
+   23 | }
+      | ~
+      | |
+      | <span class="badge badge-pill badge-info">(42) ‘free_boxed_int’ supernode:8 sm_inst: <start, {‘victim’: ‘free’}></span>
+      | <span class="badge badge-pill badge-info">(41) taking CFG edge 2->1 within ‘free_boxed_int’ (supernode 7 -> 8)</span>
+      | <span class="badge badge-pill badge-info">(40) on_stmt: ‘return;’ <start, {‘victim’: ‘free’}></span>
+		</pre>
+	      </li>
+	    </ul>
+
+	    <div class="stack">stack: <code>test</code></div>
+	    <div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c: In function ‘test’:</div>
+	    <div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c:29:3: note: (43) returning from ‘free_boxed_int’ to ‘test’ (supernode 8 -> 4)</div>
+	    <pre>
+   29 |   free_boxed_int (bi); /* BUG: double-free.  */
+      |   ^~~~~~~~~~~~~~~~~~~
+      |   |
+      |   <span class="badge badge-pill badge-info">(44) ‘test’ supernode:4 sm_inst: <start, {}></span>
+   30 | }
+      | ~  
+      | |
+      | <span class="badge badge-pill badge-info">(47) ‘test’ supernode:5 sm_inst: <start, {}></span>
+      | <span class="badge badge-pill badge-info">(46) taking CFG edge 2->1 within ‘test’ (supernode 4 -> 5)</span>
+      | <span class="badge badge-pill badge-info">(45) on_stmt: ‘return;’ <start, {}></span>
+	    </pre>
+    </li>
+    </ul>
+
+    <li class="list-group-item">
+      <div>
+	<div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c: At top level:</div>
+	<div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c:23:1: note: END OF PATH (presumably started within ‘free_boxed_int’)</div>
+      <pre>
+   23 | }
+      | ^
+      </pre>
+      <pre>
+	<div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c: In function ‘free_boxed_int’:</div>
+	<div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c:21:1: note: (1) ‘free_boxed_int’ supernode:6 sm_inst: <start, {}></div>
+   21 | {
+      | ^
+      | |
+      | (2) taking CFG edge 0->2 within ‘free_boxed_int’ (supernode 6 -> 7)
+   22 |   free (victim);
+      |   ~~~~~~~~~~~~~
+      |   |
+      |   (5) <start, {}>; transition: ‘victim’: ‘start’ -> ‘free’
+      |   (4) on_stmt: ‘free (victim_2(D));’ <start, {}>
+      |   (3) ‘free_boxed_int’ supernode:7 sm_inst: <start, {}>
+   23 | }
+      | ~
+      | |
+      | (8) ‘free_boxed_int’ supernode:8 sm_inst: <start, {‘victim’: ‘free’}>
+      | (7) taking CFG edge 2->1 within ‘free_boxed_int’ (supernode 7 -> 8)
+      | (6) on_stmt: ‘return;’ <start, {‘victim’: ‘free’}>
+      </pre>
+    </li>
+
+
+    <li class="list-group-item">
+      <div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c: At top level:</div>
+      <div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c:17:1: note: END OF PATH (presumably started within ‘make_boxed_int’)</div>
+      <pre>
+   17 | }
+      | ^
+      </pre>
+      <div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c: In function ‘make_boxed_int’:</div>
+      <div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c:13:1: note: (1) ‘make_boxed_int’ supernode:9 sm_inst: <start, {}></div>
+      <pre>
+   13 | {
+      | ^
+      | |
+      | (2) taking CFG edge 0->2 within ‘make_boxed_int’ (supernode 9 -> 10)
+   14 |   boxed_int *new_ptr = (boxed_int *)malloc (sizeof (boxed_int));
+      |                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+      |                                     |
+      |                                     (5) <start, {}>; transition: ‘new_ptr’: ‘start’ -> ‘unchecked’
+      |                                     (4) on_stmt: ‘new_ptr_3 = malloc (4);’ <start, {}>
+      |                                     (3) ‘make_boxed_int’ supernode:10 sm_inst: <start, {}>
+   15 |   new_ptr->val = val;
+      |   ~~~~~~~~~~~~~~~~~~
+      |                |
+      |                (6) on_stmt: ‘new_ptr_3->val = val_4(D);’ <start, {‘new_ptr’: ‘unchecked’}>
+   16 |   return new_ptr;
+      |          ~~~~~~~
+      |          |
+      |          (9) ‘make_boxed_int’ supernode:11 sm_inst: <start, {‘new_ptr’: ‘unchecked’, ‘<unknown>’: ‘unchecked’}>
+      |          (8) taking CFG edge 2->3 within ‘make_boxed_int’ (supernode 10 -> 11)
+      |          (7) on_stmt: ‘_6 = new_ptr_3;’ <start, {‘new_ptr’: ‘unchecked’}>
+      </pre>
+      <div class="diagnostic>">../../src/gcc/testsuite/analyzer.dg/demo.c:16:10: note: (11) on_stmt: ‘return _6;’ <start, {‘new_ptr’: ‘unchecked’, ‘<unknown>’: ‘unchecked’}></div>
+      <pre>
+   16 |   return new_ptr;
+      |          ^~~~~~~
+      |          |
+      |          (12) taking CFG edge 3->1 within ‘make_boxed_int’ (supernode 11 -> 12)
+   17 | }
+      | ~         
+      | |
+      | (13) ‘make_boxed_int’ supernode:12 sm_inst: <start, {‘new_ptr’: ‘unchecked’, ‘<unknown>’: ‘unchecked’, ‘<return-value>’: ‘unchecked’}>
+      </pre>
+      </div>
+    </ul>
+    </div>
+
+    <div id="footer">
+    </div>
+
+    <!-- Bootstrap JS -->
+    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
+    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js" integrity="sha384-smHYKdLADwkXOn1EmN1qk/HfnUcbVRZyYmZ4qpPea6sjB/pTJ0euyQp0Mk8ck+5T" crossorigin="anonymous"></script>
+
+</body>
+</html>
diff --git a/make-html.sh b/make-html.sh
new file mode 100755
index 0000000..a8a331c
--- /dev/null
+++ b/make-html.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+# Run this from BUILDDIR/gcc, e.g. via:
+#   make -j64 && make check-gcc RUNTESTFLAGS="-v -v plugin.exp=*" && ../../src/make-html.sh
+
+SRCDIR=../../src
+
+for f in $SRCDIR/gcc/testsuite/analyzer.dg/demo.c $SRCDIR/demo-direct.c $SRCDIR/demo-indirect.c $SRCDIR/demo-direct-with-loop.c ; do
+    (./xgcc -B. \
+	-c $f \
+	--analyzer \
+	-fdiagnostics-format=json \
+	2>&1) | $SRCDIR/contrib/diagnostic-json-to-html.py > $(basename $f).c.html
+done
+
+(./xgcc -B. \
+    -Wall \
+    -fdiagnostics-format=json \
+   -c $SRCDIR/gcc/testsuite/c-c++-common/Wmisleading-indentation.c \
+    2>&1) | $SRCDIR/contrib/diagnostic-json-to-html.py > Wmisleading-indentation.c.html
+
+(./xgcc -B. \
+   -fdiagnostics-format=json \
+    -c $SRCDIR/gcc/testsuite/gcc.dg/plugin/diagnostic-test-paths-3.c \
+    -fplugin=testsuite/gcc/diagnostic_plugin_test_paths.so \
+    2>&1) | $SRCDIR/contrib/diagnostic-json-to-html.py > diagnostic-test-paths-3.c.html
-- 
1.8.5.3

