X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;ds=sidebyside;f=scripts%2Fauxiliar%2Fshow_skyline_command.py;fp=scripts%2Fauxiliar%2Fshow_skyline_command.py;h=6fc63143c988eaea59e19862d95c3219e3a2a7a4;hb=0ac07f31e0f95fc18e5916ce756b9c746af7cc58;hp=0000000000000000000000000000000000000000;hpb=2f1263e2ccdddcac2eb9f7d8ce2ed92867d3d160;p=lilypond.git diff --git a/scripts/auxiliar/show_skyline_command.py b/scripts/auxiliar/show_skyline_command.py new file mode 100644 index 0000000000..6fc63143c9 --- /dev/null +++ b/scripts/auxiliar/show_skyline_command.py @@ -0,0 +1,156 @@ +# This file is part of LilyPond, the GNU music typesetter. +# +# Copyright (C) 2012 Joe Neeman +# +# LilyPond 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. +# +# LilyPond 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 LilyPond. If not, see . + +# A gdb plugin debugging skylines. To use the plugin, make sure that +# skyline_viewer.py is in your PATH, then add +# source /path/to/show_skyline_command.py +# to your .gdbinit file. The 'vsky' and 'hsky' commands for +# drawing skylines will then be available in gdb. + +import gdb +from subprocess import Popen, PIPE +from math import isinf + +SKYLINE_VIEWER = 'skyline_viewer.py' + +# Function taken from GCC +def find_type(orig, name): + typ = orig.strip_typedefs() + while True: + search = str(typ) + '::' + name + try: + return gdb.lookup_type(search) + except RuntimeError: + pass + # The type was not found, so try the superclass. We only need + # to check the first superclass, so we don't bother with + # anything fancier here. + field = typ.fields()[0] + if not field.is_base_class: + raise ValueError, "Cannot find type %s::%s" % (str(orig), name) + typ = field.type + +# Class adapted from GCC +class ListIterator: + def __init__ (self, val): + self.val = val + self.nodetype = find_type (val.type, '_Node') + self.nodetype = self.nodetype.strip_typedefs ().pointer () + + head = val['_M_impl']['_M_node'] + self.base = head['_M_next'] + self.head = head.address + + def __iter__ (self): + return self + + def next (self): + if self.base == self.head: + raise StopIteration + elt = self.base.cast (self.nodetype).dereference () + self.base = elt['_M_next'] + return elt['_M_data'] + +def to_list (list_val): + return list (ListIterator (list_val)) + +def skyline_to_lines (sky_value): + """Turns a gdb.Value into a list of line segments.""" + sky_d = int (sky_value['sky_']) + buildings = to_list (sky_value['buildings_']) + + def bld_to_line (bld): + y_intercept = float (bld['y_intercept_']) * sky_d + slope = float (bld['slope_']) * sky_d + x1 = float (bld['start_']) + x2 = float (bld['end_']) + + if isinf (y_intercept) or isinf (x1) or isinf (x2): + return None + return (x1, y_intercept + slope * x1, x2, y_intercept + slope * x2) + + ret = map (bld_to_line, buildings) + return [r for r in ret if r is not None] + +viewer = Popen(SKYLINE_VIEWER, stdin=PIPE) +def add_skyline(lines): + global viewer + try: + for line in lines: + x1, y1, x2, y2 = line + viewer.stdin.write('(%f,%f) (%f,%f)\n' % (x1, y1, x2, y2)) + viewer.stdin.write('\n') + except IOError: + # If the pipe is broken, it probably means that someone closed + # the viewer window. Open another one. + viewer = Popen(SKYLINE_VIEWER, stdin=PIPE) + add_skyline(lines) + +class ShowSkylineCommand (gdb.Command): + "Show a skyline graphically." + + def __init__ (self, command_name): + super (ShowSkylineCommand, self).__init__ (command_name, + gdb.COMMAND_DATA, + gdb.COMPLETE_SYMBOL, False) + + def to_lines (self, skyline): + pass + + def invoke (self, arg, from_tty): + global plot + + val = gdb.parse_and_eval (arg) + typ = val.type + + # If they passed in a reference or pointer to a skyline, + # dereference it. + if typ.code == gdb.TYPE_CODE_PTR or typ.code == gdb.TYPE_CODE_REF: + val = val.referenced_value () + typ = val.type + + if typ.tag == 'Skyline_pair': + sky = val['skylines_'] + arr = sky['array_'] + add_skyline (self.to_lines (arr[0])) + add_skyline (self.to_lines (arr[1])) + + elif typ.tag == 'Skyline': + add_skyline (self.to_lines (val)) + +class ShowVSkylineCommand (ShowSkylineCommand): + "Show a vertical skyline." + + def __init__ (self): + super (ShowVSkylineCommand, self).__init__ ("vsky") + + def to_lines (self, skyline): + return skyline_to_lines (skyline) + +class ShowHSkylineCommand (ShowSkylineCommand): + "Show a horizontal skyline." + + def __init__ (self): + super (ShowHSkylineCommand, self).__init__ ("hsky") + + def to_lines (self, skyline): + lines = skyline_to_lines (skyline) + # Because it is a horizontal skyline, reflect around the line y=x. + return [(y1, x1, y2, x2) for (x1, y1, x2, y2) in lines] + +ShowHSkylineCommand() +ShowVSkylineCommand()