1800f223bSChad Rosier#!/usr/bin/env python 2800f223bSChad Rosier 3fa40268fSDaniel Dunbarimport os 4800f223bSChad Rosierimport plistlib 5800f223bSChad Rosier 6800f223bSChad Rosierdef main(): 7800f223bSChad Rosier from optparse import OptionParser, OptionGroup 8800f223bSChad Rosier parser = OptionParser("""\ 9800f223bSChad RosierUsage: %prog [options] <path> 10800f223bSChad Rosier 11800f223bSChad RosierUtility for dumping Clang-style logged diagnostics.\ 12800f223bSChad Rosier""") 13800f223bSChad Rosier parser.add_option("-a", "--all", action="store_true", dest="all", 14800f223bSChad Rosier default=False, help="dump all messages.") 15800f223bSChad Rosier parser.add_option("-e", "--error", action="store_true", dest="error", 16800f223bSChad Rosier default=False, help="dump 'error' messages.") 17800f223bSChad Rosier parser.add_option("-f", "--fatal", action="store_true", dest="fatal", 18800f223bSChad Rosier default=False, help="dump 'fatal error' messages.") 19800f223bSChad Rosier parser.add_option("-i", "--ignored", action="store_true", dest="ignored", 20800f223bSChad Rosier default=False, help="dump 'ignored' messages.") 21800f223bSChad Rosier parser.add_option("-n", "--note", action="store_true", dest="note", 22800f223bSChad Rosier default=False, help="dump 'note' messages.") 23800f223bSChad Rosier parser.add_option("-w", "--warning", action="store_true", dest="warning", 24800f223bSChad Rosier default=False, help="dump 'warning' messages.") 25800f223bSChad Rosier (opts, args) = parser.parse_args() 26800f223bSChad Rosier 27800f223bSChad Rosier if len(args) != 1: 28800f223bSChad Rosier parser.error("invalid number of arguments") 29800f223bSChad Rosier 30800f223bSChad Rosier levels = {'error': False, 'fatal error': False, 'ignored': False, 31800f223bSChad Rosier 'note': False, 'warning': False} 32800f223bSChad Rosier if opts.error: 33800f223bSChad Rosier levels['error'] = True 34800f223bSChad Rosier if opts.fatal: 35800f223bSChad Rosier levels['fatal error'] = True 36800f223bSChad Rosier if opts.ignored: 37800f223bSChad Rosier levels['ignored'] = True 38800f223bSChad Rosier if opts.note: 39800f223bSChad Rosier levels['note'] = True 40800f223bSChad Rosier if opts.warning: 41800f223bSChad Rosier levels['warning'] = True 42800f223bSChad Rosier 43800f223bSChad Rosier path, = args 44800f223bSChad Rosier 45800f223bSChad Rosier # Read the diagnostics log. 46800f223bSChad Rosier f = open(path) 47800f223bSChad Rosier try: 48800f223bSChad Rosier data = f.read() 49800f223bSChad Rosier finally: 50800f223bSChad Rosier f.close() 51800f223bSChad Rosier 52800f223bSChad Rosier # Complete the plist (the log itself is just the chunks). 53800f223bSChad Rosier data = """\ 54800f223bSChad Rosier<?xml version="1.0" encoding="UTF-8"?> 55800f223bSChad Rosier<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" \ 56800f223bSChad Rosier "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 57800f223bSChad Rosier<plist version="1.0"> 58800f223bSChad Rosier<array> 59800f223bSChad Rosier%s 60800f223bSChad Rosier</array> 61800f223bSChad Rosier</plist>""" % data 62800f223bSChad Rosier 63fa40268fSDaniel Dunbar # Get the list of files and diagnostics to report. 64fa40268fSDaniel Dunbar to_report = [] 65800f223bSChad Rosier diags = plistlib.readPlistFromString(data) 66fa40268fSDaniel Dunbar for file_diags in diags: 67fa40268fSDaniel Dunbar file = file_diags.get('main-file') 68800f223bSChad Rosier 69*0c85c488SDuncan P. N. Exon Smith # Diagnostics from modules don't have a main-file listed. 70*0c85c488SDuncan P. N. Exon Smith if not file: 71*0c85c488SDuncan P. N. Exon Smith file = '<module-includes>' 72*0c85c488SDuncan P. N. Exon Smith 73fa40268fSDaniel Dunbar # Ignore diagnostics for 'conftest.c', which is the file autoconf uses 74fa40268fSDaniel Dunbar # for its tests (which frequently will have warnings). 75fa40268fSDaniel Dunbar if os.path.basename(file) == 'conftest.c': 76fa40268fSDaniel Dunbar continue 77fa40268fSDaniel Dunbar 78fa40268fSDaniel Dunbar # Get the diagnostics for the selected levels. 79fa40268fSDaniel Dunbar selected_diags = [d 80fa40268fSDaniel Dunbar for d in file_diags.get('diagnostics', ()) 81fa40268fSDaniel Dunbar if levels[d.get('level')] or opts.all] 82fa40268fSDaniel Dunbar if selected_diags: 83fa40268fSDaniel Dunbar to_report.append((file, selected_diags)) 84fa40268fSDaniel Dunbar 85fa40268fSDaniel Dunbar # If there are no diagnostics to report, show nothing. 86fa40268fSDaniel Dunbar if not to_report: 87fa40268fSDaniel Dunbar return 88fa40268fSDaniel Dunbar 89fa40268fSDaniel Dunbar # Otherwise, print out the diagnostics. 90800f223bSChad Rosier print 91800f223bSChad Rosier print "**** BUILD DIAGNOSTICS ****" 92fa40268fSDaniel Dunbar for file,selected_diags in to_report: 93800f223bSChad Rosier print "*** %s ***" % file 94fa40268fSDaniel Dunbar for d in selected_diags: 95800f223bSChad Rosier print " %s:%s:%s: %s: %s" % ( 96800f223bSChad Rosier d.get('filename'), d.get('line'), d.get('column'), 97800f223bSChad Rosier d.get('level'), d.get('message')) 98800f223bSChad Rosier 99800f223bSChad Rosierif __name__ == "__main__": 100800f223bSChad Rosier main() 101