]> The Tcpdump Group git mirrors - libpcap/blobdiff - testprogs/visopts.py
CI: Call print_so_deps() on rpcapd in remote enabled build
[libpcap] / testprogs / visopts.py
index ab4f396df97d0eba7c8ee433a9df1c055fc962d0..f7df45a54dd267038af931536153bec56ee83b24 100755 (executable)
@@ -1,47 +1,47 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 """
-This program parse the output from pcap_compile() to visualize the CFG after
+This program parses the output from pcap_compile() to visualize the CFG after
 each optimize phase.
 
 Usage guide:
-1. Enable optimizier debugging code when configure libpcap,
-   and build libpcap & filtertest
+1. Enable optimizer debugging code when configure libpcap,
+   and build libpcap & the test programs
        ./configure --enable-optimizer-dbg
        make
-       make filtertest
-2. Run filtertest to compile BPF expression, save to output a.txt
-       ./filtertest EN10MB host 192.168.1.1 > a.txt
+       make testprogs
+2. Run filtertest to compile BPF expression and produce the CFG as a
+   DOT graph, save to output a.txt
+       testprogs/filtertest -g EN10MB host 192.168.1.1 > a.txt
 3. Send a.txt to this program's standard input
-       cat a.txt | tests/visopts.py
+       cat a.txt | testprogs/visopts.py
+   (Graphviz must be installed)
 4. Step 2&3 can be merged:
-       ./filtertest EN10MB host 192.168.1.1 | tests/visopts.py
+       testprogs/filtertest -g EN10MB host 192.168.1.1 | testprogs/visopts.py
 5. The standard output is something like this:
        generated files under directory: /tmp/visopts-W9ekBw
          the directory will be removed when this programs finished.
        open this link: http://localhost:39062/expr1.html
-6. Using open link at the 3rd line `http://localhost:39062/expr1.html'
+6. Open the URL at the 3rd line in a browser.
 
 Note:
-1. CFG graph is translated to SVG document, expr1.html embeded them as external
-   document. If you open expr1.html as local file using file:// protocol, some
-   browsers will deny such requests so the web pages will not shown properly.
-   For chrome, you can run it using following command to avoid this:
+1. The CFG is translated to SVG images, expr1.html embeds them as external
+   documents. If you open expr1.html as local file using file:// protocol, some
+   browsers will deny such requests so the web page will not work properly.
+   For Chrome, you can run it using the following command to avoid this:
        chromium --disable-web-security
-   That's why this program start a localhost http server.
-2. expr1.html use jquery from http://ajax.googleapis.com, so you need internet
-   access to show the web page.
+   That's why this program starts a localhost HTTP server.
+2. expr1.html uses jQuery from https://ajax.googleapis.com, so it needs Internet
+   access to work.
 """
 
 import sys, os
 import string
-import subprocess
-import json
 
 html_template = string.Template("""
 <html>
   <head>
-    <title>BPF compiler optimization phases for $expr </title>
+    <title>BPF compiler optimization phases for "${expr_html}"</title>
     <style type="text/css">
       .hc {
          /* half width container */
@@ -51,13 +51,13 @@ html_template = string.Template("""
       }
     </style>
 
-    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"/></script>
+    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"/></script>
     <!--script type="text/javascript" src="./jquery.min.js"/></script-->
     <script type="text/javascript">
-      var expr = '$expr';
+      var expr = '${expr_json}';
       var exprid = 1;
-      var gcount = $gcount;
-      var logs = JSON.parse('$logs');
+      var gcount = ${gcount};
+      var logs = JSON.parse('${logs}');
       logs[gcount] = "";
 
       var leftsvg = null;
