From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 7649 invoked by alias); 14 Sep 2005 17:13:55 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 7546 invoked by uid 22791); 14 Sep 2005 17:13:24 -0000 Received: from nile.gnat.com (HELO nile.gnat.com) (205.232.38.5) by sourceware.org (qpsmtpd/0.30-dev) with ESMTP; Wed, 14 Sep 2005 17:13:24 +0000 Received: from localhost (localhost [127.0.0.1]) by filtered-nile.gnat.com (Postfix) with ESMTP id 1153E48CDBE for ; Wed, 14 Sep 2005 13:13:23 -0400 (EDT) Received: from nile.gnat.com ([127.0.0.1]) by localhost (nile.gnat.com [127.0.0.1]) (amavisd-new, port 10024) with LMTP id 05720-01-7 for ; Wed, 14 Sep 2005 13:13:22 -0400 (EDT) Received: from takamaka.act-europe.fr (s142-179-108-108.bc.hsia.telus.net [142.179.108.108]) by nile.gnat.com (Postfix) with ESMTP id D4D8F48CD93 for ; Wed, 14 Sep 2005 13:13:21 -0400 (EDT) Received: by takamaka.act-europe.fr (Postfix, from userid 507) id 183D947E74; Wed, 14 Sep 2005 10:13:20 -0700 (PDT) Date: Wed, 14 Sep 2005 17:13:00 -0000 From: Joel Brobecker To: gdb-patches@sources.redhat.com Subject: Re: [RFA] print arrays with indexes Message-ID: <20050914171319.GD27542@adacore.com> References: <20050906202018.GC1153@adacore.com> <20050906205710.GA12715@nevyn.them.org> <20050907053951.GC1540@adacore.com> <20050907132316.GA3622@nevyn.them.org> <20050907202402.GF1540@adacore.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20050907202402.GF1540@adacore.com> User-Agent: Mutt/1.4i X-SW-Source: 2005-09/txt/msg00104.txt.bz2 Hello, It'd be nice to have this patch reviewed. It touches quite a few files, so I'd rather not wait for too long to avoid merging conflicts. Once we agree on the interface, I think the code will follow naturally. Thank you! On Wed, Sep 07, 2005 at 01:24:02PM -0700, Joel Brobecker wrote: > > > There is also Jim's suggestion which has some merits. I'm more of > > > an all or nothing kind of guy, so I prefer the approach I've chosen, > > > but I am flexible. > > > > I've got no strong opinions on this either way. Thresholds seem > > complicated as a UI. > > I feel the same way too. > > Here is a revised patch, that implements the language method. > Now, with C, we get: > > (gdb) p array > $1 = {[0] = 1, [1] = 2, [2] = 3, [3] = 4} > > This is also the default for all the other languages, except Ada, where > the debugger will print: > > (gdb) p one_two_three > $1 = (1 => 1, 2 => 2, 3 => 3) > > 2005-09-07 Joel Brobecker > > * language.h (language_defn): New field la_print_array_index. > (LA_PRINT_ARRAY_INDEX): New macro. > (default_print_array_index): Add declaration. > * language.c (default_print_array_index): new function. > (unknown_language): Add value for new field. > (auto_language): Likewise. > (local_language): Likewise. > * c-lang.c (c_language_defn): Likewise. > (cpluc_language_defn): Likewise. > (asm_language_defn): Likewise. > (minimal_language_defn): Likewise. > * f-lang.c (f_language_defn): Likewise. > * jv-lang.c (java_language_defn): Likewise. > * m2-lang.c (m2_language_defn): Likewise. > * objc-lang.c (objc_language_defn): Likewise. > * p-lang.c (pascal_language_defn): Likewise. > * ada-lang.c (ada_print_array_index): New function. > (ada_language_defn): Add value for new field. > * valprint.h (print_array_indexes_p): Add declaration. > (maybe_print_array_index): Add declaration. > (val_print_array_elements): Add new parameter to function profile. > * valprint.c (print_array_indexes): New static variable. > (show_print_array_indexes): New function. > (print_array_indexes_p): New function. > (maybe_print_array_index): New function. > (val_print_array_elements): Add new parameter real_index_offset. > Print the index of each element if required by the user. > (_initialize_valprint): Add new array-indexes "set/show print" command. > * c-valprint.c (c_val_print): Update call to val_print_array_elements. > * p-valprint.c (pascal_val_print): Likewise. > * ada-valprint.c (ada_get_array_low_bound_and_type): New function, > mostly extracted from print_optional_low_bound(). > (print_optional_low_bound): Replace extracted code by call to > ada_get_array_low_bound_and_type(). Stop printing the low bound > if indexes will be printed for all elements of the array. > (val_print_packed_array_elements): Print the index of each element > of the array if necessary. > (ada_val_print_1): For non-packed arrays, compute the array low > bound, and pass it to val_print_array_elements(). > > Tested on x86-linux, no regression. Testcases and documentation to follow > after the review. > > Thanks, > -- > Joel > Index: language.h > =================================================================== > RCS file: /cvs/src/src/gdb/language.h,v > retrieving revision 1.35 > diff -u -p -r1.35 language.h > --- language.h 9 May 2005 21:20:34 -0000 1.35 > +++ language.h 7 Sep 2005 20:00:10 -0000 > @@ -275,6 +275,12 @@ struct language_defn > void (*la_language_arch_info) (struct gdbarch *, > struct language_arch_info *); > > + /* Print the index of an element of an array. */ > + void (*la_print_array_index) (struct value *index_value, > + struct ui_file *stream, > + int format, > + enum val_prettyprint pretty); > + > /* Add fields above this point, so the magic number is always last. */ > /* Magic number for compat checking */ > > @@ -362,6 +368,9 @@ extern enum language set_language (enum > #define LA_EMIT_CHAR(ch, stream, quoter) \ > (current_language->la_emitchar(ch, stream, quoter)) > > +#define LA_PRINT_ARRAY_INDEX(index_value, stream, format, pretty) \ > + (current_language->la_print_array_index(index_value, stream, format, pretty)) > + > /* Test a character to decide whether it can be printed in literal form > or needs to be printed in another representation. For example, > in C the literal form of the character with octal value 141 is 'a' > @@ -457,4 +466,10 @@ extern char *language_class_name_from_ph > /* Splitting strings into words. */ > extern char *default_word_break_characters (void); > > +/* Print the index of an array element using the C99 syntax. */ > +extern void default_print_array_index (struct value *index_value, > + struct ui_file *stream, > + int format, > + enum val_prettyprint pretty); > + > #endif /* defined (LANGUAGE_H) */ > Index: language.c > =================================================================== > RCS file: /cvs/src/src/gdb/language.c,v > retrieving revision 1.62 > diff -u -p -r1.62 language.c > --- language.c 29 Aug 2005 12:57:49 -0000 1.62 > +++ language.c 7 Sep 2005 20:00:09 -0000 > @@ -1057,6 +1057,17 @@ default_word_break_characters (void) > return " \t\n!@#$%^&*()+=|~`}{[]\"';:?/>.<,-"; > } > > +/* Print the index of array elements using the C99 syntax. */ > + > +void > +default_print_array_index (struct value *index_value, struct ui_file *stream, > + int format, enum val_prettyprint pretty) > +{ > + fprintf_filtered (stream, "["); > + LA_VALUE_PRINT (index_value, stream, format, pretty); > + fprintf_filtered (stream, "] = "); > +} > + > /* Define the language that is no language. */ > > static int > @@ -1181,6 +1192,7 @@ const struct language_defn unknown_langu > NULL, > default_word_break_characters, > unknown_language_arch_info, /* la_language_arch_info. */ > + default_print_array_index, > LANG_MAGIC > }; > > @@ -1217,6 +1229,7 @@ const struct language_defn auto_language > NULL, > default_word_break_characters, > unknown_language_arch_info, /* la_language_arch_info. */ > + default_print_array_index, > LANG_MAGIC > }; > > @@ -1252,6 +1265,7 @@ const struct language_defn local_languag > NULL, > default_word_break_characters, > unknown_language_arch_info, /* la_language_arch_info. */ > + default_print_array_index, > LANG_MAGIC > }; > > Index: c-lang.c > =================================================================== > RCS file: /cvs/src/src/gdb/c-lang.c,v > retrieving revision 1.37 > diff -u -p -r1.37 c-lang.c > --- c-lang.c 9 May 2005 21:20:30 -0000 1.37 > +++ c-lang.c 7 Sep 2005 19:58:49 -0000 > @@ -595,6 +595,7 @@ const struct language_defn c_language_de > NULL, > default_word_break_characters, > c_language_arch_info, > + default_print_array_index, > LANG_MAGIC > }; > > @@ -653,6 +654,7 @@ const struct language_defn cplus_languag > &builtin_type_char, /* Type of string elements */ > default_word_break_characters, > NULL, /* FIXME: la_language_arch_info. */ > + default_print_array_index, > LANG_MAGIC > }; > > @@ -688,6 +690,7 @@ const struct language_defn asm_language_ > NULL, > default_word_break_characters, > c_language_arch_info, /* FIXME: la_language_arch_info. */ > + default_print_array_index, > LANG_MAGIC > }; > > @@ -728,6 +731,7 @@ const struct language_defn minimal_langu > NULL, > default_word_break_characters, > c_language_arch_info, > + default_print_array_index, > LANG_MAGIC > }; > > Index: f-lang.c > =================================================================== > RCS file: /cvs/src/src/gdb/f-lang.c,v > retrieving revision 1.31 > diff -u -p -r1.31 f-lang.c > --- f-lang.c 9 May 2005 21:20:30 -0000 1.31 > +++ f-lang.c 7 Sep 2005 19:59:30 -0000 > @@ -485,6 +485,7 @@ const struct language_defn f_language_de > &builtin_type_f_character, /* Type of string elements */ > default_word_break_characters, > NULL, /* FIXME: la_language_arch_info. */ > + default_print_array_index, > LANG_MAGIC > }; > > Index: jv-lang.c > =================================================================== > RCS file: /cvs/src/src/gdb/jv-lang.c,v > retrieving revision 1.42 > diff -u -p -r1.42 jv-lang.c > --- jv-lang.c 27 May 2005 04:39:32 -0000 1.42 > +++ jv-lang.c 7 Sep 2005 20:00:08 -0000 > @@ -1114,6 +1114,7 @@ const struct language_defn java_language > NULL, > default_word_break_characters, > c_language_arch_info, > + default_print_array_index, > LANG_MAGIC > }; > > Index: m2-lang.c > =================================================================== > RCS file: /cvs/src/src/gdb/m2-lang.c,v > retrieving revision 1.23 > diff -u -p -r1.23 m2-lang.c > --- m2-lang.c 9 May 2005 21:20:34 -0000 1.23 > +++ m2-lang.c 7 Sep 2005 20:00:14 -0000 > @@ -437,6 +437,7 @@ const struct language_defn m2_language_d > &builtin_type_m2_char, /* Type of string elements */ > default_word_break_characters, > NULL, /* FIXME: la_language_arch_info. */ > + default_print_array_index, > LANG_MAGIC > }; > > Index: objc-lang.c > =================================================================== > RCS file: /cvs/src/src/gdb/objc-lang.c,v > retrieving revision 1.49 > diff -u -p -r1.49 objc-lang.c > --- objc-lang.c 12 Jul 2005 12:11:44 -0000 1.49 > +++ objc-lang.c 7 Sep 2005 20:00:33 -0000 > @@ -684,6 +684,7 @@ const struct language_defn objc_language > &builtin_type_char, /* Type of string elements */ > default_word_break_characters, > NULL, /* FIXME: la_language_arch_info. */ > + default_print_array_index, > LANG_MAGIC > }; > > Index: p-lang.c > =================================================================== > RCS file: /cvs/src/src/gdb/p-lang.c,v > retrieving revision 1.25 > diff -u -p -r1.25 p-lang.c > --- p-lang.c 9 May 2005 21:20:34 -0000 1.25 > +++ p-lang.c 7 Sep 2005 20:00:36 -0000 > @@ -477,6 +477,7 @@ const struct language_defn pascal_langua > &builtin_type_char, /* Type of string elements */ > default_word_break_characters, > NULL, /* FIXME: la_language_arch_info. */ > + default_print_array_index, > LANG_MAGIC > }; > > Index: scm-lang.c > =================================================================== > RCS file: /cvs/src/src/gdb/scm-lang.c,v > retrieving revision 1.32 > diff -u -p -r1.32 scm-lang.c > --- scm-lang.c 27 May 2005 04:39:32 -0000 1.32 > +++ scm-lang.c 7 Sep 2005 20:01:01 -0000 > @@ -269,6 +269,7 @@ const struct language_defn scm_language_ > NULL, > default_word_break_characters, > c_language_arch_info, > + default_print_array_index, > LANG_MAGIC > }; > > Index: ada-lang.c > =================================================================== > RCS file: /cvs/src/src/gdb/ada-lang.c,v > retrieving revision 1.78 > diff -u -p -r1.78 ada-lang.c > --- ada-lang.c 9 May 2005 21:20:29 -0000 1.78 > +++ ada-lang.c 7 Sep 2005 19:58:31 -0000 > @@ -303,6 +303,16 @@ ada_get_gdb_completer_word_break_charact > return ada_completer_word_break_characters; > } > > +/* Print an array element index using the Ada syntax. */ > + > +static void > +ada_print_array_index (struct value *index_value, struct ui_file *stream, > + int format, enum val_prettyprint pretty) > +{ > + LA_VALUE_PRINT (index_value, stream, format, pretty); > + fprintf_filtered (stream, " => "); > +} > + > /* Read the string located at ADDR from the inferior and store the > result into BUF. */ > > @@ -8766,6 +8776,7 @@ const struct language_defn ada_language_ > NULL, > ada_get_gdb_completer_word_break_characters, > ada_language_arch_info, > + ada_print_array_index, > LANG_MAGIC > }; > > Index: valprint.h > =================================================================== > RCS file: /cvs/src/src/gdb/valprint.h,v > retrieving revision 1.10 > diff -u -p -r1.10 valprint.h > --- valprint.h 9 May 2005 21:20:35 -0000 1.10 > +++ valprint.h 7 Sep 2005 20:01:35 -0000 > @@ -50,10 +50,16 @@ extern int output_format; > > extern int stop_print_at_null; /* Stop printing at null char? */ > > +extern int print_array_indexes_p (void); > + > +extern void maybe_print_array_index (struct type *index_type, LONGEST index, > + struct ui_file *stream, int format, > + enum val_prettyprint pretty); > + > extern void val_print_array_elements (struct type *, const gdb_byte *, > CORE_ADDR, struct ui_file *, int, > int, int, enum val_prettyprint, > - unsigned int); > + unsigned int, LONGEST); > > extern void val_print_type_code_int (struct type *, const gdb_byte *, > struct ui_file *); > Index: valprint.c > =================================================================== > RCS file: /cvs/src/src/gdb/valprint.c,v > retrieving revision 1.54 > diff -u -p -r1.54 valprint.c > --- valprint.c 10 Jun 2005 06:07:32 -0000 1.54 > +++ valprint.c 7 Sep 2005 20:01:35 -0000 > @@ -100,6 +100,17 @@ Default output radix for printing of val > } > int output_format = 0; > > +/* By default we print arrays without printing the index of each element in > + the array. This behavior can be changed by setting PRINT_ARRAY_INDEXES. */ > + > +static int print_array_indexes = 0; > +static void > +show_print_array_indexes (struct ui_file *file, int from_tty, > + struct cmd_list_element *c, const char *value) > +{ > + fprintf_filtered (file, _("Printing of array indexes is %s.\n"), value); > +} > + > /* Print repeat counts if there are more than this many repetitions of an > element in an array. Referenced by the low level language dependent > print routines. */ > @@ -859,9 +870,41 @@ print_char_chars (struct ui_file *stream > } > } > > +/* Return non-zero if the debugger should print the index of each element > + when printing array values. */ > + > +int > +print_array_indexes_p (void) > +{ > + return print_array_indexes; > +} > + > +/* Print on STREAM using the given FORMAT the index for the element > + at INDEX of an array whose index type is INDEX_TYPE. */ > + > +void > +maybe_print_array_index (struct type *index_type, LONGEST index, > + struct ui_file *stream, int format, > + enum val_prettyprint pretty) > +{ > + struct value *index_value; > + > + if (!print_array_indexes) > + return; > + > + index_value = value_from_longest (index_type, index); > + > + LA_PRINT_ARRAY_INDEX (index_value, stream, format, pretty); > +} > + > /* Called by various _val_print routines to print elements of an > array in the form ", , , ...". > > + Some languages such as Ada allow the user to specify arrays where > + the index of the first element is not zero. REAL_INDEX_OFFSET is > + the user-level index of the first element of the array. For many > + languages such as C or C++, it is always zero. > + > (FIXME?) Assumes array element separator is a comma, which is correct > for all languages currently handled. > (FIXME?) Some languages have a notation for repeated array elements, > @@ -873,11 +916,11 @@ val_print_array_elements (struct type *t > CORE_ADDR address, struct ui_file *stream, > int format, int deref_ref, > int recurse, enum val_prettyprint pretty, > - unsigned int i) > + unsigned int i, LONGEST real_index_offset) > { > unsigned int things_printed = 0; > unsigned len; > - struct type *elttype; > + struct type *elttype, *index_type; > unsigned eltlen; > /* Position of the array element we are examining to see > whether it is repeated. */ > @@ -888,6 +931,7 @@ val_print_array_elements (struct type *t > elttype = TYPE_TARGET_TYPE (type); > eltlen = TYPE_LENGTH (check_typedef (elttype)); > len = TYPE_LENGTH (type) / eltlen; > + index_type = TYPE_INDEX_TYPE (type); > > annotate_array_section_begin (i, elttype); > > @@ -906,6 +950,8 @@ val_print_array_elements (struct type *t > } > } > wrap_here (n_spaces (2 + 2 * recurse)); > + maybe_print_array_index (index_type, i + real_index_offset, > + stream, format, pretty); > > rep1 = i + 1; > reps = 1; > @@ -1396,6 +1442,12 @@ Show the default input and output number > Use 'show input-radix' or 'show output-radix' to independently show each."), > &showlist); > > + add_setshow_boolean_cmd ("array-indexes", class_support, > + &print_array_indexes, _("\ > +Set printing of array indexes."), _("\ > +Show printing of array indexes"), NULL, NULL, show_print_array_indexes, > + &setprintlist, &showprintlist); > + > /* Give people the defaults which they are used to. */ > prettyprint_structs = 0; > prettyprint_arrays = 0; > Index: c-valprint.c > =================================================================== > RCS file: /cvs/src/src/gdb/c-valprint.c,v > retrieving revision 1.37 > diff -u -p -r1.37 c-valprint.c > --- c-valprint.c 9 May 2005 21:20:30 -0000 1.37 > +++ c-valprint.c 7 Sep 2005 19:58:50 -0000 > @@ -133,7 +133,7 @@ c_val_print (struct type *type, const gd > i = 0; > } > val_print_array_elements (type, valaddr + embedded_offset, address, stream, > - format, deref_ref, recurse, pretty, i); > + format, deref_ref, recurse, pretty, i, 0); > fprintf_filtered (stream, "}"); > } > break; > Index: p-valprint.c > =================================================================== > RCS file: /cvs/src/src/gdb/p-valprint.c,v > retrieving revision 1.39 > diff -u -p -r1.39 p-valprint.c > --- p-valprint.c 9 May 2005 21:20:34 -0000 1.39 > +++ p-valprint.c 7 Sep 2005 20:00:37 -0000 > @@ -123,7 +123,7 @@ pascal_val_print (struct type *type, con > i = 0; > } > val_print_array_elements (type, valaddr + embedded_offset, address, stream, > - format, deref_ref, recurse, pretty, i); > + format, deref_ref, recurse, pretty, i, 0); > fprintf_filtered (stream, "}"); > } > break; > Index: ada-valprint.c > =================================================================== > RCS file: /cvs/src/src/gdb/ada-valprint.c,v > retrieving revision 1.23 > diff -u -p -r1.23 ada-valprint.c > --- ada-valprint.c 9 May 2005 21:20:30 -0000 1.23 > +++ ada-valprint.c 7 Sep 2005 19:58:33 -0000 > @@ -75,6 +75,44 @@ adjust_type_signedness (struct type *typ > TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED; > } > > +/* Assuming TYPE is a simple, non-empty array type, compute the lower > + bound and the array index type. Save the low bound into LOW_BOUND > + if not NULL. Save the index type in INDEX_TYPE if not NULL. > + > + Return 1 if the operation was successful. Return zero otherwise, > + in which case the value of LOW_BOUND and INDEX_TYPE is undefined. */ > + > +static int > +ada_get_array_low_bound_and_type (struct type *type, > + long *low_bound, > + struct type **index_type) > +{ > + struct type *index = TYPE_INDEX_TYPE (type); > + long low = 0; > + > + if (index == NULL) > + return 0; > + > + if (TYPE_CODE (index) != TYPE_CODE_RANGE > + && TYPE_CODE (index) != TYPE_CODE_ENUM) > + return 0; > + > + low = TYPE_LOW_BOUND (index); > + if (low > TYPE_HIGH_BOUND (index)) > + return 0; > + > + if (TYPE_CODE (index) == TYPE_CODE_RANGE) > + index = TYPE_TARGET_TYPE (index); > + > + if (low_bound) > + *low_bound = low; > + > + if (index_type) > + *index_type = index; > + > + return 1; > +} > + > /* Assuming TYPE is a simple, non-empty array type, prints its lower bound > on STREAM, if non-standard (i.e., other than 1 for numbers, other > than lower bound of index type for enumerated type). Returns 1 > @@ -86,19 +124,10 @@ print_optional_low_bound (struct ui_file > struct type *index_type; > long low_bound; > > - index_type = TYPE_INDEX_TYPE (type); > - low_bound = 0; > - > - if (index_type == NULL) > + if (print_array_indexes_p ()) > return 0; > - if (TYPE_CODE (index_type) == TYPE_CODE_RANGE) > - { > - low_bound = TYPE_LOW_BOUND (index_type); > - if (low_bound > TYPE_HIGH_BOUND (index_type)) > - return 0; > - index_type = TYPE_TARGET_TYPE (index_type); > - } > - else > + > + if (!ada_get_array_low_bound_and_type (type, &low_bound, &index_type)) > return 0; > > switch (TYPE_CODE (index_type)) > @@ -137,16 +166,18 @@ val_print_packed_array_elements (struct > unsigned int i; > unsigned int things_printed = 0; > unsigned len; > - struct type *elttype; > + struct type *elttype, *index_type; > unsigned eltlen; > unsigned long bitsize = TYPE_FIELD_BITSIZE (type, 0); > struct value *mark = value_mark (); > + LONGEST low = 0; > > elttype = TYPE_TARGET_TYPE (type); > eltlen = TYPE_LENGTH (check_typedef (elttype)); > + index_type = TYPE_INDEX_TYPE (type); > > { > - LONGEST low, high; > + LONGEST high; > if (get_discrete_bounds (TYPE_FIELD_TYPE (type, 0), &low, &high) < 0) > len = 1; > else > @@ -174,6 +205,7 @@ val_print_packed_array_elements (struct > } > } > wrap_here (n_spaces (2 + 2 * recurse)); > + maybe_print_array_index (index_type, i + low, stream, format, pretty); > > i0 = i; > v0 = ada_value_primitive_packed_val (NULL, valaddr, > @@ -219,6 +251,8 @@ val_print_packed_array_elements (struct > fprintf_filtered (stream, ", "); > } > wrap_here (n_spaces (2 + 2 * recurse)); > + maybe_print_array_index (index_type, j + low, > + stream, format, pretty); > } > val_print (elttype, value_contents (v0), 0, 0, stream, format, > 0, recurse + 1, pretty); > @@ -824,7 +858,11 @@ ada_val_print_1 (struct type *type, cons > } > else > { > + long low_bound = 0; > + > len = 0; > + ada_get_array_low_bound_and_type (type, &low_bound, NULL); > + > fprintf_filtered (stream, "("); > print_optional_low_bound (stream, type); > if (TYPE_FIELD_BITSIZE (type, 0) > 0) > @@ -833,7 +871,7 @@ ada_val_print_1 (struct type *type, cons > else > val_print_array_elements (type, valaddr, address, stream, > format, deref_ref, recurse, > - pretty, 0); > + pretty, 0, low_bound); > fprintf_filtered (stream, ")"); > } > gdb_flush (stream); -- Joel