mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 13:13:44 +01:00
169 lines
4.5 KiB
Python
169 lines
4.5 KiB
Python
|
#!/usr/bin/python
|
||
|
#
|
||
|
# Copyright (c) 2008 The Tor Project, Inc.
|
||
|
# See LICENSE for licensing information.
|
||
|
#
|
||
|
# Hi!
|
||
|
# I'm redox.py, the Tor redocumentation tool!
|
||
|
# I am a horrible hack!
|
||
|
# I read the output of doxygen from stderr, and add missing DOCDOC comments
|
||
|
# to tell you where documentation should go!
|
||
|
# To use me, edit the stuff below...
|
||
|
# ...and run 'make doxygen 2>doxygen.stderr' ...
|
||
|
# ...and run ./contrib/redox.py < doxygen.stderr !
|
||
|
# I'll make a bunch of new files by adding missing DOCDOC comments to your
|
||
|
# source. Those files will have names like ./src/common/util.c.newdoc.
|
||
|
# You will want to look over the changes by hand before checking them in.
|
||
|
|
||
|
SKIP_FILES = [ "OpenBSD_malloc_Linux.c",
|
||
|
"eventdns.c",
|
||
|
"eventdns.h",
|
||
|
"strlcat.c",
|
||
|
"strlcpy.c",
|
||
|
"aes.c",
|
||
|
"aes.h" ]
|
||
|
|
||
|
SKIP_NAME_PATTERNS = [ r'^.*_c_id$' ]
|
||
|
|
||
|
ADD_DOCDOCS_TO_TYPES = [ 'function', 'type', 'typedef' ]
|
||
|
# ADD_DOCDOCS_TO_TYPES += [ 'variable', 'define' ]
|
||
|
|
||
|
# ====================
|
||
|
# The rest of this should not need hacking.
|
||
|
|
||
|
import re
|
||
|
import sys
|
||
|
|
||
|
KINDS = [ "type", "field", "typedef", "define", "function", "variable" ]
|
||
|
|
||
|
NODOC_LINE_RE = re.compile(r'^([^:]+):(\d+): (\w+): (.*) is not documented\.$')
|
||
|
|
||
|
THING_RE = re.compile(r'^Member ([a-zA-Z0-9_]+).*\((typedef|define|function|variable)\) of (file|class) ')
|
||
|
|
||
|
SKIP_NAMES = [re.compile(s) for s in SKIP_NAME_PATTERNS]
|
||
|
|
||
|
def parsething(thing):
|
||
|
if thing.startswith("Compound "):
|
||
|
tp, name = "type", thing.split()[1]
|
||
|
else:
|
||
|
m = THING_RE.match(thing)
|
||
|
if not m:
|
||
|
print thing
|
||
|
return None, None
|
||
|
else:
|
||
|
name, tp, parent = m.groups()
|
||
|
if parent == 'class':
|
||
|
if tp == 'variable' or tp == 'function':
|
||
|
tp = 'field'
|
||
|
|
||
|
return name, tp
|
||
|
|
||
|
def read():
|
||
|
errs = {}
|
||
|
for line in sys.stdin:
|
||
|
m = NODOC_LINE_RE.match(line)
|
||
|
if m:
|
||
|
file, line, tp, thing = m.groups()
|
||
|
assert tp == 'Warning'
|
||
|
name, kind = parsething(thing)
|
||
|
errs.setdefault(file, []).append((int(line), name, kind))
|
||
|
|
||
|
return errs
|
||
|
|
||
|
def findline(lines, lineno, ident):
|
||
|
for lineno in xrange(lineno, 0, -1):
|
||
|
if ident in lines[lineno]:
|
||
|
return lineno
|
||
|
|
||
|
return None
|
||
|
|
||
|
FUNC_PAT = re.compile(r"^[A-Za-z0-9_]+\(")
|
||
|
|
||
|
def hascomment(lines, lineno, kind):
|
||
|
if "*/" in lines[lineno-1]:
|
||
|
return True
|
||
|
if kind == 'function' and FUNC_PAT.match(lines[lineno]):
|
||
|
if "*/" in lines[lineno-2]:
|
||
|
return True
|
||
|
return False
|
||
|
|
||
|
def hasdocdoc(lines, lineno, kind):
|
||
|
if "DOCDOC" in lines[lineno] or "DOCDOC" in lines[lineno-1]:
|
||
|
return True
|
||
|
if kind == 'function' and FUNC_PAT.match(lines[lineno]):
|
||
|
if "DOCDOC" in lines[lineno-2]:
|
||
|
return True
|
||
|
return False
|
||
|
|
||
|
def checkf(fn, errs, comments):
|
||
|
|
||
|
for skip in SKIP_FILES:
|
||
|
if fn.endswith(skip):
|
||
|
print "Skipping",fn
|
||
|
return
|
||
|
|
||
|
lines = [ None ]
|
||
|
try:
|
||
|
lines.extend( open(fn, 'r').readlines() )
|
||
|
except IOError:
|
||
|
return
|
||
|
|
||
|
for line, name, kind in errs:
|
||
|
if any(pat.match(name) for pat in SKIP_NAMES):
|
||
|
continue
|
||
|
|
||
|
if kind not in ADD_DOCDOCS_TO_TYPES:
|
||
|
continue
|
||
|
|
||
|
ln = findline(lines, line, name)
|
||
|
if ln == None:
|
||
|
print "Couldn't find the definition of %s allegedly on %s of %s"%(
|
||
|
name, line, fn)
|
||
|
else:
|
||
|
if hasdocdoc(lines, line, kind):
|
||
|
# print "Has a DOCDOC"
|
||
|
# print fn, line, name, kind
|
||
|
# print "\t",lines[line-2],
|
||
|
# print "\t",lines[line-1],
|
||
|
# print "\t",lines[line],
|
||
|
# print "-------"
|
||
|
pass
|
||
|
else:
|
||
|
if kind == 'function' and FUNC_PAT.match(lines[ln]):
|
||
|
ln = ln - 1
|
||
|
|
||
|
comments.setdefault(fn, []).append((ln, kind, name))
|
||
|
|
||
|
def applyComments(fn, entries):
|
||
|
N = 0
|
||
|
|
||
|
lines = [ None ]
|
||
|
try:
|
||
|
lines.extend( open(fn, 'r').readlines() )
|
||
|
except IOError:
|
||
|
return
|
||
|
|
||
|
entries.sort()
|
||
|
entries.reverse()
|
||
|
|
||
|
for ln, kind, name in entries:
|
||
|
|
||
|
lines.insert(ln, "/* DOCDOC %s */\n"%name)
|
||
|
N += 1
|
||
|
|
||
|
outf = open(fn+".newdoc", 'w')
|
||
|
for line in lines[1:]:
|
||
|
outf.write(line)
|
||
|
outf.close()
|
||
|
|
||
|
print "Added %s DOCDOCs to %s" %(N, fn)
|
||
|
|
||
|
e = read()
|
||
|
comments = {}
|
||
|
|
||
|
for fn, errs in e.iteritems():
|
||
|
checkf(fn, errs, comments)
|
||
|
|
||
|
for fn, entries in comments.iteritems():
|
||
|
applyComments(fn, entries)
|