[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--