- register struct symbol *sym;
- /* The symtab that SYM was found in. */
- struct symtab *sym_symtab;
-
- register CORE_ADDR pc;
- register struct minimal_symbol *msymbol;
- char *copy;
- struct symbol *sym_class;
- int i1;
- int is_quoted, has_parens;
- struct symbol **sym_arr;
- struct type *t;
- char *saved_arg = *argptr;
- extern char *gdb_completer_quote_characters;
-
- INIT_SAL (&val); /* initialize to zeroes */
-
- /* Defaults have defaults. */
-
- if (default_symtab == 0)
- {
- default_symtab = current_source_symtab;
- default_line = current_source_line;
- }
-
- /* See if arg is *PC */
-
- if (**argptr == '*')
- {
- (*argptr)++;
- pc = parse_and_eval_address_1 (argptr);
- values.sals = (struct symtab_and_line *)
- xmalloc (sizeof (struct symtab_and_line));
- values.nelts = 1;
- values.sals[0] = find_pc_line (pc, 0);
- values.sals[0].pc = pc;
- return values;
- }
-
- /* Maybe arg is FILE : LINENUM or FILE : FUNCTION */
-
- s = NULL;
- is_quoted = (**argptr
- && strchr (gdb_completer_quote_characters, **argptr) != NULL);
- has_parens = ((pp = strchr (*argptr, '(')) != NULL
- && (pp = strchr (pp, ')')) != NULL);
-
- for (p = *argptr; *p; p++)
- {
- if (p[0] == '<')
- {
- while(++p && *p != '>');
- if (!p)
- {
- error ("non-matching '<' and '>' in command");
- }
- }
- if (p[0] == ':' || p[0] == ' ' || p[0] == '\t')
- break;
- if (p[0] == '.' && strchr (p, ':') == NULL) /* Java qualified method. */
- {
- /* Find the *last* '.', since the others are package qualifiers. */
- for (p1 = p; *p1; p1++)
- {
- if (*p1 == '.')
- p = p1;
- }
- break;
- }
- }
- while (p[0] == ' ' || p[0] == '\t') p++;
-
- if ((p[0] == ':' || p[0] == '.') && !has_parens)
- {
-
- /* C++ or Java */
- if (is_quoted) *argptr = *argptr+1;
- if (p[0] == '.' || p[1] ==':')
- {
- /* Extract the class name. */
- p1 = p;
- while (p != *argptr && p[-1] == ' ') --p;
- copy = (char *) alloca (p - *argptr + 1);
- memcpy (copy, *argptr, p - *argptr);
- copy[p - *argptr] = 0;
-
- /* Discard the class name from the arg. */
- p = p1 + (p1[0] == ':' ? 2 : 1);
- while (*p == ' ' || *p == '\t') p++;
- *argptr = p;
-
- sym_class = lookup_symbol (copy, 0, STRUCT_NAMESPACE, 0,
- (struct symtab **)NULL);
-
- if (sym_class &&
- (t = check_typedef (SYMBOL_TYPE (sym_class)),
- (TYPE_CODE (t) == TYPE_CODE_STRUCT
- || TYPE_CODE (t) == TYPE_CODE_UNION)))
- {
- /* Arg token is not digits => try it as a function name
- Find the next token(everything up to end or next blank). */
- if (**argptr
- && strchr (gdb_completer_quote_characters, **argptr) != NULL)
- {
- p = skip_quoted(*argptr);
- *argptr = *argptr + 1;
- }
- else
- {
- p = *argptr;
- while (*p && *p!=' ' && *p!='\t' && *p!=',' && *p!=':') p++;
- }
-/*
- q = operator_chars (*argptr, &q1);
- if (q1 - q)
- {
- char *opname;
- char *tmp = alloca (q1 - q + 1);
- memcpy (tmp, q, q1 - q);
- tmp[q1 - q] = '\0';
- opname = cplus_mangle_opname (tmp, DMGL_ANSI);
- if (opname == NULL)
- {
- error_begin ();
- printf_filtered ("no mangling for \"%s\"\n", tmp);
- cplusplus_hint (saved_arg);
- return_to_top_level (RETURN_ERROR);
- }
- copy = (char*) alloca (3 + strlen(opname));
- sprintf (copy, "__%s", opname);
- p = q1;
- }
- else
-*/
- {
- copy = (char *) alloca (p - *argptr + 1 );
- memcpy (copy, *argptr, p - *argptr);
- copy[p - *argptr] = '\0';
- if (p != *argptr
- && copy[p - *argptr - 1]
- && strchr (gdb_completer_quote_characters,
- copy[p - *argptr - 1]) != NULL)
- copy[p - *argptr - 1] = '\0';
- }
-
- /* no line number may be specified */
- while (*p == ' ' || *p == '\t') p++;
- *argptr = p;
-
- sym = 0;
- i1 = 0; /* counter for the symbol array */
- sym_arr = (struct symbol **) alloca(total_number_of_methods (t)
- * sizeof(struct symbol *));
-
- if (destructor_name_p (copy, t))
- {
- /* Destructors are a special case. */
- int m_index, f_index;
-
- if (get_destructor_fn_field (t, &m_index, &f_index))
- {
- struct fn_field *f = TYPE_FN_FIELDLIST1 (t, m_index);
-
- sym_arr[i1] =
- lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, f_index),
- NULL, VAR_NAMESPACE, (int *) NULL,
- (struct symtab **)NULL);
- if (sym_arr[i1])
- i1++;
- }
- }
- else
- i1 = find_methods (t, copy, sym_arr);
- if (i1 == 1)
- {
- /* There is exactly one field with that name. */
- sym = sym_arr[0];
-
- if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
- {
- values.sals = (struct symtab_and_line *)
- xmalloc (sizeof (struct symtab_and_line));
- values.nelts = 1;
- values.sals[0] = find_function_start_sal (sym,
- funfirstline);
- }
- else
- {
- values.nelts = 0;
- }
- return values;
- }
- if (i1 > 0)
- {
- /* There is more than one field with that name
- (overloaded). Ask the user which one to use. */
- return decode_line_2 (sym_arr, i1, funfirstline, canonical);
- }
- else
- {
- char *tmp;
-
- if (OPNAME_PREFIX_P (copy))
- {
- tmp = (char *)alloca (strlen (copy+3) + 9);
- strcpy (tmp, "operator ");
- strcat (tmp, copy+3);
- }
- else
- tmp = copy;
- error_begin ();
- if (tmp[0] == '~')
- printf_filtered
- ("the class `%s' does not have destructor defined\n",
- SYMBOL_SOURCE_NAME(sym_class));
- else
- printf_filtered
- ("the class %s does not have any method named %s\n",
- SYMBOL_SOURCE_NAME(sym_class), tmp);
- cplusplus_hint (saved_arg);
- return_to_top_level (RETURN_ERROR);
- }
- }
- else
- {
- error_begin ();
- /* The quotes are important if copy is empty. */
- printf_filtered
- ("can't find class, struct, or union named \"%s\"\n", copy);
- cplusplus_hint (saved_arg);
- return_to_top_level (RETURN_ERROR);
- }
- }
- /* end of C++ */
-
-
- /* Extract the file name. */
- p1 = p;
- while (p != *argptr && p[-1] == ' ') --p;
- copy = (char *) alloca (p - *argptr + 1);
- memcpy (copy, *argptr, p - *argptr);
- copy[p - *argptr] = 0;
-
- /* Find that file's data. */
- s = lookup_symtab (copy);
- if (s == 0)
- {
- if (!have_full_symbols () && !have_partial_symbols ())
- error (no_symtab_msg);
- error ("No source file named %s.", copy);
- }
-
- /* Discard the file name from the arg. */
- p = p1 + 1;
- while (*p == ' ' || *p == '\t') p++;
- *argptr = p;
- }
-
- /* S is specified file's symtab, or 0 if no file specified.
- arg no longer contains the file name. */
-
- /* Check whether arg is all digits (and sign) */
-
- q = *argptr;
- if (*q == '-' || *q == '+') q++;
- while (*q >= '0' && *q <= '9')
- q++;
-
- if (q != *argptr && (*q == 0 || *q == ' ' || *q == '\t' || *q == ','))
- {
- /* We found a token consisting of all digits -- at least one digit. */
- enum sign {none, plus, minus} sign = none;
-
- /* We might need a canonical line spec if no file was specified. */
- int need_canonical = (s == 0) ? 1 : 0;
-
- /* This is where we need to make sure that we have good defaults.
- We must guarantee that this section of code is never executed
- when we are called with just a function name, since
- select_source_symtab calls us with such an argument */
-
- if (s == 0 && default_symtab == 0)
- {
- select_source_symtab (0);
- default_symtab = current_source_symtab;
- default_line = current_source_line;
- }
-
- if (**argptr == '+')
- sign = plus, (*argptr)++;
- else if (**argptr == '-')
- sign = minus, (*argptr)++;
- val.line = atoi (*argptr);
- switch (sign)
- {
- case plus:
- if (q == *argptr)
- val.line = 5;
- if (s == 0)
- val.line = default_line + val.line;
- break;
- case minus:
- if (q == *argptr)
- val.line = 15;
- if (s == 0)
- val.line = default_line - val.line;
- else
- val.line = 1;
- break;
- case none:
- break; /* No need to adjust val.line. */
- }
-
- while (*q == ' ' || *q == '\t') q++;
- *argptr = q;
- if (s == 0)
- s = default_symtab;
- val.symtab = s;
- val.pc = 0;
- values.sals = (struct symtab_and_line *)
- xmalloc (sizeof (struct symtab_and_line));
- values.sals[0] = val;
- values.nelts = 1;
- if (need_canonical)
- build_canonical_line_spec (values.sals, NULL, canonical);
- return values;
- }
-
- /* Arg token is not digits => try it as a variable name
- Find the next token (everything up to end or next whitespace). */
-
- if (**argptr == '$') /* Convenience variable */
- p = skip_quoted (*argptr + 1);
- else if (is_quoted)
- {
- p = skip_quoted (*argptr);
- if (p[-1] != '\'')
- error ("Unmatched single quote.");
- }
- else if (has_parens)
- {
- p = pp+1;
- }
- else
- {
- p = skip_quoted(*argptr);
- }
-
- copy = (char *) alloca (p - *argptr + 1);
- memcpy (copy, *argptr, p - *argptr);
- copy[p - *argptr] = '\0';
- if (p != *argptr
- && copy[0]
- && copy[0] == copy [p - *argptr - 1]
- && strchr (gdb_completer_quote_characters, copy[0]) != NULL)
- {
- copy [p - *argptr - 1] = '\0';
- copy++;
- }
- while (*p == ' ' || *p == '\t') p++;
- *argptr = p;
-
- /* See if it's a convenience variable */
-
- if (*copy == '$')
- {
- value_ptr valx;
- int need_canonical = (s == 0) ? 1 : 0;
-
- valx = value_of_internalvar (lookup_internalvar (copy + 1));
- if (TYPE_CODE (VALUE_TYPE (valx)) != TYPE_CODE_INT)
- error ("Convenience variables used in line specs must have integer values.");
-
- val.symtab = s ? s : default_symtab;
- val.line = value_as_long (valx);
- val.pc = 0;
-
- values.sals = (struct symtab_and_line *)xmalloc (sizeof val);
- values.sals[0] = val;
- values.nelts = 1;
-
- if (need_canonical)
- build_canonical_line_spec (values.sals, NULL, canonical);
-
- return values;
- }
-
-
- /* Look up that token as a variable.
- If file specified, use that file's per-file block to start with. */
-
- sym = lookup_symbol (copy,
- (s ? BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK)
- : get_selected_block ()),
- VAR_NAMESPACE, 0, &sym_symtab);
-
- if (sym != NULL)