findcsyms 3.57 KB
Newer Older
1 2 3 4
#! /usr/bin/env python

import errno
import os
5
import re
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
import sys

if __name__ == "__main__":
    _base = sys.argv[0]
else:
    _base = __file__

_script_home = os.path.abspath(os.path.dirname(_base))

srcdir = os.path.dirname(os.path.dirname(_script_home))

EXCLUDES = ["bitset.h", "cStringIO.h", "graminit.h", "grammar.h",
            "longintrepr.h", "metagrammar.h",
            "node.h", "opcode.h", "osdefs.h", "pgenheaders.h",
            "py_curses.h", "parsetok.h", "symtable.h", "token.h"]


def list_headers():
    """Return a list of headers."""
    incdir = os.path.join(srcdir, "Include")
    return [fn for fn in os.listdir(incdir)
            if fn.endswith(".h") and fn not in EXCLUDES]

29 30 31 32 33 34 35 36 37 38 39 40 41 42 43

def matcher(pattern):
    return re.compile(pattern).match

MATCHERS = [
    matcher(r"\\begin\{cfuncdesc\}\{[^{]*\}\{(?P<sym>[^{]*)\}"),
    matcher(r"\\cfuncline\{[^{]*\}\{(?P<sym>[^{]*)\}"),
    matcher(r"\\begin\{ctypedesc\}(\[[^{]*\])?\{(?P<sym>[^{]*)\}"),
    matcher(r"\\begin\{cvardesc\}\{[^{]*\}\{(?P<sym>[^{]*)\}"),
    matcher(r"\\begin\{cmemberdesc\}\{[^{]*\}\{(?P<sym>[^{]*)\}"),
    matcher(r"\\cmemberline\{[^{]*\}\{(?P<sym>[^{]*)\}"),
    matcher(r"\\begin\{csimplemacrodesc\}\{(?P<sym>[^{]*)\}"),
    ]


44 45
def list_documented_items():
    """Return a list of everything that's already documented."""
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
    apidir = os.path.join(srcdir, "Doc", "api")
    files = [fn for fn in os.listdir(apidir) if fn.endswith(".tex")]
    L = []
    for fn in files:
        fullname = os.path.join(apidir, fn)
        for line in open(fullname):
            line = line.lstrip()
            if not line.startswith("\\"):
                continue
            for matcher in MATCHERS:
                m = matcher(line)
                if m:
                    L.append(m.group("sym"))
                    break
    return L
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101

def split_documented(all, documented):
    """Split the list of all symbols into documented and undocumented
    categories."""
    doc = []
    undoc = []
    for t in all:
        if t[0] in documented:
            doc.append(t)
        else:
            undoc.append(t)
    return doc, undoc

def print_list(L, title=None):
    """Dump a list to stdout."""
    if title:
        print title + ":"
        print "-" * (len(title) + 1)
    w = 0
    for sym, filename in L:
        w = max(w, len(sym))
    if w % 4 == 0:
        w += 4
    else:
        w += (4 - (w % 4))
    for sym, filename in L:
        print "%-*s%s" % (w, sym, filename)


_spcjoin = ' '.join

def main():
    args = sys.argv[1:]
    if args:
        headers = args
        documented = []
    else:
        os.chdir(os.path.join(srcdir, "Include"))
        headers = list_headers()
        documented = list_documented_items()

102 103
    cmd = ("ctags -f - --file-scope=no --c-types=dgpstux "
           "-Istaticforward -Istatichere=static "
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
           + _spcjoin(headers))
    fp = os.popen(cmd)
    L = []
    prevsym = None
    while 1:
        line = fp.readline()
        if not line:
            break
        sym, filename = line.split()[:2]
        if sym == prevsym:
            continue
        if not sym.endswith("_H"):
            L.append((sym, filename))
            prevsym = sym
    L.sort()
    fp.close()

    try:
        if documented:
            documented, undocumented = split_documented(L, documented)
            print_list(documented, "Documented symbols")
            if undocumented:
                print
                print_list(undocumented, "Undocumented symbols")
        else:
            print_list(L)
    except IOError, e:
        if e.errno != errno.EPIPE:
            raise


if __name__ == "__main__":
    main()