This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFC: Allow field completion for pascal language


  I wrote this patch to get correct field completion
for pascal language.
  As pascal maintainer, I could have simply 
committed that change (I verified that it introduced
no testsuite regression), but as
I am not that familiar with the parser and completion
code in general, I wanted to submit it for review first.

  I tried to adapt c-exp.y specific code using the 
COMPLETE token to p-exp.y.
  The things are in fact a little easier in pascal
as only '.' can be found before a union/struct field
(named records, objects or classes in pascal language).

  If nobody has any remarks on that code,
I plan to commit it in a few days, but I would
of course welcome any comment.

  This modification is probably also doable in other language
parsers... But I will not do that.

Pierre Muller
GDB pascal language maintainer



2011-01-12  Pierre Muller  <muller@ics.u-strasbg.fr>

	* p-exp.y (intvar): New static variable, used to set CURRENT_TYPE
	for internal variables.
	(last_was_structop): New static variable.
	(COMPLETE): New token.
	(field_exp): New rule to group all '.' suffix handling.
	Add mark_struct_expression calls when approriate to be able
	to correctly find fields for completion.
	(yylex): Adapt to handle field completion and set INTVAR when 
	required.

Index: src/gdb/p-exp.y
===================================================================
RCS file: /cvs/src/src/gdb/p-exp.y,v
retrieving revision 1.53
diff -u -p -r1.53 p-exp.y
--- src/gdb/p-exp.y	10 Jan 2011 20:38:49 -0000	1.53
+++ src/gdb/p-exp.y	12 Jan 2011 14:33:45 -0000
@@ -158,10 +158,12 @@ static int
 parse_number (char *, int, int, YYSTYPE *);
 
 static struct type *current_type;
+static struct internalvar *intvar;
 static int leftdiv_is_integer;
 static void push_current_type (void);
 static void pop_current_type (void);
 static int search_field;
+
 %}
 
 %type <voidval> exp exp1 type_exp start normal_start variable
qualified_name
@@ -184,6 +186,7 @@ static int search_field;
 
 %token <sval> STRING 
 %token <sval> FIELDNAME
+%token <voidval> COMPLETE
 %token <ssym> NAME /* BLOCKNAME defined below to give it higher precedence.
*/
 %token <tsym> TYPENAME
 %type <sval> name
@@ -233,6 +236,7 @@ static int search_field;
 %%
 
 start   :	{ current_type = NULL;
+		  intvar = NULL;
 		  search_field = 0;
 		  leftdiv_is_integer = 0;
 		}
@@ -285,19 +289,56 @@ exp	:	DECREMENT  '(' exp ')'   %prec UNA
 			{ write_exp_elt_opcode (UNOP_PREDECREMENT); }
 	;
 
