Re: [RFA] Add ObjC recognition to linespec.c [5/5]

Michael Snyder
2003-01-04T01:32:59Z

Adam Fedor wrote:
>
> I know that linespec has been changing a lot lately, and I'm not sure if
> it's finished changing yet. So this is my attempt to insert ObjC
> handling into linespec. Actually Klee Dienes really did most of these
> changes, and I probably bastardized those as well...
>
> -------------------------------------------------------------------------------
> 2003-01-03 Adam Fedor <fedor@gnu.org>
>
> * linespec.c (decode_objc): New function to decode ObjC calls
> (decode_line_1): Check for ObjC calls (using decode_objc)
>
> Index: linespec.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/linespec.c,v
> retrieving revision 1.32
> diff -u -p -r1.32 linespec.c
> --- linespec.c 19 Dec 2002 18:56:14 -0000 1.32
> +++ linespec.c 3 Jan 2003 22:56:54 -0000
> @@ -37,6 +37,11 @@
>
> extern char *operator_chars (char *, char **);
>
> +/* From objc-lang.h. Included here to avoid conflict with other prototypes */
> +extern char *find_imps (struct symtab *symtab, struct block *block,
> + char *method, struct symbol **syms, unsigned int *nsym,
> + unsigned int *ndebug);
> +

I presume this will go away when you can include objc-lang.h.

