diff --git a/Makefile b/Makefile index ba0a48aa..7468de36 100644 --- a/Makefile +++ b/Makefile @@ -129,7 +129,7 @@ clean: $(RM) -r docs/_build autogenerated-config.h: $(addprefix $(srcdir),generate-config-h.py configbuilder.py) - $(PYTHON) $< -o $@ --gcc=$(CC) + $(PYTHON) $< -o $@ --gcc="$(CC)" --plugindir="$(GCCPLUGINS_DIR)" autogenerated-%.txt: $(srcdir)%.txt.in $(CPP) $(CPPFLAGS) -x c-header $^ -o $@ diff --git a/gccutils.py b/gccutils.py index 43304c55..8e18077f 100644 --- a/gccutils.py +++ b/gccutils.py @@ -634,3 +634,45 @@ def check_isinstance(obj, types): """ if not isinstance(obj, types): raise TypeError('%s / %r is not an instance of %s' % (obj, obj, types)) + +def sorted_callgraph(): + """ + Return the callgraph, in topologically-sorted order + """ + return topological_sort(gcc.get_callgraph_nodes(), + get_srcs=lambda n: [edge.caller + for edge in n.callers + # Strip out recursive calls: + if edge.caller != n], + get_dsts=lambda n: [edge.callee + for edge in n.callees + # Strip out recursive calls: + if edge.callee != n]) + +def topological_sort(nodes, get_srcs, get_dsts): + """ + Topological sort in O(n), based on depth-first traversal + """ + result = [] + visited = set() + debug = False + def visit(n): + if n not in visited: + if debug: + print('first visit to %s' % n.decl) + visited.add(n) + for m in get_srcs(n): + visit(m) + if debug: + print('adding to result: %s' % n.decl) + result.append(n) + else: + if debug: + print('already visited %s' % n.decl) + + for n in nodes: + if not get_dsts(n): + visit(n) + + return result + diff --git a/generate-config-h.py b/generate-config-h.py index bca18d0b..7d86f305 100644 --- a/generate-config-h.py +++ b/generate-config-h.py @@ -25,13 +25,18 @@ def __init__(self, argv): import argparse parser = argparse.ArgumentParser() parser.add_argument('--gcc') + parser.add_argument('--plugindir') args, argv = parser.parse_known_args(argv) ConfigBuilder.__init__(self, argv) self.gcc = args.gcc + self.plugindir = args.plugindir def main(self): prefix = 'GCC_PYTHON_PLUGIN_CONFIG_' - plugindir = self.capture_shell_output('locating plugin directory for %s' % self.gcc, + if self.plugindir: + plugindir = self.plugindir + else: + plugindir = self.capture_shell_output('locating plugin directory for %s' % self.gcc, '%s --print-file-name=plugin' % self.gcc).strip() extraargs = ['-I%s' % os.path.join(plugindir, 'include')] self.test_for_mandatory_c_header('gcc-plugin.h', extraargs) diff --git a/libcpychecker/html/make_html.py b/libcpychecker/html/make_html.py index e26de592..e3ec3b50 100755 --- a/libcpychecker/html/make_html.py +++ b/libcpychecker/html/make_html.py @@ -161,7 +161,7 @@ def footer(): """make the footer""" return E.E.footer( E.ATTR(id='footer'), - E.P(u' \xa0|\xa0 '.join(( + E.P('  |  '.join(( 'Hackathon 7.0', 'Buck G, Alex M, Jason M', 'Yelp HQ 2012', @@ -273,7 +273,7 @@ def main(argv): return "Please provide code and json filenames." codefile = open(argv[1]) jsonfile = open(argv[2]) - print HtmlPage(codefile, jsonfile) + print(HtmlPage(codefile, jsonfile)) if __name__ == '__main__': from sys import argv as ARGV diff --git a/misc/fedora/makeindex.py b/misc/fedora/makeindex.py index 92ff5cb0..b227c442 100644 --- a/misc/fedora/makeindex.py +++ b/misc/fedora/makeindex.py @@ -263,7 +263,7 @@ def __init__(self, path): with open(buildlog) as f: for line in f.readlines(): if 0: - print repr(line) + print(repr(line)) m = re.match('NotImplementedError: not yet implemented: (\S+)', line) if m: diff --git a/tests/gccutils/topological-sort/input.c b/tests/gccutils/topological-sort/input.c new file mode 100644 index 00000000..bb05b351 --- /dev/null +++ b/tests/gccutils/topological-sort/input.c @@ -0,0 +1,95 @@ +/* + Copyright 2012 David Malcolm + Copyright 2012 Red Hat, Inc. + + This is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + . +*/ + +/* + Verify that the topological sort code in gccutils works +*/ + +int a(int); +int b(int); +int c(int); +int d(int); +int e(int); +int f(int); +int g(int); +int h(int); +int j(int); +int k(int); + +int a(int i) +{ + return e(i) + c(i); +} + +int b(int i) +{ + return 42 - i; +} + +int c(int i) +{ + return i * i; +} + +int d(int i) +{ + return a(i) + b(c(i)); +} + +/* Directly recursive (actually factorial) */ +int e(int i) +{ + if (i>1) { + return i * e(i-1); + } else { + return 1; + } +} + +/* f and g are mutually recursive */ +int f(int i) +{ + return g(i) + b(i); +} + +int g(int i) +{ + return f(i) + c(i) + k(i); +} + +/* h is entirely disjoint from the rest of the graph */ +int h(int i) +{ + return i; +} + +int j(int i) +{ + return 2 * f(i); +} + +/* k is not defined */ + +/* + PEP-7 +Local variables: +c-basic-offset: 4 +indent-tabs-mode: nil +End: +*/ diff --git a/tests/gccutils/topological-sort/script.py b/tests/gccutils/topological-sort/script.py new file mode 100644 index 00000000..ba4444b9 --- /dev/null +++ b/tests/gccutils/topological-sort/script.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +# Copyright 2012 David Malcolm +# Copyright 2012 Red Hat, Inc. +# +# This is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +# Verify that the topological sort code in gccutils works +import gcc + +def on_pass_execution(p, fn): + if p.name == '*free_lang_data': + from gccutils import sorted_callgraph + for cgn in sorted_callgraph(): + print(cgn.decl) + +gcc.register_callback(gcc.PLUGIN_PASS_EXECUTION, + on_pass_execution) diff --git a/tests/gccutils/topological-sort/stdout.txt b/tests/gccutils/topological-sort/stdout.txt new file mode 100644 index 00000000..511c8550 --- /dev/null +++ b/tests/gccutils/topological-sort/stdout.txt @@ -0,0 +1,10 @@ +j +f +g +k +h +d +a +e +c +b