| #! /usr/bin/env python |
| |
| import errno |
| import os |
| import re |
| 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] |
| |
| |
| 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>[^{]*)\}"), |
| ] |
| |
| |
| def list_documented_items(): |
| """Return a list of everything that's already documented.""" |
| 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 |
| |
| 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() |
| |
| cmd = ("ctags -f - --file-scope=no --c-types=dgpstux " |
| "-Istaticforward -Istatichere=static " |
| + _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() |