# Gdb pretty printer for zsh wordcode values. # python execfile("wordcode.py") # set print array on # print *ecbuf@22 # note that you'll get garbage values for codes that reference strings from operator import itemgetter class WordcodePrinter: WC_END = 0 WC_LIST = 1 WC_SUBLIST = 2 WC_PIPE = 3 WC_REDIR = 4 WC_ASSIGN = 5 WC_SIMPLE = 6 WC_TYPESET = 7 WC_SUBSH = 8 WC_CURSH = 9 WC_TIMED = 10 WC_FUNCDEF = 11 WC_FOR = 12 WC_SELECT = 13 WC_WHILE = 14 WC_REPEAT = 15 WC_CASE = 16 WC_IF = 17 WC_COND = 18 WC_ARITH = 19 WC_AUTOFN = 20 WC_TRY = 21 WC_CODEBITS = 5 Z_END = (1<<4) Z_SIMPLE = (1<<5) WC_LIST_FREE = (6) NAME = [ "End", "List", "SubList", "Pipe", "Redir", "Assign", "Simple", "Typeset", "Subsh", "Cursh", "Timed", "Funcdef", "For", "Select", "While", "Repeat", "Case", "If", "Cond", "Arith", "Autofn", "Try" ] def __init__(self, val): self.val = val def wc_code(self, code): return int(code) & ((1 << self.WC_CODEBITS) - 1) def wc_data(self, code): return int(code) >> self.WC_CODEBITS def wc_list_type(self, data): return '|'.join(map(itemgetter(1), filter(lambda (i,s): data & (1<", ">|", ">>", ">>|", "&>", ">&|", ">>&", ">>&|", "<>", "<", "<<", "<<-", "<<<", "<&n", ">&n", ">&-, <&-", "< <(...)", "> >(...)" ][data & 0x1f] def wc_sublist_flags(self, data): return '|'.join(map(itemgetter(1), filter(lambda (i,s): data & (1<", "-nt", "-ot", "-ef", "-eq", "-ne", "-lt", "-gt", "-le", "-ge", "=~", "MOD", "MOD(infix)" ][data & 127] def to_string(self): try: code = self.wc_code(self.val) data = self.wc_data(self.val) name = self.NAME[code] if (code == self.WC_LIST): name += '(type={}, skip={})'.format(self.wc_list_type(data), data >> 6) elif (code == self.WC_SUBLIST and data & 0x1c): name += '(type={}, flags={}, skip={})'.format( self.wc_sublist_type(data), self.wc_sublist_flags(data), data >> 5) elif (code == self.WC_SUBLIST): name += '(type={}, skip={})'.format(self.wc_sublist_type(data), data >> 5) elif (code == self.WC_REDIR): name += '(type={}{})'.format(self.wc_redir_type(data), ", varid=true" if (data & 0x20) else "") elif (code == self.WC_ASSIGN): if data & 2: name += "+=" name += "(array[{}])".format(data >> 2) if data & 1 else "(scalar)" elif (code == self.WC_SUBSH or code == self.WC_CURSH or code == self.WC_REPEAT or code == self.WC_TRY or code == self.WC_FUNCDEF): name += '(skip={})'.format(data) elif (code == self.WC_TIMED): name += '(type={})'.format("pipe" if data else "empty") elif (code == self.WC_PIPE): name += '(type={}, line={})'.format( "mid" if (data & 1) else "end", (data >> 1)) elif (code == self.WC_FOR): name += '(type={}, skip={})'.format(self.wc_for_type(data), data >> 2) elif (code == self.WC_SELECT): name += '(type={}, skip={})'.format( "pparam" if (data & 1) else "list", (data >> 1)) elif (code == self.WC_WHILE): if data & 1: name += '/until' name += '(skip={})'.format(data >> 1) elif (code == self.WC_CASE): name += '(type={}, skip={})'.format(self.wc_case_type(data), data >> 3) elif (code == self.WC_SIMPLE or code == self.WC_TYPESET): name += '(argc={})'.format(data) elif (code == self.WC_IF): name += '(type={}, skip={})'.format(self.wc_if_type(data), data >> 2) elif (code == self.WC_COND): name += '({}, skip={})'.format(self.wc_cond_type(data), data >> 7) except IndexError: name = int(code) # any error likely means it isn't a wordcode return name def zsh(val): if str(val.type) == 'wordcode': return WordcodePrinter(val) return None gdb.pretty_printers.append(zsh)