1 #!/usr/bin/env python 2 3 import os 4 import plistlib 5 6 def main(): 7 from optparse import OptionParser, OptionGroup 8 parser = OptionParser("""\ 9 Usage: %prog [options] <path> 10 11 Utility for dumping Clang-style logged diagnostics.\ 12 """) 13 parser.add_option("-a", "--all", action="store_true", dest="all", 14 default=False, help="dump all messages.") 15 parser.add_option("-e", "--error", action="store_true", dest="error", 16 default=False, help="dump 'error' messages.") 17 parser.add_option("-f", "--fatal", action="store_true", dest="fatal", 18 default=False, help="dump 'fatal error' messages.") 19 parser.add_option("-i", "--ignored", action="store_true", dest="ignored", 20 default=False, help="dump 'ignored' messages.") 21 parser.add_option("-n", "--note", action="store_true", dest="note", 22 default=False, help="dump 'note' messages.") 23 parser.add_option("-w", "--warning", action="store_true", dest="warning", 24 default=False, help="dump 'warning' messages.") 25 (opts, args) = parser.parse_args() 26 27 if len(args) != 1: 28 parser.error("invalid number of arguments") 29 30 levels = {'error': False, 'fatal error': False, 'ignored': False, 31 'note': False, 'warning': False} 32 if opts.error: 33 levels['error'] = True 34 if opts.fatal: 35 levels['fatal error'] = True 36 if opts.ignored: 37 levels['ignored'] = True 38 if opts.note: 39 levels['note'] = True 40 if opts.warning: 41 levels['warning'] = True 42 43 path, = args 44 45 # Read the diagnostics log. 46 f = open(path) 47 try: 48 data = f.read() 49 finally: 50 f.close() 51 52 # Complete the plist (the log itself is just the chunks). 53 data = """\ 54 <?xml version="1.0" encoding="UTF-8"?> 55 <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" \ 56 "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 57 <plist version="1.0"> 58 <array> 59 %s 60 </array> 61 </plist>""" % data 62 63 # Get the list of files and diagnostics to report. 64 to_report = [] 65 diags = plistlib.readPlistFromString(data) 66 for file_diags in diags: 67 file = file_diags.get('main-file') 68 69 # Ignore diagnostics for 'conftest.c', which is the file autoconf uses 70 # for its tests (which frequently will have warnings). 71 if os.path.basename(file) == 'conftest.c': 72 continue 73 74 # Get the diagnostics for the selected levels. 75 selected_diags = [d 76 for d in file_diags.get('diagnostics', ()) 77 if levels[d.get('level')] or opts.all] 78 if selected_diags: 79 to_report.append((file, selected_diags)) 80 81 # If there are no diagnostics to report, show nothing. 82 if not to_report: 83 return 84 85 # Otherwise, print out the diagnostics. 86 print 87 print "**** BUILD DIAGNOSTICS ****" 88 for file,selected_diags in to_report: 89 print "*** %s ***" % file 90 for d in selected_diags: 91 print " %s:%s:%s: %s: %s" % ( 92 d.get('filename'), d.get('line'), d.get('column'), 93 d.get('level'), d.get('message')) 94 95 if __name__ == "__main__": 96 main() 97