import re import subprocess NORMAL_COLOR = '\033[0m' REG_STATUS_TO_COLOR = { "insert": '\033[32m', "change": '\033[33m', "remove": '\033[31m', "none": '\033[0m', "jump": '\033[36m' } class AsciiPainter: def __init__ (self, registers=None, max_stack_size=8, stack_draw_mode="up"): self.registers = registers if registers else REGISTERS self.states = [] self.max_stack_size = max_stack_size self.stack_draw_mode = stack_draw_mode def saveState (self, emu, line_nr=None): # Init state state = [] self.states.append(state) # Write opcode to state if line_nr != None: signature = emu.getLineSignature(line_nr) for token in signature: state.append({ 'state': 'none', 'val': token }) # for i in range(3-len(state)): state.append({'state':'none', 'val': ''}) for i in range(len(state)-3): state.pop() state.append({'state':'none', 'val':''}) # Write registers to state for reg_name in self.registers: if reg_name =="": state.append({'state':'none', 'val':''}) continue reg_state = emu.regState(reg_name) state.append({ 'state': reg_state, 'val': emu.getVal(reg_name) }) # Write stack to state stack_base_pointer = emu.getVal('%rbp') print(emu.last_sp, emu.getVal('%rsp')) base_sp = emu.getVal('%rsp') assert(isinstance(emu.getVal('%rsp'), (int, long))) state.append({'state':'none', 'val': ''}) if emu.regState('m'+str(base_sp-1)) == 'remove': state.append({'state': emu.regState('m'+str(base_sp-1)), 'val': emu.stack[base_sp-1]}) else: state.append({'state': 'none', 'val': ''}) for index in range(0, self.max_stack_size): stack_i = base_sp + index print(index, stack_i) if stack_i < emu.max_stack_size: state.append({ 'state': emu.regState("m"+str(stack_i)), 'val': emu.stack[stack_i] }) if stack_base_pointer == index: stack_base_pointer = emu.stack[base_pointer] # TODO: Draw stack frame seperators else: state.append({'state':'none', 'val': ''}) def to_string (self, emu): number_states = len(self.states) number_state_vars = len(self.states[0]) term_width = int(subprocess.check_output(['tput', 'cols'])) number_states_pr_block = term_width / (10+2) - 1 separator = '-' * term_width l = [] for base_state in range(0, number_states, number_states_pr_block): l.append(separator) for var_i in range(0, number_state_vars): l.append('{:10}'.format(self.nameOfVar(var_i-4))) for state_i in range(0, min(number_states_pr_block, number_states - base_state)): var = self.states[base_state+state_i][var_i] l.append('{}{:>10}{} '.format(REG_STATUS_TO_COLOR[var['state']], var['val'], NORMAL_COLOR)) l.append('\n') l.append(separator) return ''.join(l) def nameOfVar (self, i): if i < 0: return '' if i < len(self.registers): return self.registers[i] elif i != len(self.registers): state_i = i-len(self.registers) - 2 return 'TOS{}{}'.format('+' if state_i < 0 else '-', abs(state_i)) else: return '' def __str__ (self): return 'TikzPainter[]'