#include #include #include #include "ruamoko/qwaq/debugger/views/defview.h" #include "ruamoko/qwaq/debugger/views/nameview.h" #include "ruamoko/qwaq/debugger/localsdata.h" #include "ruamoko/qwaq/ui/listener.h" @implementation LocalsData -initWithTarget:(qdb_target_t) target { if (!(self = [super init])) { return nil; } self.target = target; qdb_def_t encodings_def = qdb_find_global (target, ".type_encodings"); qdb_get_data (target, encodings_def.offset, sizeof(target_encodings), &target_encodings); self.has_stack = qdb_has_data_stack (target); self.onRowCountChanged = [[ListenerGroup listener] retain]; return self; } +(LocalsData *)withTarget:(qdb_target_t)target { return [[[self alloc] initWithTarget:target] autorelease]; } static void free_defs (LocalsData *self) { obj_free (self.defs); self.defs = nil; for (int i = 0; i < self.num_user_defs; i++) { [self.def_views[i] release]; } obj_free (self.def_views); self.def_views = nil; obj_free (self.def_rows); self.def_rows = nil; } -(void)dealloc { [onRowCountChanged release]; if (defs) { free_defs (self); } if (data) { obj_free (data); data = nil; } [super dealloc]; } -setFunction:(unsigned) fnum { if (current_fnum == fnum) { return self; } current_fnum = fnum; if (defs) { free_defs (self); } if (data) { obj_free (data); data = nil; } func = qdb_get_function (target, fnum); if (func && func.local_size) { data = obj_malloc (func.local_size); } aux_func = qdb_get_auxfunction (target, fnum); num_user_defs = 0; if (aux_func) { defs = qdb_get_local_defs (target, fnum); for (int i = 0; i < aux_func.num_locals; i++) { string def_name = qdb_get_string (target, defs[i].name); if (str_mid (def_name, 0, 1) != ".") { num_user_defs++; } } def_views = obj_malloc (num_user_defs); def_rows = obj_malloc (num_user_defs + 1); def_rows[0] = 0; for (int i = 0, j = 0; i < aux_func.num_locals; i++) { string def_name = qdb_get_string (target, defs[i].name); if (str_mid (def_name, 0, 1) == ".") { continue; } def_views[j] = [[DefView withDef:defs[i] in:data target:target] retain]; def_rows[j + 1] = [def_views[j] rows]; j++; } prefixsum (def_rows, num_user_defs + 1); } [onRowCountChanged respond:self]; return self; } -fetchData { if (data && func.local_size) { unsigned local_data = func.local_data; if (has_stack) { unsigned stack_ptr = qdb_get_frame_addr (target); local_data = 0; if (stack_ptr) { local_data = stack_ptr - func.local_data; } } if (local_data) { qdb_get_data (target, local_data, func.local_size, data); } } int rowCount = def_rows[num_user_defs]; if (aux_func) { def_rows[0] = 0; for (int i = 0; i < num_user_defs; i++) { [def_views[i] fetchData]; def_rows[i + 1] = [def_views[i] rows]; } prefixsum (def_rows, num_user_defs + 1); } if (rowCount != def_rows[num_user_defs]) { [onRowCountChanged respond:self]; } return self; } -(ListenerGroup *)onRowCountChanged { return onRowCountChanged; } -(int)numberOfRows:(TableView *)tableview { if (aux_func) { if (!num_user_defs) { return 0; } return def_rows[num_user_defs]; } else if (func) { return (func.local_size + 3) / 4; } return 0; } -(View *)tableView:(TableView *)tableview forColumn:(TableViewColumn *)column row:(int)row { View *view = nil; int *index = fbsearch (&row, def_rows, num_user_defs, 1, nil); if (index) { DefView *dv = def_views[index - def_rows]; int r = row - *index; view = [dv viewAtRow: r forColumn:column]; } return view; } @end