From mboxrd@z Thu Jan 1 00:00:00 1970 From: Keith Seitz To: Insight Maling List Subject: [PATCH] gdbtk-register.c consolidation Date: Mon, 13 Aug 2001 11:41:00 -0000 Message-id: X-SW-Source: 2001-q3/msg00118.html Oops. Wrong title. Where's my Diet Coke (tm)? Keith ---------- Forwarded message ---------- Date: Mon, 13 Aug 2001 11:39:30 -0700 (PDT) From: Keith Seitz To: Insight Maling List Subject: [PATCH] gdbtk-bp.c consolidation Hi, On a whim, I've cleaned this file up a little. There are two big changes: 1) Consolidate all the register functions under one tcl command, "gdb_reginfo". 2) Add one new "gdb_reginfo" subcommand: "size", which tells us the raw size of the register. Note that this patch will break the register window, so you will need to not update until I check in my "new" register window (which should happen within the hour). If there are any problems, please let me know. Keith ChangeLog 2001-08-13 Keith Seitz * generic/gdbtk-register.c (gdb_register_info): New function. Consolidates all register handling. (get_register_size): New function. (gdb_changed_register_list, gdb_fetch_registers, gdb_regnames): Deprecate. (setup_architecture_data): Free old register cache when necessary. Patch Index: generic/gdbtk-register.c =================================================================== RCS file: /cvs/src/src/gdb/gdbtk/generic/gdbtk-register.c,v retrieving revision 1.3 diff -u -p -r1.3 gdbtk-register.c --- gdbtk-register.c 2001/07/31 17:34:56 1.3 +++ gdbtk-register.c 2001/08/13 18:34:49 @@ -30,16 +30,13 @@ /* This contains the previous values of the registers, since the last call to gdb_changed_register_list. */ -static char *old_regs; +static char *old_regs = NULL; -static int gdb_changed_register_list (ClientData, Tcl_Interp *, int, - Tcl_Obj * CONST[]); -static int gdb_fetch_registers (ClientData, Tcl_Interp *, int, - Tcl_Obj * CONST[]); -static int gdb_regnames (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]); static int get_pc_register (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]); +static int gdb_register_info (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]); static void get_register (int, void *); static void get_register_name (int, void *); +static void get_register_size (int regnum, void *arg); static int map_arg_registers (int, Tcl_Obj * CONST[], void (*)(int, void *), void *); static void register_changed_p (int, void *); @@ -48,12 +45,8 @@ static void setup_architecture_data (voi int Gdbtk_Register_Init (Tcl_Interp *interp) { - Tcl_CreateObjCommand (interp, "gdb_changed_register_list", gdbtk_call_wrapper, - gdb_changed_register_list, NULL); - Tcl_CreateObjCommand (interp, "gdb_fetch_registers", gdbtk_call_wrapper, - gdb_fetch_registers, NULL); - Tcl_CreateObjCommand (interp, "gdb_regnames", gdbtk_call_wrapper, gdb_regnames, - NULL); + Tcl_CreateObjCommand (interp, "gdb_reginfo", gdbtk_call_wrapper, + gdb_register_info, NULL); Tcl_CreateObjCommand (interp, "gdb_pc_reg", gdbtk_call_wrapper, get_pc_register, NULL); @@ -65,110 +58,127 @@ Gdbtk_Register_Init (Tcl_Interp *interp) return TCL_OK; } -/* This implements the tcl command "gdb_changed_register_list" - * It takes a list of registers, and returns a list of - * the registers on that list that have changed since the last - * time the proc was called. +/* This implements the tcl command "gdb_reginfo". + * It returns the requested information about registers. * * Tcl Arguments: - * A list of registers. - * Tcl Result: - * A list of changed registers. - */ -static int -gdb_changed_register_list (clientData, interp, objc, objv) - ClientData clientData; - Tcl_Interp *interp; - int objc; - Tcl_Obj *CONST objv[]; -{ - objc--; - objv++; - - return map_arg_registers (objc, objv, register_changed_p, NULL); -} - -/* This implements the tcl command gdb_fetch_registers - * Pass it a list of register names, and it will - * return their values as a list. + * OPTION - "changed", "name", "size", "value" (see below) + * REGNUM(S) - the register(s) for which info is requested * - * Tcl Arguments: - * format: The format string for printing the values - * args: the registers to look for * Tcl Result: - * A list of their values. + * The requested information + * + * Options: + * changed + * Returns a list of registers whose values have changed since the + * last time the proc was called. + * + * usage: gdb_reginfo changed [regnum0, ..., regnumN] + * + * name + * Return a list containing the names of the registers whose numbers + * are given by REGNUM ... . If no register numbers are given, return + * all the registers' names. + * + * usage: gdb_reginfo name [-numbers] [regnum0, ..., regnumN] + * + * Note that some processors have gaps in the register numberings: + * even if there is no register numbered N, there may still be a + * register numbered N+1. So if you call gdb_regnames with no + * arguments, you can't assume that the N'th element of the result is + * register number N. + * + * Given the -numbers option, gdb_regnames returns, not a list of names, + * but a list of pairs {NAME NUMBER}, where NAME is the register name, + * and NUMBER is its number. + * + * size + * Returns the raw size of the register(s) in bytes. + * + * usage: gdb_reginfo size [regnum0, ..., regnumN] + * + * value + * Returns a list of register values. + * + * usage: gdb_reginfo value format [regnum0, ..., regnumN] + * format: The format string for printing the values, "N", "x", "d", etc */ static int -gdb_fetch_registers (clientData, interp, objc, objv) - ClientData clientData; - Tcl_Interp *interp; - int objc; - Tcl_Obj *CONST objv[]; +gdb_register_info (ClientData clientData, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[]) { - int format, result; + int regnum, index, result; + void *argp; + void (*func)(int, void *); + static char *commands[] = {"changed", "name", "size", "value", NULL}; + enum commands_enum { REGINFO_CHANGED, REGINFO_NAME, REGINFO_SIZE, REGINFO_VALUE }; if (objc < 2) { - Tcl_WrongNumArgs (interp, 1, objv, "format ?register1 register2 ...?"); + Tcl_WrongNumArgs (interp, 1, objv, "name|size|value [regnum1 ... regnumN]"); return TCL_ERROR; } - objc -= 2; - objv++; - format = *(Tcl_GetStringFromObj (objv[0], NULL)); - objv++; - - if (objc != 1) - result_ptr->flags |= GDBTK_MAKES_LIST; /* Output the results as a list */ - result = map_arg_registers (objc, objv, get_register, (void *) format); - if (objc != 1) - result_ptr->flags &= ~GDBTK_MAKES_LIST; - return result; -} + if (Tcl_GetIndexFromObj (interp, objv[1], commands, "options", 0, + &index) != TCL_OK) + { + return TCL_ERROR; + } -/* This implements the TCL command `gdb_regnames'. Its syntax is: + /* Skip the option */ + objc -= 2; + objv += 2; - gdb_regnames [-numbers] [REGNUM ...] + switch ((enum commands_enum) index) + { + case REGINFO_CHANGED: + func = register_changed_p; + argp = NULL; + break; - Return a list containing the names of the registers whose numbers - are given by REGNUM ... . If no register numbers are given, return - all the registers' names. - - Note that some processors have gaps in the register numberings: - even if there is no register numbered N, there may still be a - register numbered N+1. So if you call gdb_regnames with no - arguments, you can't assume that the N'th element of the result is - register number N. - - Given the -numbers option, gdb_regnames returns, not a list of names, - but a list of pairs {NAME NUMBER}, where NAME is the register name, - and NUMBER is its number. */ -static int -gdb_regnames (clientData, interp, objc, objv) - ClientData clientData; - Tcl_Interp *interp; - int objc; - Tcl_Obj *CONST objv[]; -{ - int numbers = 0; + case REGINFO_NAME: + { + int len; + char *s = Tcl_GetStringFromObj (objv[0], &len); + if (objc != 0 && strncmp (s, "-numbers", len) == 0) + { + argp = (void *) 1; + objc--; + objv++; + } + else + argp = NULL; - objc--; - objv++; + func = get_register_name; + } + break; - if (objc >= 1) - { - char *s = Tcl_GetStringFromObj (objv[0], NULL); - if (STREQ (s, "-numbers")) - { - numbers = 1; - objc--; - objv++; - } + case REGINFO_SIZE: + func = get_register_size; + argp = NULL; + break; + + case REGINFO_VALUE: + func = get_register; + argp = (void *) (int) *(Tcl_GetStringFromObj (objv[0], NULL)); + objc--; + objv++; + break; + + default: + return TCL_ERROR; } - return map_arg_registers (objc, objv, get_register_name, &numbers); + return map_arg_registers (objc, objv, func, argp); } +static void +get_register_size (int regnum, void *arg) +{ + Tcl_ListObjAppendElement (gdbtk_interp, result_ptr->obj_ptr, + Tcl_NewIntObj (REGISTER_RAW_SIZE (regnum))); +} + /* This implements the tcl command get_pc_reg * It returns the value of the PC register * @@ -186,7 +196,7 @@ get_pc_register (clientData, interp, obj { char *buff; - xasprintf (&buff, "0x%llx", (long long) read_register (PC_REGNUM)); + xasprintf (&buff, "0x%s", paddr_nz (read_register (PC_REGNUM))); Tcl_SetStringObj (result_ptr->obj_ptr, buff, -1); free(buff); return TCL_OK; @@ -265,7 +275,7 @@ get_register_name (regnum, argp) void *argp; { /* Non-zero if the caller wants the register numbers, too. */ - int numbers = * (int *) argp; + int numbers = (int) argp; Tcl_Obj *name = Tcl_NewStringObj (REGISTER_NAME (regnum), -1); Tcl_Obj *elt; @@ -303,7 +313,10 @@ map_arg_registers (objc, objv, func, arg the particular processor being debugged. */ numregs = NUM_REGS + NUM_PSEUDO_REGS; - + + if (objc == 0 || objc > 1) + result_ptr->flags |= GDBTK_MAKES_LIST; + if (objc == 0) /* No args, just do all the regs */ { for (regnum = 0; @@ -370,6 +383,9 @@ static void setup_architecture_data () { /* don't trust REGISTER_BYTES to be zero. */ + if (old_regs != NULL) + xfree (old_regs); + old_regs = xmalloc (REGISTER_BYTES + 1); memset (old_regs, 0, REGISTER_BYTES + 1); }