summaryrefslogtreecommitdiff
path: root/scripts/maint
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/maint')
-rwxr-xr-xscripts/maint/annotate_ifdef_directives74
-rwxr-xr-xscripts/maint/checkSpace.pl6
-rwxr-xr-xscripts/maint/lintChanges.py67
-rwxr-xr-xscripts/maint/run_calltool.sh29
4 files changed, 157 insertions, 19 deletions
diff --git a/scripts/maint/annotate_ifdef_directives b/scripts/maint/annotate_ifdef_directives
new file mode 100755
index 0000000000..368d842e2e
--- /dev/null
+++ b/scripts/maint/annotate_ifdef_directives
@@ -0,0 +1,74 @@
+#!/usr/bin/python
+# Copyright (c) 2017, The Tor Project, Inc.
+# See LICENSE for licensing information
+
+import re
+
+LINE_OBVIOUSNESS_LIMIT = 4
+
+class Problem(Exception):
+ pass
+
+def uncomment(s):
+ s = re.sub(r'//.*','',s)
+ s = re.sub(r'/\*.*','',s)
+ return s.strip()
+
+def translate(f_in, f_out):
+ whole_file = []
+ stack = []
+ cur_level = whole_file
+ lineno = 0
+ for line in f_in:
+ lineno += 1
+ m = re.match(r'\s*#\s*(if|ifdef|ifndef|else|endif|elif)\b\s*(.*)',
+ line)
+ if not m:
+ f_out.write(line)
+ continue
+ command,rest = m.groups()
+ if command in ("if", "ifdef", "ifndef"):
+ # The #if directive pushes us one level lower on the stack.
+ if command == 'ifdef':
+ rest = "defined(%s)"%uncomment(rest)
+ elif command == 'ifndef':
+ rest = "!defined(%s)"%uncomment(rest)
+ elif rest.endswith("\\"):
+ rest = rest[:-1]+"..."
+
+ rest = uncomment(rest)
+
+ new_level = [ (command, rest, lineno) ]
+ stack.append(cur_level)
+ cur_level = new_level
+ f_out.write(line)
+ elif command in ("else", "elif"):
+ if len(cur_level) == 0 or cur_level[-1][0] == 'else':
+ raise Problem("Unexpected #%s on %d"% (command,lineno))
+ if (len(cur_level) == 1 and command == 'else' and
+ lineno > cur_level[0][2] + LINE_OBVIOUSNESS_LIMIT):
+ f_out.write("#else /* !(%s) */\n"%cur_level[0][1])
+ else:
+ f_out.write(line)
+ cur_level.append((command, rest, lineno))
+ else:
+ assert command == 'endif'
+ if len(stack) == 0:
+ raise Problem("Unmatched #%s on %s"% (command,lineno))
+ if lineno <= cur_level[0][2] + LINE_OBVIOUSNESS_LIMIT:
+ f_out.write(line)
+ elif len(cur_level) == 1 or (
+ len(cur_level) == 2 and cur_level[1][0] == 'else'):
+ f_out.write("#endif /* %s */\n"%cur_level[0][1])
+ else:
+ f_out.write("#endif /* %s || ... */\n"%cur_level[0][1])
+ cur_level = stack.pop()
+ if len(stack) or cur_level != whole_file:
+ raise Problem("Missing #endif")
+
+import sys,os
+for fn in sys.argv[1:]:
+ with open(fn+"_OUT", 'w') as output_file:
+ translate(open(fn, 'r'), output_file)
+ os.rename(fn+"_OUT", fn)
+
diff --git a/scripts/maint/checkSpace.pl b/scripts/maint/checkSpace.pl
index 6d19d6ccde..9929932cc5 100755
--- a/scripts/maint/checkSpace.pl
+++ b/scripts/maint/checkSpace.pl
@@ -123,6 +123,10 @@ for my $fn (@ARGV) {
if (/([^\s'])\{/) {
msg " $1\{:$fn:$.\n";
}
+ ## Warn about double semi-colons at the end of a line.
+ if (/;;$/) {
+ msg " double semi-colons at the end of $. in $fn\n"
+ }
## Warn about multiple internal spaces.
#if (/[^\s,:]\s{2,}[^\s\\=]/) {
# msg " X X:$fn:$.\n";
@@ -140,7 +144,7 @@ for my $fn (@ARGV) {
$1 ne "switch" and $1 ne "return" and $1 ne "int" and
$1 ne "elsif" and $1 ne "WINAPI" and $2 ne "WINAPI" and
$1 ne "void" and $1 ne "__attribute__" and $1 ne "op" and
- $1 ne "size_t" and $1 ne "double" and
+ $1 ne "size_t" and $1 ne "double" and $1 ne "uint64_t" and
$1 ne "workqueue_reply_t") {
msg " fn ():$fn:$.\n";
}
diff --git a/scripts/maint/lintChanges.py b/scripts/maint/lintChanges.py
index bf06064fa8..d5b8fcae5c 100755
--- a/scripts/maint/lintChanges.py
+++ b/scripts/maint/lintChanges.py
@@ -20,8 +20,20 @@ KNOWN_GROUPS = set([
"Testing",
"Documentation",
"Code simplification and refactoring",
- "Removed features"])
+ "Removed features",
+ "Deprecated features",
+ "Directory authority changes"])
+NEEDS_SUBCATEGORIES = set([
+ "Minor bugfix",
+ "Minor bugfixes",
+ "Major bugfix",
+ "Major bugfixes",
+ "Minor feature",
+ "Minor features",
+ "Major feature",
+ "Major features",
+ ])
def lintfile(fname):
have_warned = []
@@ -46,13 +58,11 @@ def lintfile(fname):
m = re.match(r'^[ ]{2}o ([^\(:]*)([^:]*):', contents)
if not m:
- warn("header not in format expected")
+ warn("Header not in format expected. (' o Foo:' or ' o Foo (Bar):')")
elif m.group(1).strip() not in KNOWN_GROUPS:
- warn("Weird header: %r" % m.group(1))
- elif (("bugfix" in m.group(1) or "feature" in m.group(1)) and
- ("Removed" not in m.group(1)) and
- '(' not in m.group(2)):
- warn("Missing subcategory on %s" % m.group(1))
+ warn("Unrecognized header: %r" % m.group(1))
+ elif (m.group(1) in NEEDS_SUBCATEGORIES and '(' not in m.group(2)):
+ warn("Missing subcategory on %r" % m.group(1))
if m:
isBug = ("bug" in m.group(1).lower() or "fix" in m.group(1).lower())
@@ -62,25 +72,46 @@ def lintfile(fname):
contents = " ".join(contents.split())
if re.search(r'\#\d{2,}', contents):
- warn("don't use a # before ticket numbers")
+ warn("Don't use a # before ticket numbers. ('bug 1234' not '#1234')")
if isBug and not re.search(r'(\d+)', contents):
- warn("bugfix does not mention a number")
- elif isBug and not re.search(r'Fixes ([a-z ]*)bug (\d+)', contents):
- warn("bugfix does not say 'Fixes bug XXX'")
+ warn("Ticket marked as bugfix, but does not mention a number.")
+ elif isBug and not re.search(r'Fixes ([a-z ]*)bugs? (\d+)', contents):
+ warn("Ticket marked as bugfix, but does not say 'Fixes bug XXX'")
if re.search(r'[bB]ug (\d+)', contents):
if not re.search(r'[Bb]ugfix on ', contents):
- warn("bugfix does not say 'bugfix on X.Y.Z'")
- elif not re.search('[fF]ixes ([a-z ]*)bug (\d+); bugfix on ',
+ warn("Bugfix does not say 'bugfix on X.Y.Z'")
+ elif not re.search('[fF]ixes ([a-z ]*)bugs? (\d+)((, \d+)* and \d+)?; bugfix on ',
contents):
- warn("bugfix incant is not semicoloned")
+ warn("Bugfix does not say 'Fixes bug X; bugfix on Y'")
elif re.search('tor-([0-9]+)', contents):
- warn("do not prefix versions with 'tor-'")
-
+ warn("Do not prefix versions with 'tor-'. ('0.1.2', not 'tor-0.1.2'.)")
+
+ return have_warned != []
+
+def files(args):
+ """Walk through the arguments: for directories, yield their contents;
+ for files, just yield the files. Only search one level deep, because
+ that's how the changes directory is laid out."""
+ for f in args:
+ if os.path.isdir(f):
+ for item in os.listdir(f):
+ if item.startswith("."): #ignore dotfiles
+ continue
+ yield os.path.join(f, item)
+ else:
+ yield f
if __name__ == '__main__':
- for fname in sys.argv[1:]:
+ problems = 0
+ for fname in files(sys.argv[1:]):
if fname.endswith("~"):
continue
- lintfile(fname)
+ if lintfile(fname):
+ problems += 1
+
+ if problems:
+ sys.exit(1)
+ else:
+ sys.exit(0)
diff --git a/scripts/maint/run_calltool.sh b/scripts/maint/run_calltool.sh
new file mode 100755
index 0000000000..efb8706fea
--- /dev/null
+++ b/scripts/maint/run_calltool.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+# You can find calltool at https://gitweb.torproject.org/user/nickm/calltool.git
+
+set -e
+
+if test "x$CALLTOOL_PATH" != "x"; then
+ PYTHONPATH="${CALLTOOL_PATH}:${PYTHONPATH}"
+ export PYTHONPATH
+fi
+
+mkdir -p callgraph
+
+SUBITEMS="fn_graph fn_invgraph fn_scc fn_scc_weaklinks module_graph module_invgraph module_scc module_scc_weaklinks"
+
+for calculation in $SUBITEMS; do
+ echo "======== $calculation"
+ python -m calltool $calculation > callgraph/$calculation
+done
+
+echo <<EOF > callgraph/README
+This directory holds output from calltool, as run on Tor. For more
+information about each of these files, see the NOTES and README files in
+the calltool distribution.
+
+You can find calltool at
+ https://gitweb.torproject.org/user/nickm/calltool.git
+EOF
+