summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin H. Johnson <robbat2@gentoo.org>2015-08-08 13:49:04 -0700
committerRobin H. Johnson <robbat2@gentoo.org>2015-08-08 17:38:18 -0700
commit56bd759df1d0c750a065b8c845e93d5dfa6b549d (patch)
tree3f91093cdb475e565ae857f1c5a7fd339e2d781e /dev-util/gprof2dot
downloadgentoo-56bd759df1d0c750a065b8c845e93d5dfa6b549d.tar.gz
gentoo-56bd759df1d0c750a065b8c845e93d5dfa6b549d.tar.bz2
gentoo-56bd759df1d0c750a065b8c845e93d5dfa6b549d.zip
proj/gentoo: Initial commit
This commit represents a new era for Gentoo: Storing the gentoo-x86 tree in Git, as converted from CVS. This commit is the start of the NEW history. Any historical data is intended to be grafted onto this point. Creation process: 1. Take final CVS checkout snapshot 2. Remove ALL ChangeLog* files 3. Transform all Manifests to thin 4. Remove empty Manifests 5. Convert all stale $Header$/$Id$ CVS keywords to non-expanded Git $Id$ 5.1. Do not touch files with -kb/-ko keyword flags. Signed-off-by: Robin H. Johnson <robbat2@gentoo.org> X-Thanks: Alec Warner <antarus@gentoo.org> - did the GSoC 2006 migration tests X-Thanks: Robin H. Johnson <robbat2@gentoo.org> - infra guy, herding this project X-Thanks: Nguyen Thai Ngoc Duy <pclouds@gentoo.org> - Former Gentoo developer, wrote Git features for the migration X-Thanks: Brian Harring <ferringb@gentoo.org> - wrote much python to improve cvs2svn X-Thanks: Rich Freeman <rich0@gentoo.org> - validation scripts X-Thanks: Patrick Lauer <patrick@gentoo.org> - Gentoo dev, running new 2014 work in migration X-Thanks: Michał Górny <mgorny@gentoo.org> - scripts, QA, nagging X-Thanks: All of other Gentoo developers - many ideas and lots of paint on the bikeshed
Diffstat (limited to 'dev-util/gprof2dot')
-rw-r--r--dev-util/gprof2dot/Manifest1
-rw-r--r--dev-util/gprof2dot/files/gprof2dot-0_p20100216-python3.patch489
-rw-r--r--dev-util/gprof2dot/files/gprof2dot-0_p20130517-py3-xrange.patch10
-rw-r--r--dev-util/gprof2dot/gprof2dot-0_p20130517.ebuild51
-rw-r--r--dev-util/gprof2dot/metadata.xml8
5 files changed, 559 insertions, 0 deletions
diff --git a/dev-util/gprof2dot/Manifest b/dev-util/gprof2dot/Manifest
new file mode 100644
index 000000000000..f5e3cfc4d54b
--- /dev/null
+++ b/dev-util/gprof2dot/Manifest
@@ -0,0 +1 @@
+DIST gprof2dot-0_p20130517.tar.xz 1080464 SHA256 d491a8048a7ebc169557393ee517ede3c3958696e5257fbe3698bfbab6218691 SHA512 1907cb889d1776723ca944d588fa4185afdeee11cc85ec40c03832568d91612bab708160c69036fc45fef05bca62c5bc8f6ef19cbb45c6bfd1952dda94c54a4b WHIRLPOOL 1f04729faf6fa47921c3b953d4a38db598d9905a35d198ff7680e778f214e5ec54026840de7a8bcfaf351fdceadd3d0ba3865dbbe95cbc28704b6cab9670b2d7
diff --git a/dev-util/gprof2dot/files/gprof2dot-0_p20100216-python3.patch b/dev-util/gprof2dot/files/gprof2dot-0_p20100216-python3.patch
new file mode 100644
index 000000000000..875ccbc1ebd9
--- /dev/null
+++ b/dev-util/gprof2dot/files/gprof2dot-0_p20100216-python3.patch
@@ -0,0 +1,489 @@
+From 6087a16e81d5c41647e05291dd25bb6eac9493eb Mon Sep 17 00:00:00 2001
+From: Sebastian Pipping <sebastian@pipping.org>
+Date: Fri, 5 Nov 2010 18:10:29 +0100
+Subject: [PATCH] Support both Python 2.x and 3.x
+
+---
+ gprof2dot.py | 138 ++++++++++++++++++++++++++++++++++------------------------
+ 1 files changed, 81 insertions(+), 57 deletions(-)
+
+diff --git a/gprof2dot.py b/gprof2dot.py
+index bf0aba8..888081f 100755
+--- a/gprof2dot.py
++++ b/gprof2dot.py
+@@ -32,6 +32,27 @@ import optparse
+ import xml.parsers.expat
+
+
++# Python 2.x/3.x compatibility
++if sys.version_info[0] == 3:
++ PYTHON_3 = True
++ def compat_iteritems(x): return x.items() # No iteritems() in Python 3
++ def compat_itervalues(x): return x.values() # No itervalues() in Python 3
++ def compat_keys(x): return list(x.keys()) # keys() is a generator in Python 3
++ compat_basestring = str # No class basestring in Python 3
++
++ CALL_TIMES_FORMAT = "%u\xd7" # All strings are unicode in Python 3, no u"" marking
++else:
++ PYTHON_3 = False
++ def compat_iteritems(x): return x.iteritems()
++ def compat_itervalues(x): return x.itervalues()
++ def compat_keys(x): return x.keys()
++ compat_basestring = basestring
++
++ # u"" strings not supported in Python 3
++ # By using eval() we don't get a syntax error
++ CALL_TIMES_FORMAT = eval('u"%u\xd7"')
++
++
+ try:
+ # Debugging helper module
+ import debug
+@@ -40,7 +61,7 @@ except ImportError:
+
+
+ def times(x):
+- return u"%u\xd7" % (x,)
++ return CALL_TIMES_FORMAT % (x,)
+
+ def percentage(p):
+ return "%.02f%%" % (p*100.0,)
+@@ -236,8 +257,8 @@ class Profile(Object):
+ def validate(self):
+ """Validate the edges."""
+
+- for function in self.functions.itervalues():
+- for callee_id in function.calls.keys():
++ for function in compat_itervalues(self.functions):
++ for callee_id in compat_keys(function.calls):
+ assert function.calls[callee_id].callee_id == callee_id
+ if callee_id not in self.functions:
+ sys.stderr.write('warning: call to undefined function %s from function %s\n' % (str(callee_id), function.name))
+@@ -248,11 +269,11 @@ class Profile(Object):
+
+ # Apply the Tarjan's algorithm successively until all functions are visited
+ visited = set()
+- for function in self.functions.itervalues():
++ for function in compat_itervalues(self.functions):
+ if function not in visited:
+ self._tarjan(function, 0, [], {}, {}, visited)
+ cycles = []
+- for function in self.functions.itervalues():
++ for function in compat_itervalues(self.functions):
+ if function.cycle is not None and function.cycle not in cycles:
+ cycles.append(function.cycle)
+ self.cycles = cycles
+@@ -275,7 +296,7 @@ class Profile(Object):
+ order += 1
+ pos = len(stack)
+ stack.append(function)
+- for call in function.calls.itervalues():
++ for call in compat_itervalues(function.calls):
+ callee = self.functions[call.callee_id]
+ # TODO: use a set to optimize lookup
+ if callee not in orders:
+@@ -299,10 +320,10 @@ class Profile(Object):
+ for cycle in self.cycles:
+ cycle_totals[cycle] = 0.0
+ function_totals = {}
+- for function in self.functions.itervalues():
++ for function in compat_itervalues(self.functions):
+ function_totals[function] = 0.0
+- for function in self.functions.itervalues():
+- for call in function.calls.itervalues():
++ for function in compat_itervalues(self.functions):
++ for call in compat_itervalues(function.calls):
+ if call.callee_id != function.id:
+ callee = self.functions[call.callee_id]
+ function_totals[callee] += call[event]
+@@ -310,8 +331,8 @@ class Profile(Object):
+ cycle_totals[callee.cycle] += call[event]
+
+ # Compute the ratios
+- for function in self.functions.itervalues():
+- for call in function.calls.itervalues():
++ for function in compat_itervalues(self.functions):
++ for call in compat_itervalues(function.calls):
+ assert call.ratio is None
+ if call.callee_id != function.id:
+ callee = self.functions[call.callee_id]
+@@ -332,10 +353,10 @@ class Profile(Object):
+
+ # Sanity checking
+ assert outevent not in self
+- for function in self.functions.itervalues():
++ for function in compat_itervalues(self.functions):
+ assert outevent not in function
+ assert inevent in function
+- for call in function.calls.itervalues():
++ for call in compat_itervalues(function.calls):
+ assert outevent not in call
+ if call.callee_id != function.id:
+ assert call.ratio is not None
+@@ -343,13 +364,13 @@ class Profile(Object):
+ # Aggregate the input for each cycle
+ for cycle in self.cycles:
+ total = inevent.null()
+- for function in self.functions.itervalues():
++ for function in compat_itervalues(self.functions):
+ total = inevent.aggregate(total, function[inevent])
+ self[inevent] = total
+
+ # Integrate along the edges
+ total = inevent.null()
+- for function in self.functions.itervalues():
++ for function in compat_itervalues(self.functions):
+ total = inevent.aggregate(total, function[inevent])
+ self._integrate_function(function, outevent, inevent)
+ self[outevent] = total
+@@ -360,7 +381,7 @@ class Profile(Object):
+ else:
+ if outevent not in function:
+ total = function[inevent]
+- for call in function.calls.itervalues():
++ for call in compat_itervalues(function.calls):
+ if call.callee_id != function.id:
+ total += self._integrate_call(call, outevent, inevent)
+ function[outevent] = total
+@@ -381,7 +402,7 @@ class Profile(Object):
+ total = inevent.null()
+ for member in cycle.functions:
+ subtotal = member[inevent]
+- for call in member.calls.itervalues():
++ for call in compat_itervalues(member.calls):
+ callee = self.functions[call.callee_id]
+ if callee.cycle is not cycle:
+ subtotal += self._integrate_call(call, outevent, inevent)
+@@ -390,9 +411,9 @@ class Profile(Object):
+
+ # Compute the time propagated to callers of this cycle
+ callees = {}
+- for function in self.functions.itervalues():
++ for function in compat_itervalues(self.functions):
+ if function.cycle is not cycle:
+- for call in function.calls.itervalues():
++ for call in compat_itervalues(function.calls):
+ callee = self.functions[call.callee_id]
+ if callee.cycle is cycle:
+ try:
+@@ -403,7 +424,7 @@ class Profile(Object):
+ for member in cycle.functions:
+ member[outevent] = outevent.null()
+
+- for callee, call_ratio in callees.iteritems():
++ for callee, call_ratio in compat_iteritems(callees):
+ ranks = {}
+ call_ratios = {}
+ partials = {}
+@@ -418,7 +439,7 @@ class Profile(Object):
+ def _rank_cycle_function(self, cycle, function, rank, ranks):
+ if function not in ranks or ranks[function] > rank:
+ ranks[function] = rank
+- for call in function.calls.itervalues():
++ for call in compat_itervalues(function.calls):
+ if call.callee_id != function.id:
+ callee = self.functions[call.callee_id]
+ if callee.cycle is cycle:
+@@ -427,7 +448,7 @@ class Profile(Object):
+ def _call_ratios_cycle(self, cycle, function, ranks, call_ratios, visited):
+ if function not in visited:
+ visited.add(function)
+- for call in function.calls.itervalues():
++ for call in compat_itervalues(function.calls):
+ if call.callee_id != function.id:
+ callee = self.functions[call.callee_id]
+ if callee.cycle is cycle:
+@@ -438,7 +459,7 @@ class Profile(Object):
+ def _integrate_cycle_function(self, cycle, function, partial_ratio, partials, ranks, call_ratios, outevent, inevent):
+ if function not in partials:
+ partial = partial_ratio*function[inevent]
+- for call in function.calls.itervalues():
++ for call in compat_itervalues(function.calls):
+ if call.callee_id != function.id:
+ callee = self.functions[call.callee_id]
+ if callee.cycle is not cycle:
+@@ -465,7 +486,7 @@ class Profile(Object):
+ """Aggregate an event for the whole profile."""
+
+ total = event.null()
+- for function in self.functions.itervalues():
++ for function in compat_itervalues(self.functions):
+ try:
+ total = event.aggregate(total, function[event])
+ except UndefinedEvent:
+@@ -475,11 +496,11 @@ class Profile(Object):
+ def ratio(self, outevent, inevent):
+ assert outevent not in self
+ assert inevent in self
+- for function in self.functions.itervalues():
++ for function in compat_itervalues(self.functions):
+ assert outevent not in function
+ assert inevent in function
+ function[outevent] = ratio(function[inevent], self[inevent])
+- for call in function.calls.itervalues():
++ for call in compat_itervalues(function.calls):
+ assert outevent not in call
+ if inevent in call:
+ call[outevent] = ratio(call[inevent], self[inevent])
+@@ -489,13 +510,13 @@ class Profile(Object):
+ """Prune the profile"""
+
+ # compute the prune ratios
+- for function in self.functions.itervalues():
++ for function in compat_itervalues(self.functions):
+ try:
+ function.weight = function[TOTAL_TIME_RATIO]
+ except UndefinedEvent:
+ pass
+
+- for call in function.calls.itervalues():
++ for call in compat_itervalues(function.calls):
+ callee = self.functions[call.callee_id]
+
+ if TOTAL_TIME_RATIO in call:
+@@ -509,24 +530,24 @@ class Profile(Object):
+ pass
+
+ # prune the nodes
+- for function_id in self.functions.keys():
++ for function_id in compat_keys(self.functions):
+ function = self.functions[function_id]
+ if function.weight is not None:
+ if function.weight < node_thres:
+ del self.functions[function_id]
+
+ # prune the egdes
+- for function in self.functions.itervalues():
+- for callee_id in function.calls.keys():
++ for function in compat_itervalues(self.functions):
++ for callee_id in compat_keys(function.calls):
+ call = function.calls[callee_id]
+ if callee_id not in self.functions or call.weight is not None and call.weight < edge_thres:
+ del function.calls[callee_id]
+
+ def dump(self):
+- for function in self.functions.itervalues():
++ for function in compat_itervalues(self.functions):
+ sys.stderr.write('Function %s:\n' % (function.name,))
+ self._dump_events(function.events)
+- for call in function.calls.itervalues():
++ for call in compat_itervalues(function.calls):
+ callee = self.functions[call.callee_id]
+ sys.stderr.write(' Call %s:\n' % (callee.name,))
+ self._dump_events(call.events)
+@@ -537,7 +558,7 @@ class Profile(Object):
+ sys.stderr.write(' Function %s\n' % (function.name,))
+
+ def _dump_events(self, events):
+- for event, value in events.iteritems():
++ for event, value in compat_iteritems(events):
+ sys.stderr.write(' %s: %s\n' % (event.name, event.format(value)))
+
+
+@@ -695,7 +716,7 @@ class XmlTokenizer:
+ self.final = len(data) < size
+ try:
+ self.parser.Parse(data, self.final)
+- except xml.parsers.expat.ExpatError, e:
++ except xml.parsers.expat.ExpatError as e:
+ #if e.code == xml.parsers.expat.errors.XML_ERROR_NO_ELEMENTS:
+ if e.code == 3:
+ pass
+@@ -801,7 +822,7 @@ class GprofParser(Parser):
+ """Extract a structure from a match object, while translating the types in the process."""
+ attrs = {}
+ groupdict = mo.groupdict()
+- for name, value in groupdict.iteritems():
++ for name, value in compat_iteritems(groupdict):
+ if value is None:
+ value = None
+ elif self._int_re.match(value):
+@@ -977,7 +998,7 @@ class GprofParser(Parser):
+ for index in self.cycles.iterkeys():
+ cycles[index] = Cycle()
+
+- for entry in self.functions.itervalues():
++ for entry in compat_itervalues(self.functions):
+ # populate the function
+ function = Function(entry.index, entry.name)
+ function[TIME] = entry.self
+@@ -1019,7 +1040,7 @@ class GprofParser(Parser):
+
+ profile[TIME] = profile[TIME] + function[TIME]
+
+- for cycle in cycles.itervalues():
++ for cycle in compat_itervalues(cycles):
+ profile.add_cycle(cycle)
+
+ # Compute derived events
+@@ -1350,7 +1371,7 @@ class OprofileParser(LineParser):
+ self.update_subentries_dict(callees_total, callees)
+
+ def update_subentries_dict(self, totals, partials):
+- for partial in partials.itervalues():
++ for partial in compat_itervalues(partials):
+ try:
+ total = totals[partial.id]
+ except KeyError:
+@@ -1372,7 +1393,7 @@ class OprofileParser(LineParser):
+
+ # populate the profile
+ profile[SAMPLES] = 0
+- for _callers, _function, _callees in self.entries.itervalues():
++ for _callers, _function, _callees in compat_itervalues(self.entries):
+ function = Function(_function.id, _function.name)
+ function[SAMPLES] = _function.samples
+ profile.add_function(function)
+@@ -1384,10 +1405,10 @@ class OprofileParser(LineParser):
+ function.module = os.path.basename(_function.image)
+
+ total_callee_samples = 0
+- for _callee in _callees.itervalues():
++ for _callee in compat_itervalues(_callees):
+ total_callee_samples += _callee.samples
+
+- for _callee in _callees.itervalues():
++ for _callee in compat_itervalues(_callees):
+ if not _callee.self:
+ call = Call(_callee.id)
+ call[SAMPLES2] = _callee.samples
+@@ -1548,7 +1569,7 @@ class SysprofParser(XmlParser):
+ profile = Profile()
+
+ profile[SAMPLES] = 0
+- for id, object in objects.iteritems():
++ for id, object in compat_iteritems(objects):
+ # Ignore fake objects (process names, modules, "Everything", "kernel", etc.)
+ if object['self'] == 0:
+ continue
+@@ -1558,7 +1579,7 @@ class SysprofParser(XmlParser):
+ profile.add_function(function)
+ profile[SAMPLES] += function[SAMPLES]
+
+- for id, node in nodes.iteritems():
++ for id, node in compat_iteritems(nodes):
+ # Ignore fake calls
+ if node['self'] == 0:
+ continue
+@@ -1672,7 +1693,7 @@ class SharkParser(LineParser):
+
+ profile = Profile()
+ profile[SAMPLES] = 0
+- for _function, _callees in self.entries.itervalues():
++ for _function, _callees in compat_itervalues(self.entries):
+ function = Function(_function.id, _function.name)
+ function[SAMPLES] = _function.samples
+ profile.add_function(function)
+@@ -1681,7 +1702,7 @@ class SharkParser(LineParser):
+ if _function.image:
+ function.module = os.path.basename(_function.image)
+
+- for _callee in _callees.itervalues():
++ for _callee in compat_itervalues(_callees):
+ call = Call(_callee.id)
+ call[SAMPLES] = _callee.samples
+ function.add_call(call)
+@@ -1965,7 +1986,8 @@ class PstatsParser:
+ self.profile = Profile()
+ self.function_ids = {}
+
+- def get_function_name(self, (filename, line, name)):
++ def get_function_name(self, info):
++ filename, line, name = info
+ module = os.path.splitext(filename)[0]
+ module = os.path.basename(module)
+ return "%s:%d:%s" % (module, line, name)
+@@ -1986,14 +2008,14 @@ class PstatsParser:
+ def parse(self):
+ self.profile[TIME] = 0.0
+ self.profile[TOTAL_TIME] = self.stats.total_tt
+- for fn, (cc, nc, tt, ct, callers) in self.stats.stats.iteritems():
++ for fn, (cc, nc, tt, ct, callers) in compat_iteritems(self.stats.stats):
+ callee = self.get_function(fn)
+ callee.called = nc
+ callee[TOTAL_TIME] = ct
+ callee[TIME] = tt
+ self.profile[TIME] += tt
+ self.profile[TOTAL_TIME] = max(self.profile[TOTAL_TIME], ct)
+- for fn, value in callers.iteritems():
++ for fn, value in compat_iteritems(callers):
+ caller = self.get_function(fn)
+ call = Call(callee.id)
+ if isinstance(value, tuple):
+@@ -2190,7 +2212,7 @@ class DotWriter:
+ self.attr('node', fontname=fontname, shape="box", style="filled", fontcolor="white", width=0, height=0)
+ self.attr('edge', fontname=fontname)
+
+- for function in profile.functions.itervalues():
++ for function in compat_itervalues(profile.functions):
+ labels = []
+ if function.process is not None:
+ labels.append(function.process)
+@@ -2202,7 +2224,7 @@ class DotWriter:
+ label = event.format(function[event])
+ labels.append(label)
+ if function.called is not None:
+- labels.append(u"%u\xd7" % (function.called,))
++ labels.append(CALL_TIMES_FORMAT % (function.called,))
+
+ if function.weight is not None:
+ weight = function.weight
+@@ -2217,7 +2239,7 @@ class DotWriter:
+ fontsize = "%.2f" % theme.node_fontsize(weight),
+ )
+
+- for call in function.calls.itervalues():
++ for call in compat_itervalues(function.calls):
+ callee = profile.functions[call.callee_id]
+
+ labels = []
+@@ -2278,7 +2300,7 @@ class DotWriter:
+ return
+ self.write(' [')
+ first = True
+- for name, value in attrs.iteritems():
++ for name, value in compat_iteritems(attrs):
+ if first:
+ first = False
+ else:
+@@ -2291,7 +2313,7 @@ class DotWriter:
+ def id(self, id):
+ if isinstance(id, (int, float)):
+ s = str(id)
+- elif isinstance(id, basestring):
++ elif isinstance(id, compat_basestring):
+ if id.isalnum() and not id.startswith('0x'):
+ s = id
+ else:
+@@ -2300,7 +2322,8 @@ class DotWriter:
+ raise TypeError
+ self.write(s)
+
+- def color(self, (r, g, b)):
++ def color(self, rgb):
++ r, g, b = rgb
+
+ def float2int(f):
+ if f <= 0.0:
+@@ -2312,7 +2335,8 @@ class DotWriter:
+ return "#" + "".join(["%02x" % float2int(c) for c in (r, g, b)])
+
+ def escape(self, s):
+- s = s.encode('utf-8')
++ if not PYTHON_3:
++ s = s.encode('utf-8')
+ s = s.replace('\\', r'\\')
+ s = s.replace('\n', r'\n')
+ s = s.replace('\t', r'\t')
+@@ -2505,7 +2529,7 @@ class Main:
+ profile = self.profile
+ profile.prune(self.options.node_thres/100.0, self.options.edge_thres/100.0)
+
+- for function in profile.functions.itervalues():
++ for function in compat_itervalues(profile.functions):
+ function.name = self.compress_function_name(function.name)
+
+ dot.graph(profile, self.theme)
+--
+1.7.3.2
+
diff --git a/dev-util/gprof2dot/files/gprof2dot-0_p20130517-py3-xrange.patch b/dev-util/gprof2dot/files/gprof2dot-0_p20130517-py3-xrange.patch
new file mode 100644
index 000000000000..228b1d8230d7
--- /dev/null
+++ b/dev-util/gprof2dot/files/gprof2dot-0_p20130517-py3-xrange.patch
@@ -0,0 +1,10 @@
+--- gprof2dot.py 2013-05-29 19:18:46.217823810 +0300
++++ gprof2dot.py 2013-06-16 12:12:28.095478734 +0300
+@@ -39,6 +39,7 @@
+ def compat_keys(x): return list(x.keys()) # keys() is a generator in Python 3
+ basestring = str # No class basestring in Python 3
+ unichr = chr # No unichr in Python 3
++ xrange = range # No xrange in Python 3
+ else:
+ PYTHON_3 = False
+ def compat_iteritems(x): return x.iteritems()
diff --git a/dev-util/gprof2dot/gprof2dot-0_p20130517.ebuild b/dev-util/gprof2dot/gprof2dot-0_p20130517.ebuild
new file mode 100644
index 000000000000..ec4cff4d96dc
--- /dev/null
+++ b/dev-util/gprof2dot/gprof2dot-0_p20130517.ebuild
@@ -0,0 +1,51 @@
+# Copyright 1999-2014 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+EAPI="5"
+
+PYTHON_COMPAT=( python{2_7,3_3,3_4} )
+PYTHON_REQ_USE='xml'
+
+inherit eutils python-r1
+
+DESCRIPTION="Converts profiling output to dot graphs"
+HOMEPAGE="http://code.google.com/p/jrfonseca/wiki/Gprof2Dot"
+SRC_URI="http://www.hartwork.org/public/${P}.tar.xz"
+
+LICENSE="GPL-3"
+SLOT="0"
+KEYWORDS="~amd64 ~x86"
+IUSE=""
+
+DEPEND=""
+RDEPEND=""
+
+REQUIRED_USE="${PYTHON_REQUIRED_USE}"
+
+src_prepare() {
+ epatch "${FILESDIR}"/${P}-py3-xrange.patch
+}
+
+_make_call_script() {
+ cat <<-EOF >"${D}/$1"
+ #! /usr/bin/env python
+ from gprof2dot import Main
+ Main().main()
+ EOF
+
+ fperms a+x "$1" || die
+}
+
+src_install() {
+ abi_specific_install() {
+ insinto "$(python_get_sitedir)"
+ doins ${PN}.py || die
+ python_optimize || die
+ }
+ python_parallel_foreach_impl abi_specific_install
+
+ dodir /usr/bin || die
+ _make_call_script /usr/bin/${PN} || die
+ python_replicate_script "${D}"/usr/bin/${PN} || die
+}
diff --git a/dev-util/gprof2dot/metadata.xml b/dev-util/gprof2dot/metadata.xml
new file mode 100644
index 000000000000..16bcc9f800a2
--- /dev/null
+++ b/dev-util/gprof2dot/metadata.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<pkgmetadata>
+ <maintainer>
+ <email>sping@gentoo.org</email>
+ <name>Sebastian Pipping</name>
+ </maintainer>
+</pkgmetadata>