158194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar#!/usr/bin/env python
258194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar
370d4e75a37fcd98e9a29073ef6d84fad6663bb02Daniel Dunbarimport os
458194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbarimport plistlib
558194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar
658194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbardef main():
758194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar    from optparse import OptionParser, OptionGroup
858194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar    parser = OptionParser("""\
97f53d592ffbef0225a95cbd97d653307f546a347Chad RosierUsage: %prog [options] <path>
1058194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar
1158194307c1a45f6a20f5ed421c97309a9e007e46Daniel DunbarUtility for dumping Clang-style logged diagnostics.\
1258194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar""")
137f53d592ffbef0225a95cbd97d653307f546a347Chad Rosier    parser.add_option("-a", "--all", action="store_true", dest="all", 
147f53d592ffbef0225a95cbd97d653307f546a347Chad Rosier                      default=False, help="dump all messages.")
157f53d592ffbef0225a95cbd97d653307f546a347Chad Rosier    parser.add_option("-e", "--error", action="store_true", dest="error", 
167f53d592ffbef0225a95cbd97d653307f546a347Chad Rosier                      default=False, help="dump 'error' messages.")
177f53d592ffbef0225a95cbd97d653307f546a347Chad Rosier    parser.add_option("-f", "--fatal", action="store_true", dest="fatal", 
187f53d592ffbef0225a95cbd97d653307f546a347Chad Rosier                      default=False, help="dump 'fatal error' messages.")
197f53d592ffbef0225a95cbd97d653307f546a347Chad Rosier    parser.add_option("-i", "--ignored", action="store_true", dest="ignored", 
207f53d592ffbef0225a95cbd97d653307f546a347Chad Rosier                      default=False, help="dump 'ignored' messages.")
217f53d592ffbef0225a95cbd97d653307f546a347Chad Rosier    parser.add_option("-n", "--note", action="store_true", dest="note", 
227f53d592ffbef0225a95cbd97d653307f546a347Chad Rosier                      default=False, help="dump 'note' messages.")
237f53d592ffbef0225a95cbd97d653307f546a347Chad Rosier    parser.add_option("-w", "--warning", action="store_true", dest="warning", 
247f53d592ffbef0225a95cbd97d653307f546a347Chad Rosier                      default=False, help="dump 'warning' messages.")
2558194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar    (opts, args) = parser.parse_args()
2658194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar
2758194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar    if len(args) != 1:
2858194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar        parser.error("invalid number of arguments")
2958194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar
307f53d592ffbef0225a95cbd97d653307f546a347Chad Rosier    levels = {'error': False, 'fatal error': False, 'ignored': False,
317f53d592ffbef0225a95cbd97d653307f546a347Chad Rosier              'note': False, 'warning': False}
327f53d592ffbef0225a95cbd97d653307f546a347Chad Rosier    if opts.error:
337f53d592ffbef0225a95cbd97d653307f546a347Chad Rosier        levels['error'] = True
347f53d592ffbef0225a95cbd97d653307f546a347Chad Rosier    if opts.fatal:
357f53d592ffbef0225a95cbd97d653307f546a347Chad Rosier        levels['fatal error'] = True
367f53d592ffbef0225a95cbd97d653307f546a347Chad Rosier    if opts.ignored:
377f53d592ffbef0225a95cbd97d653307f546a347Chad Rosier        levels['ignored'] = True
387f53d592ffbef0225a95cbd97d653307f546a347Chad Rosier    if opts.note:
397f53d592ffbef0225a95cbd97d653307f546a347Chad Rosier        levels['note'] = True
407f53d592ffbef0225a95cbd97d653307f546a347Chad Rosier    if opts.warning:
417f53d592ffbef0225a95cbd97d653307f546a347Chad Rosier        levels['warning'] = True
427f53d592ffbef0225a95cbd97d653307f546a347Chad Rosier
4358194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar    path, = args
4458194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar
4558194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar    # Read the diagnostics log.
4658194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar    f = open(path)
4758194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar    try:
4858194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar        data = f.read()
4958194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar    finally:
5058194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar        f.close()
5158194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar
5258194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar    # Complete the plist (the log itself is just the chunks).
5358194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar    data = """\
5458194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar<?xml version="1.0" encoding="UTF-8"?>
5558194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" \
5658194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar                       "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
5758194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar<plist version="1.0">
5858194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar<array>
5958194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar%s
6058194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar</array>
6158194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar</plist>""" % data
6258194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar
6370d4e75a37fcd98e9a29073ef6d84fad6663bb02Daniel Dunbar    # Get the list of files and diagnostics to report.
6470d4e75a37fcd98e9a29073ef6d84fad6663bb02Daniel Dunbar    to_report = []
6558194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar    diags = plistlib.readPlistFromString(data)
6670d4e75a37fcd98e9a29073ef6d84fad6663bb02Daniel Dunbar    for file_diags in diags:
6770d4e75a37fcd98e9a29073ef6d84fad6663bb02Daniel Dunbar        file = file_diags.get('main-file')
6870d4e75a37fcd98e9a29073ef6d84fad6663bb02Daniel Dunbar
6970d4e75a37fcd98e9a29073ef6d84fad6663bb02Daniel Dunbar        # Ignore diagnostics for 'conftest.c', which is the file autoconf uses
7070d4e75a37fcd98e9a29073ef6d84fad6663bb02Daniel Dunbar        # for its tests (which frequently will have warnings).
7170d4e75a37fcd98e9a29073ef6d84fad6663bb02Daniel Dunbar        if os.path.basename(file) == 'conftest.c':
7270d4e75a37fcd98e9a29073ef6d84fad6663bb02Daniel Dunbar            continue
7370d4e75a37fcd98e9a29073ef6d84fad6663bb02Daniel Dunbar
7470d4e75a37fcd98e9a29073ef6d84fad6663bb02Daniel Dunbar        # Get the diagnostics for the selected levels.
7570d4e75a37fcd98e9a29073ef6d84fad6663bb02Daniel Dunbar        selected_diags = [d
7670d4e75a37fcd98e9a29073ef6d84fad6663bb02Daniel Dunbar                          for d in file_diags.get('diagnostics', ())
7770d4e75a37fcd98e9a29073ef6d84fad6663bb02Daniel Dunbar                          if levels[d.get('level')] or opts.all]
7870d4e75a37fcd98e9a29073ef6d84fad6663bb02Daniel Dunbar        if selected_diags:
7970d4e75a37fcd98e9a29073ef6d84fad6663bb02Daniel Dunbar            to_report.append((file, selected_diags))
8058194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar
8170d4e75a37fcd98e9a29073ef6d84fad6663bb02Daniel Dunbar    # If there are no diagnostics to report, show nothing.
8270d4e75a37fcd98e9a29073ef6d84fad6663bb02Daniel Dunbar    if not to_report:
8370d4e75a37fcd98e9a29073ef6d84fad6663bb02Daniel Dunbar        return
8470d4e75a37fcd98e9a29073ef6d84fad6663bb02Daniel Dunbar
8570d4e75a37fcd98e9a29073ef6d84fad6663bb02Daniel Dunbar    # Otherwise, print out the diagnostics.
8658194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar    print
8758194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar    print "**** BUILD DIAGNOSTICS ****"
8870d4e75a37fcd98e9a29073ef6d84fad6663bb02Daniel Dunbar    for file,selected_diags in to_report:
8958194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar        print "*** %s ***" % file
9070d4e75a37fcd98e9a29073ef6d84fad6663bb02Daniel Dunbar        for d in selected_diags:
9170d4e75a37fcd98e9a29073ef6d84fad6663bb02Daniel Dunbar            print " %s:%s:%s: %s: %s" % (
9270d4e75a37fcd98e9a29073ef6d84fad6663bb02Daniel Dunbar                d.get('filename'), d.get('line'), d.get('column'),
9370d4e75a37fcd98e9a29073ef6d84fad6663bb02Daniel Dunbar                d.get('level'), d.get('message'))
9458194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar
9558194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbarif __name__ == "__main__":
9658194307c1a45f6a20f5ed421c97309a9e007e46Daniel Dunbar    main()
97