> /* Prototypes for local functions */
>
> static void initialize_defaults (struct symtab **default_symtab,
> @@ -48,6 +53,12 @@ static struct symtabs_and_lines decode_i
>
> static char *locate_first_half (char **argptr, int *is_quote_enclosed);
>
> +static struct symtabs_and_lines decode_objc (char **argptr,
> + int funfirstline,
> + struct symtab *file_symtab,
> + char ***canonical,
> + char *saved_arg);
> +

I like this -- presumably it keeps a lot of the new code
out of poor old decrepit decode_line_1.

> static struct symtabs_and_lines decode_compound (char **argptr,
> int funfirstline,
> char ***canonical,
> @@ -568,6 +579,7 @@ decode_line_1 (char **argptr, int funfir
> int is_quoted;
> /* Is part of *ARGPTR is enclosed in double quotes? */
> int is_quote_enclosed;
> + int is_objc_method = 0;
> char *saved_arg = *argptr;
>
> init_sal (&val); /* initialize to zeroes */
> @@ -596,6 +608,24 @@ decode_line_1 (char **argptr, int funfir
>
> p = locate_first_half (argptr, &is_quote_enclosed);
>
> + /* Check if this is an Objective-C method. */
> + if (*p && (p[0] == ':') && (strchr ("+-", p[1]) != NULL)
> + && (p[2] == '['))
> + {
> + is_objc_method = 1;
> + paren_pointer = NULL; /* Probably just a category name. Ignore it */
> + }
> +
> + /* Is it an Objective-C selector? */
> +
> + {
> + struct symtabs_and_lines values;
> + values = decode_objc (argptr, funfirstline, NULL,
> + canonical, saved_arg);
> + if (values.sals != NULL)
> + return values;
> + }

Was this meant to be an if? It seems to be a naked block.
I'd feel better if there was an if around it, eg. is there
a simple way to test for a selector name? Do I remember
that they begin with a unique prefix such as '@'?

> +
> /* Does it look like there actually were two parts? */
>
> if ((p[0] == ':' || p[0] == '.') && paren_pointer == NULL)
> @@ -669,13 +699,21 @@ decode_line_1 (char **argptr, int funfir
> Find the next token (everything up to end or next whitespace). */
>
> if (**argptr == '$') /* May be a convenience variable */
> - p = skip_quoted (*argptr + (((*argptr)[1] == '$') ? 2 : 1)); /* One or two $ chars possible */
> + {
> + /* One or two $ chars possible */
> + p = skip_quoted (*argptr + (((*argptr)[1] == '$') ? 2 : 1));
> + }
> else if (is_quoted)
> {
> p = skip_quoted (*argptr);
> if (p[-1] != '\'')
> error ("Unmatched single quote.");
> }
> + else if (is_objc_method)
> + {
> + /* allow word separators in method names for Obj-C */
> + p = skip_quoted_chars (*argptr, NULL, "");
> + }

OK, except didn't we decide that "skip_quoted_chars" needs a
better name? One that identifies it with objc?

> else if (paren_pointer != NULL)
> {
> p = paren_pointer + 1;
> @@ -952,6 +990,13 @@ locate_first_half (char **argptr, int *i
> error ("malformed template specification in command");
> p = temp_end;
> }
> + /* Check for a colon and a plus or minus and a [ (which
> + indicates an Objective-C method) */
> + if (*p && (p[0] == ':') && (strchr ("+-", p[1]) != NULL)
> + && (p[2] == '['))
> + {
> + break;
> + }
> /* Check for the end of the first half of the linespec. End of line,
> a tab, a double colon or the last single colon, or a space. But
> if enclosed in double quotes we do not break on enclosed spaces */
> @@ -993,6 +1038,98 @@ locate_first_half (char **argptr, int *i
> }
>
>
> +
> +struct symtabs_and_lines
> +decode_objc (char **argptr, int funfirstline, struct symtab *file_symtab,
> + char ***canonical, char *saved_arg)
> +{
> + /* here's where we recognise an Objective-C Selector. An
> + * Objective C selector may be implemented by more than one
> + * class, therefore it may represent more than one
> + * method/function. This gives us a situation somewhat
> + * analogous to C++ overloading. If there's more than one
> + * method that could represent the selector, then use some of
> + * the existing C++ code to let the user choose one.
> + */
> +
> + struct symtabs_and_lines values;
> + struct symbol **sym_arr = NULL;
> + struct symbol *sym = NULL;
> + char *copy = NULL;
> + struct block *block = NULL;
> + int i1 = 0;
> + int i2 = 0;
> +
> + values.sals = NULL;
> + values.nelts = 0;
> +
> + if (file_symtab != NULL)
> + block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (file_symtab), STATIC_BLOCK);
> + else
> + block = get_selected_block (0);
> +
> + copy = find_imps (file_symtab, block, *argptr, NULL, &i1, &i2);
> +
> + if (i1 > 0)
> + {
> + sym_arr = (struct symbol **) alloca ((i1 + 1) * sizeof (struct symbol *));
> + sym_arr[i1] = 0;
> +
> + copy = find_imps (file_symtab, block, *argptr, sym_arr, &i1, &i2);
> + *argptr = copy;
> + }
> +
> + /* i1 now represents the TOTAL number of matches found...
> + i2 represents how many HIGH-LEVEL (struct symbol) matches,
> + which will come first in the sym_arr array. Any low-level
> + (minimal_symbol) matches will follow those. */
> +
> + if (i1 == 1)
> + {
> + if (i2 > 0)
> + {
> + /* already a struct symbol */
> + sym = sym_arr[0];
> + }
> + else
> + {
> + sym = find_pc_function (SYMBOL_VALUE_ADDRESS (sym_arr[0]));
> + if ((sym != NULL) && strcmp (SYMBOL_NAME (sym_arr[0]), SYMBOL_NAME (sym)) != 0)
> + {
> + warning ("debugging symbol \"%s\" does not match selector; ignoring", SYMBOL_NAME (sym));
> + sym = NULL;
> + }
> + }
> +
> + values.sals = (struct symtab_and_line *) xmalloc (sizeof (struct symtab_and_line));
> + values.nelts = 1;
> +
> + if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
> + {
> + /* canonicalize this, so it remains resolved for dylib loads */
> + values.sals[0] = find_function_start_sal (sym, funfirstline);
> + build_canonical_line_spec (values.sals, SYMBOL_SOURCE_NAME (sym), canonical);
> + }
> + else
> + {
> + /* the only match was a non-debuggable symbol */
> + values.sals[0].symtab = 0;
> + values.sals[0].line = 0;
> + values.sals[0].end = 0;
> + values.sals[0].pc = SYMBOL_VALUE_ADDRESS (sym_arr[0]);
> + }
> + return values;
> + }
> +
> + if (i1 > 1)
> + {
> + /* more than one match -- user must choose one or more */
> + return decode_line_2 (sym_arr, i2, funfirstline, canonical);
> + //return select_symbols (sym_arr, i1, i2, funfirstline, canonical);
> + }
> +
> + return values;
> +}
>
> /* This handles C++ and Java compound data structures. P should point
> at the first component separator, i.e. double-colon or period. */