|
|
1.1 ! root 1: /* Print values for GNU debugger GDB. ! 2: Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc. ! 3: ! 4: GDB is distributed in the hope that it will be useful, but WITHOUT ANY ! 5: WARRANTY. No author or distributor accepts responsibility to anyone ! 6: for the consequences of using it or for whether it serves any ! 7: particular purpose or works at all, unless he says so in writing. ! 8: Refer to the GDB General Public License for full details. ! 9: ! 10: Everyone is granted permission to copy, modify and redistribute GDB, ! 11: but only under the conditions described in the GDB General Public ! 12: License. A copy of this license is supposed to have been given to you ! 13: along with GDB so you can know your rights and responsibilities. It ! 14: should be in a file named COPYING. Among other things, the copyright ! 15: notice and this notice must be preserved on all copies. ! 16: ! 17: In other words, go ahead and share GDB, but don't try to stop ! 18: anyone else from sharing it farther. Help stamp out software hoarding! ! 19: */ ! 20: ! 21: #include <stdio.h> ! 22: #include "defs.h" ! 23: #include "initialize.h" ! 24: #include "param.h" ! 25: #include "symtab.h" ! 26: #include "value.h" ! 27: #include "expression.h" ! 28: ! 29: struct format_data ! 30: { ! 31: int count; ! 32: char format; ! 33: char size; ! 34: }; ! 35: ! 36: /* Last specified output format. */ ! 37: ! 38: static char last_format = 'x'; ! 39: ! 40: /* Last specified examination size. 'b', 'h', 'w' or `q'. */ ! 41: ! 42: static char last_size = 'w'; ! 43: ! 44: /* Default address to examine next. */ ! 45: ! 46: static CORE_ADDR next_address; ! 47: ! 48: /* Last address examined. */ ! 49: ! 50: static CORE_ADDR last_examine_address; ! 51: ! 52: /* Contents of last address examined. ! 53: This is not valid past the end of the `x' command! */ ! 54: ! 55: static value last_examine_value; ! 56: ! 57: /* Number of auto-display expression currently being displayed. ! 58: So that we can deleted it if we get an error or a signal within it. ! 59: -1 when not doing one. */ ! 60: ! 61: int current_display_number; ! 62: ! 63: static void do_one_display (); ! 64: ! 65: void do_displays (); ! 66: void print_address (); ! 67: void print_scalar_formatted (); ! 68: ! 69: START_FILE ! 70: ! 71: /* Decode a format specification. *STRING_PTR should point to it. ! 72: OFORMAT and OSIZE are used as defaults for the format and size ! 73: if none are given in the format specification. ! 74: The structure returned describes all the data ! 75: found in the specification. In addition, *STRING_PTR is advanced ! 76: past the specification and past all whitespace following it. */ ! 77: ! 78: struct format_data ! 79: decode_format (string_ptr, oformat, osize) ! 80: char **string_ptr; ! 81: char oformat; ! 82: char osize; ! 83: { ! 84: struct format_data val; ! 85: register char *p = *string_ptr; ! 86: ! 87: val.format = oformat; ! 88: val.size = osize; ! 89: val.count = 1; ! 90: ! 91: if (*p >= '0' && *p <= '9') ! 92: val.count = atoi (p); ! 93: while (*p >= '0' && *p <= '9') p++; ! 94: ! 95: /* Now process size or format letters that follow. */ ! 96: ! 97: while (1) ! 98: { ! 99: if (*p == 'b' || *p == 'h' || *p == 'w' || *p == 'g') ! 100: val.size = *p++; ! 101: else if (*p >= 'a' && *p <= 'z') ! 102: val.format = *p++; ! 103: else ! 104: break; ! 105: } ! 106: ! 107: /* Make sure 'g' size is not used on integer types. */ ! 108: if (val.size == 'g' && val.format != 'f') ! 109: val.size = 'w'; ! 110: ! 111: while (*p == ' ' || *p == '\t') p++; ! 112: *string_ptr = p; ! 113: ! 114: return val; ! 115: } ! 116: ! 117: /* Print value VAL on stdout according to FORMAT, a letter or 0. ! 118: Do not end with a newline. ! 119: 0 means print VAL according to its own type. ! 120: SIZE is the letter for the size of datum being printed. ! 121: This is used to pad hex numbers so they line up. */ ! 122: ! 123: static void ! 124: print_formatted (val, format, size) ! 125: register value val; ! 126: register char format; ! 127: char size; ! 128: { ! 129: register CORE_ADDR val_long; ! 130: int len = TYPE_LENGTH (VALUE_TYPE (val)); ! 131: ! 132: if (VALUE_LVAL (val) == lval_memory) ! 133: next_address = VALUE_ADDRESS (val) + len; ! 134: ! 135: switch (format) ! 136: { ! 137: case 's': ! 138: next_address = VALUE_ADDRESS (val) ! 139: + value_print (value_addr (val), stdout, 0); ! 140: break; ! 141: ! 142: case 'i': ! 143: next_address = VALUE_ADDRESS (val) ! 144: + print_insn (VALUE_ADDRESS (val), stdout); ! 145: break; ! 146: ! 147: default: ! 148: if (format == 0 ! 149: || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_ARRAY ! 150: || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_STRUCT ! 151: || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_UNION) ! 152: value_print (val, stdout, format); ! 153: else ! 154: print_scalar_formatted (VALUE_CONTENTS (val), VALUE_TYPE (val), ! 155: format, size, stdout); ! 156: } ! 157: } ! 158: ! 159: /* Print a scalar of data of type TYPE, pointed to in GDB by VALADDR, ! 160: according to letters FORMAT and SIZE on STREAM. ! 161: FORMAT may not be zero. Formats s and i are not supported at this level. ! 162: ! 163: This is how the elements of an array or structure are printed ! 164: with a format. */ ! 165: ! 166: void ! 167: print_scalar_formatted (valaddr, type, format, size, stream) ! 168: char *valaddr; ! 169: struct type *type; ! 170: char format; ! 171: int size; ! 172: FILE *stream; ! 173: { ! 174: long val_long; ! 175: int len = TYPE_LENGTH (type); ! 176: ! 177: val_long = unpack_long (type, valaddr); ! 178: ! 179: /* If value is unsigned, truncate it in case negative. */ ! 180: if (format != 'd') ! 181: { ! 182: if (len == sizeof (char)) ! 183: val_long &= (1 << 8 * sizeof(char)) - 1; ! 184: else if (len == sizeof (short)) ! 185: val_long &= (1 << 8 * sizeof(short)) - 1; ! 186: } ! 187: ! 188: switch (format) ! 189: { ! 190: case 'x': ! 191: switch (size) ! 192: { ! 193: case 'b': ! 194: printf ("0x%02x", val_long); ! 195: break; ! 196: case 'h': ! 197: printf ("0x%04x", val_long); ! 198: break; ! 199: case 0: /* no size specified, like in print */ ! 200: case 'w': ! 201: printf ("0x%08x", val_long); ! 202: break; ! 203: case 'g': ! 204: printf ("0x%16x", val_long); ! 205: break; ! 206: default: ! 207: error ("Undefined output size \"%c\".", size); ! 208: } ! 209: break; ! 210: ! 211: case 'd': ! 212: printf ("%d", val_long); ! 213: break; ! 214: ! 215: case 'u': ! 216: printf ("%u", val_long); ! 217: break; ! 218: ! 219: case 'o': ! 220: if (val_long) ! 221: printf ("0%o", val_long); ! 222: else ! 223: printf ("0"); ! 224: break; ! 225: ! 226: case 'a': ! 227: print_address (val_long, stream); ! 228: break; ! 229: ! 230: case 'c': ! 231: value_print (value_from_long (builtin_type_char, val_long), stream, 0); ! 232: break; ! 233: ! 234: case 'f': ! 235: if (len == sizeof (float)) ! 236: type = builtin_type_float; ! 237: if (len == sizeof (double)) ! 238: type = builtin_type_double; ! 239: #ifdef IEEE_FLOAT ! 240: if (is_nan (unpack_double (type, valaddr))) ! 241: { ! 242: printf ("Nan"); ! 243: break; ! 244: } ! 245: #endif ! 246: printf ("%g", unpack_double (type, valaddr)); ! 247: break; ! 248: ! 249: case 0: ! 250: abort (); ! 251: ! 252: default: ! 253: error ("Undefined output format \"%c\".", format); ! 254: } ! 255: } ! 256: ! 257: /* Specify default address for `x' command. ! 258: `info lines' uses this. */ ! 259: ! 260: void ! 261: set_next_address (addr) ! 262: CORE_ADDR addr; ! 263: { ! 264: next_address = addr; ! 265: ! 266: /* Make address available to the user as $_. */ ! 267: set_internalvar (lookup_internalvar ("_"), ! 268: value_from_long (builtin_type_int, addr)); ! 269: } ! 270: ! 271: /* Print address ADDR symbolically on STREAM. ! 272: First print it as a number. Then perhaps print ! 273: <SYMBOL + OFFSET> after the number. */ ! 274: ! 275: void ! 276: print_address (addr, stream) ! 277: CORE_ADDR addr; ! 278: FILE *stream; ! 279: { ! 280: register int i; ! 281: ! 282: fprintf (stream, "0x%x", addr); ! 283: ! 284: i = find_pc_misc_function (addr); ! 285: if (i >= 0) ! 286: if (misc_function_vector[i].address != addr) ! 287: fprintf (stream, " <%s+%d>", ! 288: misc_function_vector[i].name, ! 289: addr - misc_function_vector[i].address); ! 290: else ! 291: fprintf (stream, " <%s>", misc_function_vector[i].name); ! 292: ! 293: } ! 294: ! 295: /* Examine data at address ADDR in format FMT. ! 296: Fetch it from memory and print on stdout. */ ! 297: ! 298: static void ! 299: do_examine (fmt, addr) ! 300: struct format_data fmt; ! 301: CORE_ADDR addr; ! 302: { ! 303: register char format = 0; ! 304: register char size; ! 305: register int count = 1; ! 306: struct type *val_type; ! 307: register int i; ! 308: register int maxelts; ! 309: ! 310: format = fmt.format; ! 311: size = fmt.size; ! 312: count = fmt.count; ! 313: next_address = addr; ! 314: ! 315: /* String or instruction format implies fetch single bytes ! 316: regardless of the specified size. */ ! 317: if (format == 's' || format == 'i') ! 318: size = 'b'; ! 319: ! 320: if (size == 'b') ! 321: val_type = builtin_type_char; ! 322: else if (size == 'h') ! 323: val_type = builtin_type_short; ! 324: else if (size == 'w') ! 325: val_type = builtin_type_long; ! 326: else if (size == 'g') ! 327: val_type = builtin_type_double; ! 328: ! 329: maxelts = 8; ! 330: if (size == 'w') ! 331: maxelts = 4; ! 332: if (size == 'g') ! 333: maxelts = 2; ! 334: if (format == 's' || format == 'i') ! 335: maxelts = 1; ! 336: ! 337: /* Print as many objects as specified in COUNT, at most maxelts per line, ! 338: with the address of the next one at the start of each line. */ ! 339: ! 340: while (count > 0) ! 341: { ! 342: print_address (next_address, stdout); ! 343: fputc (':', stdout); ! 344: for (i = maxelts; ! 345: i > 0 && count > 0; ! 346: i--, count--) ! 347: { ! 348: fputc ('\t', stdout); ! 349: /* Note that this sets next_address for the next object. */ ! 350: last_examine_address = next_address; ! 351: last_examine_value = value_at (val_type, next_address); ! 352: print_formatted (last_examine_value, format, size); ! 353: } ! 354: fputc ('\n', stdout); ! 355: fflush (stdout); ! 356: } ! 357: } ! 358: ! 359: static void ! 360: validate_format (fmt, cmdname) ! 361: struct format_data fmt; ! 362: char *cmdname; ! 363: { ! 364: if (fmt.size != 0) ! 365: error ("Size letters are meaningless in \"%s\" command.", cmdname); ! 366: if (fmt.count != 1) ! 367: error ("Item count other than 1 is meaningless in \"%s\" command.", ! 368: cmdname); ! 369: if (fmt.format == 'i' || fmt.format == 's') ! 370: error ("Format letter \"%c\" is meaningless in \"%s\" command.", ! 371: fmt.format, cmdname); ! 372: } ! 373: ! 374: static void ! 375: print_command (exp) ! 376: char *exp; ! 377: { ! 378: struct expression *expr; ! 379: register struct cleanup *old_chain = 0; ! 380: register char format = 0; ! 381: register value val; ! 382: struct format_data fmt; ! 383: int histindex; ! 384: int cleanup = 0; ! 385: ! 386: if (exp && *exp == '/') ! 387: { ! 388: exp++; ! 389: fmt = decode_format (&exp, last_format, 0); ! 390: validate_format (fmt, "print"); ! 391: last_format = format = fmt.format; ! 392: } ! 393: ! 394: if (exp && *exp) ! 395: { ! 396: expr = parse_c_expression (exp); ! 397: old_chain = make_cleanup (free_current_contents, &expr); ! 398: cleanup = 1; ! 399: val = evaluate_expression (expr); ! 400: } ! 401: else ! 402: val = access_value_history (0); ! 403: ! 404: histindex = record_latest_value (val); ! 405: printf ("$%d = ", histindex); ! 406: ! 407: print_formatted (val, format, fmt.size); ! 408: printf ("\n"); ! 409: ! 410: if (cleanup) ! 411: do_cleanups (old_chain); ! 412: } ! 413: ! 414: static void ! 415: output_command (exp) ! 416: char *exp; ! 417: { ! 418: struct expression *expr; ! 419: register struct cleanup *old_chain; ! 420: register char format = 0; ! 421: register value val; ! 422: struct format_data fmt; ! 423: ! 424: if (exp && *exp == '/') ! 425: { ! 426: exp++; ! 427: fmt = decode_format (&exp, 0, 0); ! 428: validate_format (fmt, "print"); ! 429: format = fmt.format; ! 430: } ! 431: ! 432: expr = parse_c_expression (exp); ! 433: old_chain = make_cleanup (free_current_contents, &expr); ! 434: ! 435: val = evaluate_expression (expr); ! 436: ! 437: print_formatted (val, format, fmt.size); ! 438: ! 439: do_cleanups (old_chain); ! 440: } ! 441: ! 442: static void ! 443: set_command (exp) ! 444: char *exp; ! 445: { ! 446: struct expression *expr = parse_c_expression (exp); ! 447: register struct cleanup *old_chain ! 448: = make_cleanup (free_current_contents, &expr); ! 449: evaluate_expression (expr); ! 450: do_cleanups (old_chain); ! 451: } ! 452: ! 453: static void ! 454: address_info (exp) ! 455: char *exp; ! 456: { ! 457: register struct symbol *sym; ! 458: register CORE_ADDR val; ! 459: ! 460: if (exp == 0) ! 461: error ("Argument required."); ! 462: ! 463: sym = lookup_symbol (exp, get_selected_block (), VAR_NAMESPACE); ! 464: if (sym == 0) ! 465: { ! 466: register int i; ! 467: ! 468: for (i = 0; i < misc_function_count; i++) ! 469: if (!strcmp (misc_function_vector[i].name, exp)) ! 470: break; ! 471: ! 472: if (i < misc_function_count) ! 473: printf ("Symbol \"%s\" is at 0x%x in a file compiled without -g.\n", ! 474: exp, misc_function_vector[i].address); ! 475: else ! 476: error ("No symbol \"%s\" in current context.", exp); ! 477: return; ! 478: } ! 479: ! 480: printf ("Symbol \"%s\" is ", SYMBOL_NAME (sym)); ! 481: val = SYMBOL_VALUE (sym); ! 482: ! 483: switch (SYMBOL_CLASS (sym)) ! 484: { ! 485: case LOC_CONST: ! 486: case LOC_CONST_BYTES: ! 487: printf ("constant"); ! 488: break; ! 489: ! 490: case LOC_LABEL: ! 491: printf ("a label at address 0x%x", val); ! 492: break; ! 493: ! 494: case LOC_REGISTER: ! 495: printf ("a variable in register %s", reg_names[val]); ! 496: break; ! 497: ! 498: case LOC_STATIC: ! 499: printf ("static at address 0x%x", val); ! 500: break; ! 501: ! 502: case LOC_ARG: ! 503: printf ("an argument at offset %d", val); ! 504: break; ! 505: ! 506: case LOC_LOCAL: ! 507: printf ("a local variable at frame offset %d", val); ! 508: break; ! 509: ! 510: case LOC_TYPEDEF: ! 511: printf ("a typedef"); ! 512: break; ! 513: ! 514: case LOC_BLOCK: ! 515: printf ("a function at address 0x%x", ! 516: BLOCK_START (SYMBOL_BLOCK_VALUE (sym))); ! 517: break; ! 518: } ! 519: printf (".\n"); ! 520: } ! 521: ! 522: static void ! 523: x_command (exp, from_tty) ! 524: char *exp; ! 525: int from_tty; ! 526: { ! 527: struct expression *expr; ! 528: struct format_data fmt; ! 529: struct cleanup *old_chain; ! 530: ! 531: fmt.format = last_format; ! 532: fmt.size = last_size; ! 533: fmt.count = 1; ! 534: ! 535: if (exp && *exp == '/') ! 536: { ! 537: exp++; ! 538: fmt = decode_format (&exp, last_format, last_size); ! 539: last_size = fmt.size; ! 540: last_format = fmt.format; ! 541: } ! 542: ! 543: /* If we have an expression, evaluate it and use it as the address. */ ! 544: ! 545: if (exp != 0 && *exp != 0) ! 546: { ! 547: expr = parse_c_expression (exp); ! 548: /* Cause expression not to be there any more ! 549: if this command is repeated with Newline. ! 550: But don't clobber a user-defined command's definition. */ ! 551: if (from_tty) ! 552: *exp = 0; ! 553: old_chain = make_cleanup (free_current_contents, &expr); ! 554: next_address = value_as_long (evaluate_expression (expr)); ! 555: do_cleanups (old_chain); ! 556: } ! 557: ! 558: do_examine (fmt, next_address); ! 559: ! 560: /* Make last address examined available to the user as $_. */ ! 561: set_internalvar (lookup_internalvar ("_"), ! 562: value_from_long (builtin_type_int, last_examine_address)); ! 563: ! 564: /* Make contents of last address examined available to the user as $__. */ ! 565: set_internalvar (lookup_internalvar ("__"), last_examine_value); ! 566: } ! 567: ! 568: /* Commands for printing types of things. */ ! 569: ! 570: static void ! 571: whatis_command (exp) ! 572: char *exp; ! 573: { ! 574: struct expression *expr; ! 575: register value val; ! 576: register struct cleanup *old_chain; ! 577: ! 578: if (exp) ! 579: { ! 580: expr = parse_c_expression (exp); ! 581: old_chain = make_cleanup (free_current_contents, &expr); ! 582: val = evaluate_type (expr); ! 583: } ! 584: else ! 585: val = access_value_history (0); ! 586: ! 587: printf ("type = "); ! 588: type_print (VALUE_TYPE (val), "", stdout, 1); ! 589: printf ("\n"); ! 590: ! 591: if (exp) ! 592: do_cleanups (old_chain); ! 593: } ! 594: ! 595: static void ! 596: ptype_command (typename) ! 597: char *typename; ! 598: { ! 599: register char *p = typename; ! 600: register int len; ! 601: extern struct block *get_current_block (); ! 602: register struct block *b ! 603: = (have_inferior_p () || have_core_file_p ()) ? get_current_block () : 0; ! 604: register struct type *type; ! 605: ! 606: if (typename == 0) ! 607: error_no_arg ("type name"); ! 608: ! 609: while (*p && *p != ' ' && *p != '\t') p++; ! 610: len = p - typename; ! 611: while (*p == ' ' || *p == '\t') p++; ! 612: ! 613: if (len == 6 && !strncmp (typename, "struct", 6)) ! 614: type = lookup_struct (p, b); ! 615: else if (len == 5 && !strncmp (typename, "union", 5)) ! 616: type = lookup_union (p, b); ! 617: else if (len == 4 && !strncmp (typename, "enum", 4)) ! 618: type = lookup_enum (p, b); ! 619: else ! 620: { ! 621: type = lookup_typename (typename, b, 1); ! 622: if (type == 0) ! 623: { ! 624: register struct symbol *sym ! 625: = lookup_symbol (typename, b, STRUCT_NAMESPACE); ! 626: if (sym == 0) ! 627: error ("No type named %s.", typename); ! 628: printf ("No type named %s, but there is a ", ! 629: typename); ! 630: switch (TYPE_CODE (SYMBOL_TYPE (sym))) ! 631: { ! 632: case TYPE_CODE_STRUCT: ! 633: printf ("struct"); ! 634: break; ! 635: ! 636: case TYPE_CODE_UNION: ! 637: printf ("union"); ! 638: break; ! 639: ! 640: case TYPE_CODE_ENUM: ! 641: printf ("enum"); ! 642: } ! 643: printf (" %s. Type \"help ptype\".\n", typename); ! 644: type = SYMBOL_TYPE (sym); ! 645: } ! 646: } ! 647: ! 648: type_print (type, "", stdout, 1); ! 649: printf ("\n"); ! 650: } ! 651: ! 652: struct display ! 653: { ! 654: /* Chain link to next auto-display item. */ ! 655: struct display *next; ! 656: /* Expression to be evaluated and displayed. */ ! 657: struct expression *exp; ! 658: /* Item number of this auto-display item. */ ! 659: int number; ! 660: /* Display format specified. */ ! 661: struct format_data format; ! 662: /* Block in which expression is to be evaluated. */ ! 663: struct block *block; ! 664: }; ! 665: ! 666: /* Chain of expressions whose values should be displayed ! 667: automatically each time the program stops. */ ! 668: ! 669: static struct display *display_chain; ! 670: ! 671: static int display_number; ! 672: ! 673: /* Add an expression to the auto-display chain. ! 674: Specify the expression. */ ! 675: ! 676: static void ! 677: display_command (exp, from_tty) ! 678: char *exp; ! 679: int from_tty; ! 680: { ! 681: struct format_data fmt; ! 682: register struct expression *expr; ! 683: register struct display *new; ! 684: ! 685: if (exp == 0) ! 686: { ! 687: do_displays (); ! 688: return; ! 689: } ! 690: ! 691: if (*exp == '/') ! 692: { ! 693: exp++; ! 694: fmt = decode_format (&exp, 0, 0); ! 695: if (fmt.size && fmt.format == 0) ! 696: fmt.format = 'x'; ! 697: if (fmt.format == 'i' || fmt.format == 's') ! 698: fmt.size = 'b'; ! 699: } ! 700: else ! 701: { ! 702: fmt.format = 0; ! 703: fmt.size = 0; ! 704: fmt.count = 0; ! 705: } ! 706: ! 707: expr = parse_c_expression (exp); ! 708: ! 709: new = (struct display *) xmalloc (sizeof (struct display)); ! 710: ! 711: new->exp = expr; ! 712: new->next = display_chain; ! 713: new->number = ++display_number; ! 714: new->format = fmt; ! 715: display_chain = new; ! 716: ! 717: if (from_tty) ! 718: do_one_display (new); ! 719: ! 720: dont_repeat (); ! 721: } ! 722: ! 723: static void ! 724: free_display (d) ! 725: struct display *d; ! 726: { ! 727: free (d->exp); ! 728: free (d); ! 729: } ! 730: ! 731: /* Clear out the display_chain. ! 732: Done when new symtabs are loaded, since this invalidates ! 733: the types stored in many expressions. */ ! 734: ! 735: void ! 736: clear_displays () ! 737: { ! 738: register struct display *d; ! 739: ! 740: while (d = display_chain) ! 741: { ! 742: free (d->exp); ! 743: display_chain = d->next; ! 744: free (d); ! 745: } ! 746: } ! 747: ! 748: /* Delete the auto-display number NUM. */ ! 749: ! 750: void ! 751: delete_display (num) ! 752: int num; ! 753: { ! 754: register struct display *d1, *d; ! 755: ! 756: if (!display_chain) ! 757: error ("No display number %d.", num); ! 758: ! 759: if (display_chain->number == num) ! 760: { ! 761: d1 = display_chain; ! 762: display_chain = d1->next; ! 763: free_display (d1); ! 764: } ! 765: else ! 766: for (d = display_chain; ; d = d->next) ! 767: { ! 768: if (d->next == 0) ! 769: error ("No display number %d.", num); ! 770: if (d->next->number == num) ! 771: { ! 772: d1 = d->next; ! 773: d->next = d1->next; ! 774: free_display (d1); ! 775: break; ! 776: } ! 777: } ! 778: } ! 779: ! 780: /* Delete some values from the auto-display chain. ! 781: Specify the element numbers. */ ! 782: ! 783: static void ! 784: undisplay_command (args) ! 785: char *args; ! 786: { ! 787: register char *p = args; ! 788: register char *p1; ! 789: register int num; ! 790: register struct display *d, *d1; ! 791: ! 792: if (args == 0) ! 793: { ! 794: if (query ("Delete all auto-display expressions? ")) ! 795: clear_displays (); ! 796: dont_repeat (); ! 797: return; ! 798: } ! 799: ! 800: while (*p) ! 801: { ! 802: p1 = p; ! 803: while (*p1 >= '0' && *p1 <= '9') p1++; ! 804: if (*p1 && *p1 != ' ' && *p1 != '\t') ! 805: error ("Arguments must be display numbers."); ! 806: ! 807: num = atoi (p); ! 808: ! 809: delete_display (num); ! 810: ! 811: p = p1; ! 812: while (*p == ' ' || *p == '\t') p++; ! 813: } ! 814: dont_repeat (); ! 815: } ! 816: ! 817: /* Display a single auto-display. */ ! 818: ! 819: static void ! 820: do_one_display (d) ! 821: struct display *d; ! 822: { ! 823: current_display_number = d->number; ! 824: ! 825: printf ("%d: ", d->number); ! 826: if (d->format.size) ! 827: { ! 828: printf ("x/"); ! 829: if (d->format.count != 1) ! 830: printf ("%d", d->format.count); ! 831: printf ("%c", d->format.format); ! 832: if (d->format.format != 'i' && d->format.format != 's') ! 833: printf ("%c", d->format.size); ! 834: printf (" "); ! 835: print_expression (d->exp, stdout); ! 836: if (d->format.count != 1) ! 837: printf ("\n"); ! 838: else ! 839: printf (" "); ! 840: do_examine (d->format, ! 841: value_as_long (evaluate_expression (d->exp))); ! 842: } ! 843: else ! 844: { ! 845: if (d->format.format) ! 846: printf ("/%c ", d->format.format); ! 847: print_expression (d->exp, stdout); ! 848: printf (" = "); ! 849: print_formatted (evaluate_expression (d->exp), ! 850: d->format.format, d->format.size); ! 851: printf ("\n"); ! 852: } ! 853: ! 854: fflush (stdout); ! 855: current_display_number = -1; ! 856: } ! 857: ! 858: /* Display all of the values on the auto-display chain. */ ! 859: ! 860: void ! 861: do_displays () ! 862: { ! 863: register struct display *d; ! 864: ! 865: for (d = display_chain; d; d = d->next) ! 866: do_one_display (d); ! 867: } ! 868: ! 869: /* Delete the auto-display which we were in the process of displaying. ! 870: This is done when there is an error or a signal. */ ! 871: ! 872: void ! 873: delete_current_display () ! 874: { ! 875: if (current_display_number >= 0) ! 876: { ! 877: delete_display (current_display_number); ! 878: fprintf (stderr, "Deleting display %d to avoid infinite recursion.\n", ! 879: current_display_number); ! 880: } ! 881: current_display_number = -1; ! 882: } ! 883: ! 884: static void ! 885: display_info () ! 886: { ! 887: register struct display *d; ! 888: ! 889: if (!display_chain) ! 890: printf ("There are no auto-display expressions now.\n"); ! 891: else ! 892: printf ("Auto-display expressions now in effect:\n"); ! 893: for (d = display_chain; d; d = d->next) ! 894: { ! 895: printf ("%d: ", d->number); ! 896: if (d->format.size) ! 897: printf ("/%d%c%c ", d->format.count, d->format.size, ! 898: d->format.format); ! 899: else if (d->format.format) ! 900: printf ("/%c ", d->format.format); ! 901: print_expression (d->exp, stdout); ! 902: printf ("\n"); ! 903: fflush (stdout); ! 904: } ! 905: } ! 906: ! 907: /* Print the value in stack frame FRAME of a variable ! 908: specified by a struct symbol. */ ! 909: ! 910: void ! 911: print_variable_value (var, frame, stream) ! 912: struct symbol *var; ! 913: CORE_ADDR frame; ! 914: FILE *stream; ! 915: { ! 916: value val = read_var_value (var, frame); ! 917: value_print (val, stream, 0); ! 918: } ! 919: ! 920: /* Print the arguments of a stack frame, given the function FUNC ! 921: running in that frame (as a symbol), the address of the arglist, ! 922: and the number of args according to the stack frame (or -1 if unknown). */ ! 923: ! 924: static void print_frame_nameless_args (); ! 925: ! 926: print_frame_args (func, addr, num, stream) ! 927: struct symbol *func; ! 928: register CORE_ADDR addr; ! 929: int num; ! 930: FILE *stream; ! 931: { ! 932: struct block *b; ! 933: int nsyms = 0; ! 934: int first = 1; ! 935: register int i; ! 936: register int last_offset = FRAME_ARGS_SKIP; ! 937: register struct symbol *sym, *nextsym; ! 938: register value val; ! 939: ! 940: if (func) ! 941: { ! 942: b = SYMBOL_BLOCK_VALUE (func); ! 943: nsyms = BLOCK_NSYMS (b); ! 944: } ! 945: ! 946: while (1) ! 947: { ! 948: /* Find first arg that is not before LAST_OFFSET. */ ! 949: nextsym = 0; ! 950: for (i = 0; i < nsyms; i++) ! 951: { ! 952: QUIT; ! 953: sym = BLOCK_SYM (b, i); ! 954: if (SYMBOL_CLASS (sym) == LOC_ARG ! 955: && SYMBOL_VALUE (sym) >= last_offset ! 956: && (nextsym == 0 ! 957: || SYMBOL_VALUE (sym) < SYMBOL_VALUE (nextsym))) ! 958: nextsym = sym; ! 959: } ! 960: if (nextsym == 0) ! 961: break; ! 962: sym = nextsym; ! 963: /* Print any nameless args between the last arg printed ! 964: and the next arg. */ ! 965: if (last_offset != (SYMBOL_VALUE (sym) / sizeof (int)) * sizeof (int)) ! 966: { ! 967: print_frame_nameless_args (addr, last_offset, SYMBOL_VALUE (sym), ! 968: stream); ! 969: first = 0; ! 970: } ! 971: /* Print the next arg. */ ! 972: val = value_at (SYMBOL_TYPE (sym), addr + SYMBOL_VALUE (sym)); ! 973: if (! first) ! 974: fprintf (stream, ", "); ! 975: fprintf (stream, "%s=", SYMBOL_NAME (sym)); ! 976: value_print (val, stream, 0); ! 977: first = 0; ! 978: last_offset = SYMBOL_VALUE (sym) + TYPE_LENGTH (SYMBOL_TYPE (sym)); ! 979: /* Round up address of next arg to multiple of size of int. */ ! 980: last_offset ! 981: = ((last_offset + sizeof (int) - 1) / sizeof (int)) * sizeof (int); ! 982: } ! 983: if (num >= 0 && num * sizeof (int) + FRAME_ARGS_SKIP > last_offset) ! 984: print_frame_nameless_args (addr, last_offset, ! 985: num * sizeof (int) + FRAME_ARGS_SKIP, stream); ! 986: } ! 987: ! 988: static void ! 989: print_frame_nameless_args (argsaddr, start, end, stream) ! 990: CORE_ADDR argsaddr; ! 991: int start; ! 992: int end; ! 993: FILE *stream; ! 994: { ! 995: while (start < end) ! 996: { ! 997: QUIT; ! 998: if (start != FRAME_ARGS_SKIP) ! 999: fprintf (stream, ", "); ! 1000: fprintf (stream, "%d", ! 1001: read_memory_integer (argsaddr + start, sizeof (int))); ! 1002: start += sizeof (int); ! 1003: } ! 1004: } ! 1005: ! 1006: static void ! 1007: printf_command (arg) ! 1008: char *arg; ! 1009: { ! 1010: register char *f; ! 1011: register char *s = arg; ! 1012: char *string; ! 1013: value *val_args; ! 1014: int nargs = 0; ! 1015: int allocated_args = 20; ! 1016: char *arg_bytes; ! 1017: char *argclass; ! 1018: int i; ! 1019: int argindex; ! 1020: int nargs_wanted; ! 1021: ! 1022: val_args = (value *) xmalloc (allocated_args * sizeof (value)); ! 1023: ! 1024: if (s == 0) ! 1025: error_no_arg ("format-control string and values to print"); ! 1026: ! 1027: /* Skip white space before format string */ ! 1028: while (*s == ' ' || *s == '\t') s++; ! 1029: ! 1030: /* A format string should follow, enveloped in double quotes */ ! 1031: if (*s++ != '"') ! 1032: error ("Bad format string, missing '\"'."); ! 1033: ! 1034: /* Parse the format-control string and copy it into the string STRING, ! 1035: processing some kinds of escape sequence. */ ! 1036: ! 1037: f = string = (char *) alloca (strlen (s) + 1); ! 1038: while (*s != '"') ! 1039: { ! 1040: int c = *s++; ! 1041: switch (c) ! 1042: { ! 1043: case '\0': ! 1044: error ("Bad format string, non-terminated '\"'."); ! 1045: /* doesn't return */ ! 1046: ! 1047: case '\\': ! 1048: switch (c = *s++) ! 1049: { ! 1050: case '\\': ! 1051: *f++ = '\\'; ! 1052: break; ! 1053: case 'n': ! 1054: *f++ = '\n'; ! 1055: break; ! 1056: case 't': ! 1057: *f++ = '\t'; ! 1058: break; ! 1059: case 'r': ! 1060: *f++ = '\r'; ! 1061: break; ! 1062: case '"': ! 1063: *f++ = '"'; ! 1064: break; ! 1065: default: ! 1066: /* ??? TODO: handle other escape sequences */ ! 1067: error ("Unrecognized \\ escape character in format string."); ! 1068: } ! 1069: break; ! 1070: ! 1071: default: ! 1072: *f++ = c; ! 1073: } ! 1074: } ! 1075: ! 1076: /* Skip over " and following space and comma. */ ! 1077: s++; ! 1078: *f++ = '\0'; ! 1079: while (*s == ' ' || *s == '\t') s++; ! 1080: ! 1081: if (*s != ',' && *s != 0) ! 1082: error ("Invalid argument syntax"); ! 1083: ! 1084: if (*s == ',') s++; ! 1085: while (*s == ' ' || *s == '\t') s++; ! 1086: ! 1087: /* Now scan the string for %-specs and see what kinds of args they want. ! 1088: argclass[I] is set to 1 if the Ith arg should be a string. */ ! 1089: ! 1090: argclass = (char *) alloca (strlen (s)); ! 1091: nargs_wanted = 0; ! 1092: f = string; ! 1093: while (*f) ! 1094: if (*f++ == '%') ! 1095: { ! 1096: while (index ("0123456789.hlL-+ #", *f)) f++; ! 1097: if (*f == 's') ! 1098: argclass[nargs_wanted++] = 1; ! 1099: else if (*f != '%') ! 1100: argclass[nargs_wanted++] = 0; ! 1101: f++; ! 1102: } ! 1103: ! 1104: /* Now, parse all arguments and evaluate them. ! 1105: Store the VALUEs in VAL_ARGS. */ ! 1106: ! 1107: while (*s != '\0') ! 1108: { ! 1109: char *s1; ! 1110: if (nargs == allocated_args) ! 1111: val_args = (value *) xrealloc (val_args, ! 1112: (allocated_args *= 2) ! 1113: * sizeof (value)); ! 1114: s1 = s; ! 1115: val_args[nargs++] = parse_to_comma_and_eval (&s1); ! 1116: s = s1; ! 1117: if (*s == ',') ! 1118: s++; ! 1119: } ! 1120: ! 1121: if (nargs != nargs_wanted) ! 1122: error ("Wrong number of arguments for specified format-string"); ! 1123: ! 1124: /* Now lay out an argument-list containing the arguments ! 1125: as doubles, integers and C pointers. */ ! 1126: ! 1127: arg_bytes = (char *) alloca (sizeof (double) * nargs); ! 1128: argindex = 0; ! 1129: for (i = 0; i < nargs; i++) ! 1130: { ! 1131: if (argclass[i]) ! 1132: { ! 1133: char *str; ! 1134: int tem, j; ! 1135: tem = value_as_long (val_args[i]); ! 1136: ! 1137: /* This is a %s argument. Find the length of the string. */ ! 1138: for (j = 0; ; j++) ! 1139: { ! 1140: char c; ! 1141: QUIT; ! 1142: read_memory (tem + j, &c, 1); ! 1143: if (c == 0) ! 1144: break; ! 1145: } ! 1146: ! 1147: /* Copy the string contents into a string inside GDB. */ ! 1148: str = (char *) alloca (j + 1); ! 1149: read_memory (tem, str, j); ! 1150: str[j] = 0; ! 1151: ! 1152: /* Pass address of internal copy as the arg to vprintf. */ ! 1153: *((int *) &arg_bytes[argindex]) = (int) str; ! 1154: argindex += sizeof (int); ! 1155: } ! 1156: else if (VALUE_TYPE (val_args[i])->code == TYPE_CODE_FLT) ! 1157: { ! 1158: *((double *) &arg_bytes[argindex]) = value_as_double (val_args[i]); ! 1159: argindex += sizeof (double); ! 1160: } ! 1161: else ! 1162: { ! 1163: *((int *) &arg_bytes[argindex]) = value_as_long (val_args[i]); ! 1164: argindex += sizeof (int); ! 1165: } ! 1166: } ! 1167: ! 1168: vprintf (string, arg_bytes); ! 1169: } ! 1170: ! 1171: static ! 1172: initialize () ! 1173: { ! 1174: current_display_number = -1; ! 1175: ! 1176: add_info ("address", address_info, ! 1177: "Describe where variable VAR is stored."); ! 1178: ! 1179: add_com ("x", class_vars, x_command, ! 1180: "Examine memory: x/FMT ADDRESS.\n\ ! 1181: ADDRESS is an expression for the memory address to examine.\n\ ! 1182: FMT is a repeat count followed by a format letter and a size letter.\n\ ! 1183: Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal),\n\ ! 1184: f(float), a(address), i(instruction), c(char) and s(string).\n\ ! 1185: Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes).\n\ ! 1186: g is meaningful only with f, for type double.\n\ ! 1187: The specified number of objects of the specified size are printed\n\ ! 1188: according to the format.\n\n\ ! 1189: Defaults for format and size letters are those previously used.\n\ ! 1190: Default count is 1. Default address is following last thing printed\n\ ! 1191: with this command or \"print\"."); ! 1192: ! 1193: add_com ("ptype", class_vars, ptype_command, ! 1194: "Print definition of type TYPE.\n\ ! 1195: Argument may be a type name defined by typedef, or \"struct STRUCTNAME\"\n\ ! 1196: or \"union UNIONNAME\" or \"enum ENUMNAME\".\n\ ! 1197: The selected stack frame's lexical context is used to look up the name."); ! 1198: ! 1199: add_com ("whatis", class_vars, whatis_command, ! 1200: "Print data type of expression EXP."); ! 1201: ! 1202: add_info ("display", display_info, ! 1203: "Expressions to display when program stops, with code numbers."); ! 1204: add_com ("undisplay", class_vars, undisplay_command, ! 1205: "Cancel some expressions to be displayed whenever program stops.\n\ ! 1206: Arguments are the code numbers of the expressions to stop displaying.\n\ ! 1207: No argument means cancel all automatic-display expressions.\n\ ! 1208: Do \"info display\" to see current list of code numbers."); ! 1209: add_com ("display", class_vars, display_command, ! 1210: "Print value of expression EXP each time the program stops.\n\ ! 1211: /FMT may be used before EXP as in the \"print\" command.\n\ ! 1212: /FMT \"i\" or \"s\" or including a size-letter is allowed,\n\ ! 1213: as in the \"x\" command, and then EXP is used to get the address to examine\n\ ! 1214: and examining is done as in the \"x\" command.\n\n\ ! 1215: With no argument, display all currently requested auto-display expressions.\n\ ! 1216: Use \"undisplay\" to cancel display requests previously made."); ! 1217: ! 1218: add_com ("printf", class_vars, printf_command, ! 1219: "printf \"printf format string\", arg1, arg2, arg3, ..., argn\n\ ! 1220: This is useful for formatted output in user-defined commands."); ! 1221: add_com ("output", class_vars, output_command, ! 1222: "Like \"print\" but don't put in value history and don't print newline.\n\ ! 1223: This is useful in user-defined commands."); ! 1224: ! 1225: add_com ("set", class_vars, set_command, ! 1226: "Perform an assignment VAR = EXP. You must type the \"=\".\n\ ! 1227: VAR may be a debugger \"convenience\" variables (names starting with $),\n\ ! 1228: a register (a few standard names starting with $), or an actual variable\n\ ! 1229: in the program being debugger. EXP is any expression."); ! 1230: ! 1231: add_com ("print", class_vars, print_command, ! 1232: concat ("Print value of expression EXP.\n\ ! 1233: Variables accessible are those of the lexical environment of the selected\n\ ! 1234: stack frame, plus all those whose scope is global or an entire file.\n\ ! 1235: \n\ ! 1236: $NUM gets previous value number NUM. $ and $$ are the last two values.\n\ ! 1237: $$NUM refers to NUM'th value back from the last one.\n\ ! 1238: Names starting with $ refer to registers (with the values they would have\n\ ! 1239: if the program were to return to the stack frame now selected, restoring\n\ ! 1240: all registers saved by frames farther in) or else to debugger\n\ ! 1241: \"convenience\" variables (any such name not a known register).\n\ ! 1242: Use assignment expressions to give values to convenience variables.\n", ! 1243: "\n\ ! 1244: \{TYPE}ADREXP refers to a datum of data type TYPE, located at address ADREXP.\n\ ! 1245: @ is a binary operator for treating consecutive data objects\n\ ! 1246: anywhere in memory as an array. FOO@NUM gives an array whose first\n\ ! 1247: element is FOO, whose second element is stored in the space following\n\ ! 1248: where FOO is stored, etc. FOO must be an expression whose value\n\ ! 1249: resides in memory.\n", ! 1250: "\n\ ! 1251: EXP may be preceded with /FMT, where FMT is a format letter\n\ ! 1252: but no count or size letter (see \"x\" command).")); ! 1253: add_com_alias ("p", "print", class_vars, 1); ! 1254: } ! 1255: ! 1256: END_FILE
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.