- FUNCTION may be an undebuggable function found in minimal symbol table.
-
- If the argument FUNFIRSTLINE is nonzero, we want the first line
- of real code inside a function when a function is specified, and it is
- not OK to specify a variable or type to get its line number.
-
- DEFAULT_SYMTAB specifies the file to use if none is specified.
- It defaults to current_source_symtab.
- DEFAULT_LINE specifies the line number to use for relative
- line numbers (that start with signs). Defaults to current_source_line.
- If CANONICAL is non-NULL, store an array of strings containing the canonical
- line specs there if necessary. Currently overloaded member functions and
- line numbers or static functions without a filename yield a canonical
- line spec. The array and the line spec strings are allocated on the heap,
- it is the callers responsibility to free them.
-
- Note that it is possible to return zero for the symtab
- if no file is validly specified. Callers must check that.
- Also, the line number returned may be invalid. */
-
-/* We allow single quotes in various places. This is a hideous
- kludge, which exists because the completer can't yet deal with the
- lack of single quotes. FIXME: write a linespec_completer which we
- can use as appropriate instead of make_symbol_completion_list. */
-
-struct symtabs_and_lines
-decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical)
- char **argptr;
- int funfirstline;
- struct symtab *default_symtab;
- int default_line;
- char ***canonical;
-{
- struct symtabs_and_lines values;
-#ifdef HPPA_COMPILER_BUG
- /* FIXME: The native HP 9000/700 compiler has a bug which appears
- when optimizing this file with target i960-vxworks. I haven't
- been able to construct a simple test case. The problem is that
- in the second call to SKIP_PROLOGUE below, the compiler somehow
- does not realize that the statement val = find_pc_line (...) will
- change the values of the fields of val. It extracts the elements
- into registers at the top of the block, and does not update the
- registers after the call to find_pc_line. You can check this by
- inserting a printf at the end of find_pc_line to show what values
- it is returning for val.pc and val.end and another printf after
- the call to see what values the function actually got (remember,
- this is compiling with cc -O, with this patch removed). You can
- also examine the assembly listing: search for the second call to
- skip_prologue; the LDO statement before the next call to
- find_pc_line loads the address of the structure which
- find_pc_line will return; if there is a LDW just before the LDO,
- which fetches an element of the structure, then the compiler
- still has the bug.
-
- Setting val to volatile avoids the problem. We must undef
- volatile, because the HPPA native compiler does not define
- __STDC__, although it does understand volatile, and so volatile
- will have been defined away in defs.h. */
-#undef volatile
- volatile struct symtab_and_line val;
-#define volatile /*nothing*/
-#else
- struct symtab_and_line val;
-#endif
- register char *p, *p1;
- char *q, *pp;
-#if 0
- char *q1;
-#endif
- register struct symtab *s;
-
- 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);
- 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)
- {
- if (SYMBOL_CLASS (sym) == LOC_BLOCK)
- {
- /* Arg is the name of a function */
- values.sals = (struct symtab_and_line *)
- xmalloc (sizeof (struct symtab_and_line));
- values.sals[0] = find_function_start_sal (sym, funfirstline);
- values.nelts = 1;
-
- /* Don't use the SYMBOL_LINE; if used at all it points to
- the line containing the parameters or thereabouts, not
- the first line of code. */
-
- /* We might need a canonical line spec if it is a static
- function. */
- if (s == 0)
- {
- struct blockvector *bv = BLOCKVECTOR (sym_symtab);
- struct block *b = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
- if (lookup_block_symbol (b, copy, VAR_NAMESPACE) != NULL)
- build_canonical_line_spec (values.sals, copy, canonical);
- }
- return values;
- }
- else
- {
- if (funfirstline)
- error ("\"%s\" is not a function", copy);
- else if (SYMBOL_LINE (sym) != 0)
- {
- /* We know its line number. */
- values.sals = (struct symtab_and_line *)
- xmalloc (sizeof (struct symtab_and_line));
- values.nelts = 1;
- memset (&values.sals[0], 0, sizeof (values.sals[0]));
- values.sals[0].symtab = sym_symtab;
- values.sals[0].line = SYMBOL_LINE (sym);
- return values;
- }
- else
- /* This can happen if it is compiled with a compiler which doesn't
- put out line numbers for variables. */
- /* FIXME: Shouldn't we just set .line and .symtab to zero
- and return? For example, "info line foo" could print
- the address. */
- error ("Line number not known for symbol \"%s\"", copy);
- }
- }
-
- msymbol = lookup_minimal_symbol (copy, NULL, NULL);
- if (msymbol != NULL)
- {
- val.pc = SYMBOL_VALUE_ADDRESS (msymbol);
- val.section = SYMBOL_BFD_SECTION (msymbol);
- if (funfirstline)
- {
- val.pc += FUNCTION_START_OFFSET;
- SKIP_PROLOGUE (val.pc);
- }
- values.sals = (struct symtab_and_line *)
- xmalloc (sizeof (struct symtab_and_line));
- values.sals[0] = val;
- values.nelts = 1;
- return values;
- }
-
- if (!have_full_symbols () &&
- !have_partial_symbols () && !have_minimal_symbols ())
- error (no_symtab_msg);
-
- error ("Function \"%s\" not defined.", copy);
- return values; /* for lint */
-}
-
-struct symtabs_and_lines
-decode_line_spec (string, funfirstline)
- char *string;
- int funfirstline;
-{
- struct symtabs_and_lines sals;
- if (string == 0)
- error ("Empty line specification.");
- sals = decode_line_1 (&string, funfirstline,
- current_source_symtab, current_source_line,
- (char ***)NULL);
- if (*string)
- error ("Junk at end of line specification: %s", string);
- return sals;