[gvd-devel] Bug in GVD-1.2.4 handling templates and empty structures
Sergey Koshcheyev
serko84@hotmail.com, serko84@hotmail.com
Fri, 08 Feb 2002 00:27:16 +0100
This is a multi-part message in MIME format.
--------------070105060306070707020809
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit
Hi!
I have noticed a bug in gvd-1.2.4 that is related to handling of gdb 5.1
output for empty structures and parsing of output for C++ templates. The
first problem is that gdb 5.1 prints "{<No data members>}" instead of
just "{}" for empty structures. The second problem is that GVD's parsing
code doesn't handle template parameters in declarations.
My fix for these bugs is attached and contains a new procedure
String_Utils.Skip_To_Match which will skip over matching delimiters.
This procedure is then used in several places in Debugger.Gdb.C and
Debugger.Gdb.Cpp.
Sergey Koshcheyev.
--------------070105060306070707020809
Content-Type: text/plain;
name="patch-gvd-1.2.4-templates-gdb5.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="patch-gvd-1.2.4-templates-gdb5.diff"
diff -ruN gvd-1.2.4-src/common/string_utils.adb gvd-1.2.4-sergey/common/string_utils.adb
--- gvd-1.2.4-src/common/string_utils.adb Mon Nov 26 17:17:38 2001
+++ gvd-1.2.4-sergey/common/string_utils.adb Thu Feb 7 22:34:34 2002
@@ -120,6 +120,37 @@
end loop;
end Skip_To_String;
+ -------------------
+ -- Skip_Matching --
+ -------------------
+
+ procedure Skip_Matching
+ (Type_Str : String;
+ Index : in out Natural;
+ Opening : Character;
+ Closing : Character)
+ is
+ Nesting_Level : Natural := 0;
+
+ -- To catch out-of-bounds access or too many closing delimiters
+ pragma Unsuppress (Range_Check, On => Nesting_Level);
+ pragma Unsuppress (Index_Check, On => Type_Str);
+
+ begin
+ pragma Assert (Type_Str (Index) = Opening);
+
+ loop
+ if Type_Str (Index) = Opening then
+ Nesting_Level := Nesting_Level + 1;
+ elsif Type_Str (Index) = Closing then
+ Nesting_Level := Nesting_Level - 1;
+ end if;
+
+ Index := Index + 1;
+ exit when Nesting_Level = 0;
+ end loop;
+ end Skip_Matching;
+
---------------
-- Parse_Num --
---------------
diff -ruN gvd-1.2.4-src/common/string_utils.ads gvd-1.2.4-sergey/common/string_utils.ads
--- gvd-1.2.4-src/common/string_utils.ads Mon Nov 26 17:17:38 2001
+++ gvd-1.2.4-sergey/common/string_utils.ads Thu Feb 7 21:48:07 2002
@@ -58,6 +58,15 @@
-- Skip every character until an occurence of Substring is found.
-- Index is set to the first character of the occurence.
+ procedure Skip_Matching
+ (Type_Str : String;
+ Index : in out Natural;
+ Opening : Character;
+ Closing : Character);
+ -- Skip to the Closing character that matches the Opening one, handling
+ -- nested occurences correctly. For example, to skip from '{' to
+ -- matching '}', use Skip_To_Matching (Type_Str, Index, '{', '}');
+
procedure Skip_Word
(Type_Str : String;
Index : in out Natural;
diff -ruN gvd-1.2.4-src/gvd/debugger-gdb-c.adb gvd-1.2.4-sergey/gvd/debugger-gdb-c.adb
--- gvd-1.2.4-src/gvd/debugger-gdb-c.adb Mon Nov 26 17:17:48 2001
+++ gvd-1.2.4-sergey/gvd/debugger-gdb-c.adb Thu Feb 7 22:44:07 2002
@@ -178,19 +178,7 @@
-- Begin of union or struct => skip to the end
elsif Type_Str (Index) = '{' then
- declare
- Num : Natural := 1;
- begin
- Index := Index + 1;
- while Num /= 0 loop
- if Type_Str (Index) = '}' then
- Num := Num - 1;
- elsif Type_Str (Index) = '{' then
- Num := Num + 1;
- end if;
- Index := Index + 1;
- end loop;
- end;
+ Skip_Matching (Type_Str, Index, '{', '}');
-- Access to subprogram
elsif Type_Str (Index) = '(' then
@@ -284,7 +272,7 @@
case Type_Str (Index) is
when '<' =>
-- Simple types, like <4-byte integer> and <4-byte float>
- Skip_To_Char (Type_Str, Index, '>');
+ Skip_Matching (Type_Str, Index, '<', '>');
Result := New_Simple_Type;
Set_Type_Name (Result, Type_Str (Tmp .. Index));
Index := Index + 1;
@@ -565,7 +553,8 @@
if Looking_At (Type_Str, Tmp, "struct {")
or else Looking_At (Type_Str, Tmp, "union {")
then
- Skip_To_Char (Type_Str, Tmp, '}');
+ Skip_To_Char (Type_Str, Tmp, '{');
+ Skip_Matching (Type_Str, Tmp, '{', '}');
end if;
Skip_To_Char (Type_Str, Tmp, ';');
@@ -670,8 +659,10 @@
loop
-- embedded unions or structs
if Type_Str (Index) = '{' then
- Skip_To_Char (Type_Str, Index, '}');
-
+ Skip_Matching (Type_Str, Index, '{', '}');
+ elsif Type_Str (Index) = '<' then
+ Skip_Matching (Type_Str, Index, '<', '>');
+ Index := Index - 1; -- the '>' will be skipped below
elsif Type_Str (Index) = ';' then
Num_Fields := Num_Fields + 1;
end if;
diff -ruN gvd-1.2.4-src/gvd/debugger-gdb-cpp.adb gvd-1.2.4-sergey/gvd/debugger-gdb-cpp.adb
--- gvd-1.2.4-src/gvd/debugger-gdb-cpp.adb Mon Nov 26 17:17:48 2001
+++ gvd-1.2.4-sergey/gvd/debugger-gdb-cpp.adb Thu Feb 7 23:18:36 2002
@@ -69,6 +69,7 @@
Result : out Generic_Type_Access);
-- Parse the contents of a class/union in C++ (ie the part after '{'
-- Index should point to the character after '{'
+
--------------------
-- Is_Simple_Type --
--------------------
@@ -251,10 +252,15 @@
Index := Index + 1;
end if;
+ if Looking_At (Type_Str, Index, "<No data fields>") then
+ Index := Index + 16; -- skips "<No data fields>"
+ end if;
+
-- Parse the ancestors
while Type_Str (Index) = '<' loop
- Skip_To_Char (Type_Str, Index, '>');
- Index := Index + 5; -- skips "> = "
+ Skip_Matching (Type_Str, Index, '<', '>');
+
+ Index := Index + 4; -- skips " = "
V := Get_Ancestor (Class_Type (Result.all), Ancestor);
Parse_Value (Lang, Type_Str, Index, V, Repeat_Num);
pragma Assert (Looking_At (Type_Str, Index, ", "));
@@ -417,7 +423,7 @@
Num_Ancestors : Natural := 0;
Tmp : Natural := Index;
Ancestor : Natural := 1;
- Ancestor_Start : Natural;
+ Ancestor_Start : Natural;
Child : Generic_Type_Access;
begin
@@ -426,6 +432,12 @@
-- Count the number of ancestors
while Type_Str (Tmp) /= '{' loop
+
+ -- Skip template parameters
+ if Type_Str (Tmp) = '<' then
+ Skip_Matching (Type_Str, Tmp, '<', '>');
+ end if;
+
if Type_Str (Tmp) = ':' or else Type_Str (Tmp) = ',' then
Num_Ancestors := Num_Ancestors + 1;
end if;
@@ -475,6 +487,8 @@
Ancestor_Start := Tmp;
+ elsif Type_Str (Tmp) = '<' then
+ Skip_Matching (Type_Str, Tmp, '<', '>');
else
Tmp := Tmp + 1;
end if;
--------------070105060306070707020809--