]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/scan-view/bin/scan-view
Vendor import of clang trunk r351319 (just before the release_80 branch
[FreeBSD/FreeBSD.git] / tools / scan-view / bin / scan-view
1 #!/usr/bin/env python
2
3 from __future__ import print_function
4
5 """The clang static analyzer results viewer.
6 """
7
8 import sys
9 import imp
10 import os
11 import posixpath
12 import threading
13 import time
14 try:
15     from urllib.request import urlopen
16 except ImportError:
17     from urllib2 import urlopen
18 import webbrowser
19
20 # How long to wait for server to start.
21 kSleepTimeout = .05
22 kMaxSleeps = int(60 / kSleepTimeout)
23
24 # Default server parameters
25
26 kDefaultHost = '127.0.0.1'
27 kDefaultPort = 8181
28 kMaxPortsToTry = 100
29
30 ###
31
32
33 def url_is_up(url):
34     try:
35         o = urlopen(url)
36     except IOError:
37         return False
38     o.close()
39     return True
40
41
42 def start_browser(port, options):
43     import webbrowser
44
45     url = 'http://%s:%d' % (options.host, port)
46
47     # Wait for server to start...
48     if options.debug:
49         sys.stderr.write('%s: Waiting for server.' % sys.argv[0])
50         sys.stderr.flush()
51     for i in range(kMaxSleeps):
52         if url_is_up(url):
53             break
54         if options.debug:
55             sys.stderr.write('.')
56             sys.stderr.flush()
57         time.sleep(kSleepTimeout)
58     else:
59         print('WARNING: Unable to detect that server started.', file=sys.stderr) 
60
61     if options.debug:
62         print('%s: Starting webbrowser...' % sys.argv[0], file=sys.stderr)
63     webbrowser.open(url)
64
65
66 def run(port, options, root):
67     # Prefer to look relative to the installed binary
68     share = os.path.dirname(__file__) + "/../share/scan-view"
69     if not os.path.isdir(share):
70         # Otherwise look relative to the source
71         share = os.path.dirname(__file__) + "/../../scan-view/share"
72     sys.path.append(share)
73
74     import ScanView
75     try:
76         print('Starting scan-view at: http://%s:%d' % (options.host,
77                                                        port))
78         print('  Use Ctrl-C to exit.')
79         httpd = ScanView.create_server((options.host, port),
80                                        options, root)
81         httpd.serve_forever()
82     except KeyboardInterrupt:
83         pass
84
85
86 def port_is_open(port):
87     try:
88         import socketserver
89     except ImportError:
90         import SocketServer as socketserver
91     try:
92         t = socketserver.TCPServer((kDefaultHost, port), None)
93     except:
94         return False
95     t.server_close()
96     return True
97
98
99 def main():
100     import argparse
101     parser = argparse.ArgumentParser(description="The clang static analyzer "
102                                                  "results viewer.")
103     parser.add_argument("root", metavar="<results directory>", type=str)
104     parser.add_argument(
105         '--host', dest="host", default=kDefaultHost, type=str,
106         help="Host interface to listen on. (default=%s)" % kDefaultHost)
107     parser.add_argument('--port', dest="port", default=None, type=int,
108                         help="Port to listen on. (default=%s)" % kDefaultPort)
109     parser.add_argument("--debug", dest="debug", default=0,
110                         action="count",
111                         help="Print additional debugging information.")
112     parser.add_argument("--auto-reload", dest="autoReload", default=False,
113                         action="store_true",
114                         help="Automatically update module for each request.")
115     parser.add_argument("--no-browser", dest="startBrowser", default=True,
116                         action="store_false",
117                         help="Don't open a webbrowser on startup.")
118     parser.add_argument("--allow-all-hosts", dest="onlyServeLocal",
119                         default=True, action="store_false",
120                         help='Allow connections from any host (access '
121                              'restricted to "127.0.0.1" by default)')
122     args = parser.parse_args()
123
124     # Make sure this directory is in a reasonable state to view.
125     if not posixpath.exists(posixpath.join(args.root, 'index.html')):
126         parser.error('Invalid directory, analysis results not found!')
127
128     # Find an open port. We aren't particularly worried about race
129     # conditions here. Note that if the user specified a port we only
130     # use that one.
131     if args.port is not None:
132         port = args.port
133     else:
134         for i in range(kMaxPortsToTry):
135             if port_is_open(kDefaultPort + i):
136                 port = kDefaultPort + i
137                 break
138         else:
139             parser.error('Unable to find usable port in [%d,%d)' %
140                          (kDefaultPort, kDefaultPort+kMaxPortsToTry))
141
142     # Kick off thread to wait for server and start web browser, if
143     # requested.
144     if args.startBrowser:
145         threading.Thread(target=start_browser, args=(port, args)).start()
146
147     run(port, args, args.root)
148
149 if __name__ == '__main__':
150     main()