-exp	:	exp '.' { search_field = 1; } 
-		FIELDNAME 
-		/* name */
+
+field_exp	:	exp '.'	%prec UNARY
+			{ search_field = 1; } 
+	;
+
+exp	:	field_exp FIELDNAME 
 			{ write_exp_elt_opcode (STRUCTOP_STRUCT);
-			  write_exp_string ($4); 
+			  write_exp_string ($2); 
 			  write_exp_elt_opcode (STRUCTOP_STRUCT);
 			  search_field = 0; 
 			  if (current_type)
-			    { while (TYPE_CODE (current_type) ==
TYPE_CODE_PTR)
-				current_type = TYPE_TARGET_TYPE
(current_type);
+			    { 
+			      while (TYPE_CODE (current_type)
+				     == TYPE_CODE_PTR)
+				current_type =
+				  TYPE_TARGET_TYPE (current_type);
 			      current_type = lookup_struct_elt_type (
-				current_type, $4.ptr, 0); };
-			 } ; 
+				current_type, $2.ptr, 0);
+			    }
+			 }
+	; 
+
+exp	:	field_exp name
+			{ mark_struct_expression ();
+			  write_exp_elt_opcode (STRUCTOP_STRUCT);
+			  write_exp_string ($2);
+			  write_exp_elt_opcode (STRUCTOP_STRUCT);
+			  search_field = 0; 
+			  if (current_type)
+			    { 
+			      while (TYPE_CODE (current_type)
+				     == TYPE_CODE_PTR)
+				current_type =
+				  TYPE_TARGET_TYPE (current_type);
+			      current_type = lookup_struct_elt_type (
+				current_type, $2.ptr, 0);
+			    }
+			}
+	;
+
+exp	:	field_exp COMPLETE
+			{ struct stoken s;
+			  mark_struct_expression ();
+			  write_exp_elt_opcode (STRUCTOP_STRUCT);
+			  s.ptr = "";
+			  s.length = 0;
+			  write_exp_string (s);
+			  write_exp_elt_opcode (STRUCTOP_STRUCT); }
+	;
+
 exp	:	exp '['
 			/* We need to save the current_type value.  */
 			{ char *arrayname; 
@@ -516,8 +557,19 @@ exp	:	variable
 	;
 
 exp	:	VARIABLE
-			/* Already written by write_dollar_variable.  */
-	;
+			/* Already written by write_dollar_variable.
+			   Handle current_type.  */
+ 			{  if (intvar) {
+ 			     struct value * val, * mark;
+
+			     mark = value_mark ();
+ 			     val = value_of_internalvar (parse_gdbarch,
+ 							 intvar);
+ 			     current_type = value_type (val);
+			     value_release_to_mark (mark);
+ 			   }
+ 			}
+ 	;
 
 exp	:	SIZEOF '(' type ')'	%prec UNARY
 			{ write_exp_elt_opcode (OP_LONG);
@@ -1060,8 +1112,13 @@ static char * uptok (tokstart, namelen)
   uptokstart[namelen]='\0';
   return uptokstart;
 }
-/* Read one token, getting characters through lexptr.  */
 
+/* This is set if the previously-returned token was a structure
+   operator  '.'.  This is used only when parsing to
+   do field name completion.  */
+static int last_was_structop;
+
+/* Read one token, getting characters through lexptr.  */
 
 static int
 yylex ()
@@ -1075,7 +1132,9 @@ yylex ()
   int explen, tempbufindex;
   static char *tempbuf;
   static int tempbufsize;
-
+  int saw_structop = last_was_structop;
+ 
+  last_was_structop = 0;
  retry:
 
   prev_lexptr = lexptr;
@@ -1111,7 +1170,10 @@ yylex ()
   switch (c = *tokstart)
     {
     case 0:
-      return 0;
+      if (saw_structop && search_field)
+	return COMPLETE;
+      else
+       return 0;
 
     case ' ':
     case '\t':
@@ -1172,7 +1234,12 @@ yylex ()
     case '.':
       /* Might be a floating point number.  */
       if (lexptr[1] < '0' || lexptr[1] > '9')
-	goto symbol;		/* Nope, must be a symbol.  */
+	{
+	  if (in_parse_field)
+	    last_was_structop = 1;
+	  goto symbol;		/* Nope, must be a symbol.  */
+	}
+
       /* FALL THRU into number case.  */
 
     case '0':
@@ -1430,11 +1497,17 @@ yylex ()
 
   if (*tokstart == '$')
     {
+      char c;
       /* $ is the normal prefix for pascal hexadecimal values
         but this conflicts with the GDB use for debugger variables
         so in expression to enter hexadecimal values
         we still need to use C syntax with 0xff  */
       write_dollar_variable (yylval.sval);
+      c = tokstart[namelen];
+      tokstart[namelen] = 0;
+      intvar = lookup_only_internalvar (++tokstart);
+      --tokstart;
+      tokstart[namelen] = c;
       free (uptokstart);
       return VARIABLE;
     }
@@ -1454,7 +1527,7 @@ yylex ()
 
     if (search_field && current_type)
       is_a_field = (lookup_struct_elt_type (current_type, tmp, 1) != NULL);
-    if (is_a_field)
+    if (is_a_field || in_parse_field)
       sym = NULL;
     else
       sym = lookup_symbol (tmp, expression_context_block,
@@ -1469,7 +1542,7 @@ yylex ()
          }
        if (search_field && current_type)
 	 is_a_field = (lookup_struct_elt_type (current_type, tmp, 1) !=
NULL);
-       if (is_a_field)
+       if (is_a_field || in_parse_field)
 	 sym = NULL;
        else
 	 sym = lookup_symbol (tmp, expression_context_block,
@@ -1497,7 +1570,7 @@ yylex ()
           }
        if (search_field && current_type)
 	 is_a_field = (lookup_struct_elt_type (current_type, tmp, 1) !=
NULL);
-       if (is_a_field)
+       if (is_a_field || in_parse_field)
 	 sym = NULL;
        else
 	 sym = lookup_symbol (tmp, expression_context_block,


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]