|
@@ -0,0 +1,168 @@
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+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' ]
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+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):
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ 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)
|