@@ -141,7 +141,7 @@ html_template = string.Template("""
       }
       function load_left(index) {
         var url = gurl(index);
-        var frag = "<embed id='leftsvgc'  type='image/svg+xml' pluginspage='http://www.adobe.com/svg/viewer/install/' src='" + url + "'/>";
+        var frag = "<embed id='leftsvgc'  type='image/svg+xml' pluginspage='https://www.adobe.com/svg/viewer/install/' src='" + url + "'/>";
         $$("#lsvg").html(frag);
         $$("#lcomment").html(logs[index]);
         $$("#lsvglink").attr("href", url);
@@ -150,7 +150,7 @@ html_template = string.Template("""
       }
       function load_right(index) {
         var url = gurl(index);
-        var frag = "<embed id='rightsvgc' type='image/svg+xml' pluginspage='http://www.adobe.com/svg/viewer/install/' src='" + url + "'/>";
+        var frag = "<embed id='rightsvgc' type='image/svg+xml' pluginspage='https://www.adobe.com/svg/viewer/install/' src='" + url + "'/>";
         $$("#rsvg").html(frag);
         $$("#rcomment").html(logs[index]);
         $$("#rsvglink").attr("href", url);
@@ -194,7 +194,7 @@ html_template = string.Template("""
   </head>
   <body style="width: 96%">
     <div>
-      <h1>$expr</h1>
+      <h1>${expr_html}</h1>
       <div style="text-align: center;">
         <button id="backward" type="button">&lt;&lt;</button>
           &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -224,14 +224,29 @@ html_template = string.Template("""
 """)
 
 def write_html(expr, gcount, logs):
-    logs = map(lambda s: s.strip().replace("\n", "<br/>"), logs)
+    import html
+    import json
 
-    global html_template
-    html = html_template.safe_substitute(expr=expr.encode("string-escape"), gcount=gcount, logs=json.dumps(logs).encode("string-escape"))
-    with file("expr1.html", "wt") as f:
-        f.write(html)
+    # In the Python 2.7 version this used to be str.encode('string-escape'),
+    # which was a normal string, but in Python 3 the "string_escape" encoding
+    # no longer exists and even with the "unicode_escape" encoding encode()
+    # always returns a binary string.  So let's just escape the single quotes
+    # here and hope the result is a valid JavaScript string literal.
+    def encode(s):
+        return s.replace("'", "\'")
+
+    mapping = {
+        'expr_html': html.escape(expr),
+        'expr_json': encode(expr),
+        'gcount': gcount,
+        'logs': encode(json.dumps([s.strip().replace("\n", "<br/>") for s in logs])),
+    }
+    with open("expr1.html", "wt") as f:
+        f.write(html_template.safe_substitute(mapping))
 
 def render_on_html(infile):
+    import subprocess
+
     expr = None
     gid = 1
     log = ""
@@ -254,9 +269,17 @@ def render_on_html(infile):
             log += line
 
         if indot == 2:
-            p = subprocess.Popen(['dot', '-Tsvg'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
-            svg = p.communicate(dot)[0]
-            with file("expr1_g%03d.svg" % (gid), "wt") as f:
+            try:
+                svg=subprocess.check_output(['dot', '-Tsvg'], input=dot, universal_newlines=True)
+            except OSError as ose:
+                print("Failed to run 'dot':", ose)
+                print("(Is Graphviz installed?)")
+                return False
+            except subprocess.CalledProcessError as cpe:
+                print("Got an error from the 'dot' process: ", cpe)
+                return False
+
+            with open("expr1_g%03d.svg" % gid, "wt") as f:
                 f.write(svg)
 
             logs.append(log)
@@ -275,14 +298,10 @@ def render_on_html(infile):
     return True
 
 def run_httpd():
-    import SimpleHTTPServer
-    import SocketServer
+    import http.server
 
-    class MySocketServer(SocketServer.TCPServer):
-        allow_reuse_address = True
-    Handler = SimpleHTTPServer.SimpleHTTPRequestHandler
-    httpd = MySocketServer(("localhost", 0), Handler)
-    print "open this link: http://localhost:%d/expr1.html" % (httpd.server_address[1])
+    httpd = http.server.HTTPServer(("localhost", 0), http.server.SimpleHTTPRequestHandler)
+    print("open this link: http://localhost:%d/expr1.html" % httpd.server_port)
     try:
         httpd.serve_forever()
     except KeyboardInterrupt as e:
@@ -294,8 +313,8 @@ def main():
     import shutil
     os.chdir(tempfile.mkdtemp(prefix="visopts-"))
     atexit.register(shutil.rmtree, os.getcwd())
-    print "generated files under directory: %s" % os.getcwd()
-    print "  the directory will be removed when this programs finished."
+    print("generated files under directory: %s" % os.getcwd())
+    print("  the directory will be removed when this program has finished.")
 
     if not render_on_html(sys.stdin):
         return 1
@@ -304,6 +323,6 @@ def main():
 
 if __name__ == "__main__":
     if '-h' in sys.argv or '--help' in sys.argv:
-        print __doc__
+        print(__doc__)
         exit(0)
     exit(main())