* ada-exp.y: Considerable reorganization to move functionality
from ada-lex.l to here, where it is logically more appropriate. The original reason, however, was to prevent premature name lookups for selector names in record aggregates. (BLOCKNAME, TYPENAME, OBJECT_RENAMING): Remove; lexer now returns NAME for all of these. (VAR): New artificial token to clarify precedence rules. (OTHERS): New lexeme. (empty_stoken): New symbol. (%union): Remove ssym, voidval. (%type): Remove <voidval> type declarations. (syntax definitions): Add aggregates. Remove distinction between NAME, TYPENAME, BLOCKNAME, OBJECT_RENAMING. Rename some non-terminals to be closer to reference manual usage. Tighten up expression syntax to disallow certain non-Ada constructions such as X and then Y or else Z. (ada_parse): Remove initialization of left_block_context. (write_var_from_name): Remove. (write_var_or_type): New function, containing previous code from defunct write_var_from_name and name_lookup. (block_lookup): New function, moved from ada-lex.l (select_possible_type_sym): New function, factored out of name_lookup, which used to be in ada-lex.l. (find_primitive_type): Ditto. (chop_selector): Ditto. (write_ambiguous_var): New function, factored out of defunct write_var_from_name. (write_selectors): New function. (write_name_assoc): New function. (write_exp_op_with_string): New function. * ada-lex.l (processId): Change interface to return stoken. (tempbuf, resize_tempbuf, tempbuf_size, tempbuf_len): Remove. (block_lookup, name_lookup): Remove. Functionality moved to ada-exp.y. (state IN_STRING): Remove. (rules): Handle string escapes in processString. Add 'others' token. Return all NAMEs, BLOCKNAMEs, OBJECT_RENAMINGs, TYPENAMEs in yylval.sval (as simple strings). All name look-ups now handled in ada-exp.y. Introduce "::" (COLONCOLON) token and return as separate token. (processId): Change return convention. Comment. Leave leading "'" in place. (processString): New function. (find_dot_all): Add note to comment. Fix problem that allowed match only at the end. * ada-lang.c: Introduce aggregates. (find_struct_field): Add new parameter to count fields skipped, and allow other output parameters to be NULL. (value_tag_from_contents_and_address, ada_value_struct_elt): Use new find_struct_field. (ada_index_struct_field, assign_aggregate, ada_is_array_type) (num_visible_fields, ada_index_struct_field_1, ada_index_struct_field) (num_component_specs, assign_component, assign_aggregate): (aggregate_assign_from_choices,aggregate_assign_positional) (aggregate_assign_others,add_component_interval): New functions. (ada_evaluate_subexp): Declare. Add aggregate-related operators. (ada_forward_operator_length): Declare. (resolve_subexp): Add cases for new aggregate operators and OP_NAME. Consolidate Ada operators, using ada_forward_operator_length. (ada_search_struct_field): Search in forward order. (ADA_OPERATORS): Add new aggregate operators. (ada_operator_length, ada_op_name, ada_forward_operator_length) (ada_dump_subexp_body, ada_print_subexp): Handle new aggregate operators and OP_NAME. (ada_type_of_array): Use longest_to_int. (value_assign_to_component): New function. (ada_forward_operator_length, ada_op_name, ada_dump_subexp_body): Add OP_NAME case. (ada_forward_operator_length, ada_dump_subexp_body): Add OP_STRING case. * ada-lang.h (enum ada_operator): Add OP_AGGREGATE, OP_OTHERS, OP_CHOICES, OP_DISCRETE_RANGE, OP_POSITIONAL.
This commit is contained in:
parent
529cad9c5b
commit
52ce64369c
@ -1,3 +1,84 @@
|
||||
2006-01-02 Paul N. Hilfinger <hilfinger@adacore.com>
|
||||
|
||||
* ada-exp.y: Considerable reorganization to move functionality
|
||||
from ada-lex.l to here, where it is logically more appropriate.
|
||||
The original reason, however, was to prevent premature name
|
||||
lookups for selector names in record aggregates.
|
||||
(BLOCKNAME, TYPENAME, OBJECT_RENAMING): Remove; lexer now returns
|
||||
NAME for all of these.
|
||||
(VAR): New artificial token to clarify precedence rules.
|
||||
(OTHERS): New lexeme.
|
||||
(empty_stoken): New symbol.
|
||||
(%union): Remove ssym, voidval.
|
||||
(%type): Remove <voidval> type declarations.
|
||||
(syntax definitions): Add aggregates.
|
||||
Remove distinction between NAME, TYPENAME, BLOCKNAME, OBJECT_RENAMING.
|
||||
Rename some non-terminals to be closer to reference manual usage.
|
||||
Tighten up expression syntax to disallow certain non-Ada
|
||||
constructions such as X and then Y or else Z.
|
||||
(ada_parse): Remove initialization of left_block_context.
|
||||
(write_var_from_name): Remove.
|
||||
(write_var_or_type): New function, containing previous code from
|
||||
defunct write_var_from_name and name_lookup.
|
||||
(block_lookup): New function, moved from ada-lex.l
|
||||
(select_possible_type_sym): New function, factored out of
|
||||
name_lookup, which used to be in ada-lex.l.
|
||||
(find_primitive_type): Ditto.
|
||||
(chop_selector): Ditto.
|
||||
(write_ambiguous_var): New function, factored out of defunct
|
||||
write_var_from_name.
|
||||
(write_selectors): New function.
|
||||
(write_name_assoc): New function.
|
||||
(write_exp_op_with_string): New function.
|
||||
|
||||
* ada-lex.l (processId): Change interface to return stoken.
|
||||
(tempbuf, resize_tempbuf, tempbuf_size, tempbuf_len): Remove.
|
||||
(block_lookup, name_lookup): Remove. Functionality moved to
|
||||
ada-exp.y.
|
||||
(state IN_STRING): Remove.
|
||||
(rules): Handle string escapes in processString.
|
||||
Add 'others' token.
|
||||
Return all NAMEs, BLOCKNAMEs, OBJECT_RENAMINGs, TYPENAMEs in
|
||||
yylval.sval (as simple strings).
|
||||
All name look-ups now handled in ada-exp.y.
|
||||
Introduce "::" (COLONCOLON) token and return as separate token.
|
||||
(processId): Change return convention. Comment.
|
||||
Leave leading "'" in place.
|
||||
(processString): New function.
|
||||
(find_dot_all): Add note to comment.
|
||||
Fix problem that allowed match only at the end.
|
||||
|
||||
* ada-lang.c: Introduce aggregates.
|
||||
(find_struct_field): Add new parameter to count fields skipped, and
|
||||
allow other output parameters to be NULL.
|
||||
(value_tag_from_contents_and_address, ada_value_struct_elt): Use
|
||||
new find_struct_field.
|
||||
(ada_index_struct_field, assign_aggregate, ada_is_array_type)
|
||||
(num_visible_fields, ada_index_struct_field_1, ada_index_struct_field)
|
||||
(num_component_specs, assign_component, assign_aggregate):
|
||||
(aggregate_assign_from_choices,aggregate_assign_positional)
|
||||
(aggregate_assign_others,add_component_interval):
|
||||
New functions.
|
||||
(ada_evaluate_subexp): Declare.
|
||||
Add aggregate-related operators.
|
||||
(ada_forward_operator_length): Declare.
|
||||
(resolve_subexp): Add cases for new aggregate operators and OP_NAME.
|
||||
Consolidate Ada operators, using ada_forward_operator_length.
|
||||
(ada_search_struct_field): Search in forward order.
|
||||
(ADA_OPERATORS): Add new aggregate operators.
|
||||
(ada_operator_length, ada_op_name, ada_forward_operator_length)
|
||||
(ada_dump_subexp_body, ada_print_subexp): Handle new aggregate
|
||||
operators and OP_NAME.
|
||||
(ada_type_of_array): Use longest_to_int.
|
||||
(value_assign_to_component): New function.
|
||||
(ada_forward_operator_length, ada_op_name, ada_dump_subexp_body):
|
||||
Add OP_NAME case.
|
||||
(ada_forward_operator_length, ada_dump_subexp_body):
|
||||
Add OP_STRING case.
|
||||
|
||||
* ada-lang.h (enum ada_operator): Add OP_AGGREGATE, OP_OTHERS,
|
||||
OP_CHOICES, OP_DISCRETE_RANGE, OP_POSITIONAL.
|
||||
|
||||
2006-01-02 Paul N. Hilfinger <hilfinger@adacore.com>
|
||||
|
||||
* ada-lang.c (process_raise_exception_name): Remove extraneous
|
||||
|
825
gdb/ada-exp.y
825
gdb/ada-exp.y
File diff suppressed because it is too large
Load Diff
768
gdb/ada-lang.c
768
gdb/ada-lang.c
File diff suppressed because it is too large
Load Diff
@ -115,6 +115,54 @@ enum ada_operator
|
||||
type TYPE (typically a subrange). */
|
||||
UNOP_IN_RANGE,
|
||||
|
||||
/* An aggregate. A single immediate operand, N>0, gives
|
||||
the number of component specifications that follow. The
|
||||
immediate operand is followed by a second OP_AGGREGATE.
|
||||
Next come N component specifications. A component
|
||||
specification is either an OP_OTHERS (others=>...), an
|
||||
OP_CHOICES (for named associations), or other expression (for
|
||||
positional aggregates only). Aggregates currently
|
||||
occur only as the right sides of assignments. */
|
||||
OP_AGGREGATE,
|
||||
|
||||
/* An others clause. Followed by a single expression. */
|
||||
OP_OTHERS,
|
||||
|
||||
/* An aggregate component association. A single immediate operand, N,
|
||||
gives the number of choices that follow. This is followed by a second
|
||||
OP_CHOICES operator. Next come N operands, each of which is an
|
||||
expression, an OP_DISCRETE_RANGE, or an OP_NAME---the latter
|
||||
for a simple name that must be a record component name and does
|
||||
not correspond to a single existing symbol. After the N choice
|
||||
indicators comes an expression giving the value.
|
||||
|
||||
In an aggregate such as (X => E1, ...), where X is a simple
|
||||
name, X could syntactically be either a component_selector_name
|
||||
or an expression used as a discrete_choice, depending on the
|
||||
aggregate's type context. Since this is not known at parsing
|
||||
time, we don't attempt to disambiguate X if it has multiple
|
||||
definitions, but instead supply an OP_NAME. If X has a single
|
||||
definition, we represent it with an OP_VAR_VALUE, even though
|
||||
it may turn out to be within a record aggregate. Aggregate
|
||||
evaluation can use either OP_NAMEs or OP_VAR_VALUEs to get a
|
||||
record field name, and can evaluate OP_VAR_VALUE normally to
|
||||
get its value as an expression. Unfortunately, we lose out in
|
||||
cases where X has multiple meanings and is part of an array
|
||||
aggregate. I hope these are not common enough to annoy users,
|
||||
who can work around the problem in any case by putting
|
||||
parentheses around X. */
|
||||
OP_CHOICES,
|
||||
|
||||
/* A positional aggregate component association. The operator is
|
||||
followed by a single integer indicating the position in the
|
||||
aggregate (0-based), followed by a second OP_POSITIONAL. Next
|
||||
follows a single expression giving the component value. */
|
||||
OP_POSITIONAL,
|
||||
|
||||
/* A range of values. Followed by two expressions giving the
|
||||
upper and lower bounds of the range. */
|
||||
OP_DISCRETE_RANGE,
|
||||
|
||||
/* End marker */
|
||||
OP_ADA_LAST
|
||||
};
|
||||
|
433
gdb/ada-lex.l
433
gdb/ada-lex.l
@ -50,9 +50,10 @@ POSEXP (e"+"?{NUM10})
|
||||
/* Temporary staging for numeric literals. */
|
||||
static char numbuf[NUMERAL_WIDTH];
|
||||
static void canonicalizeNumeral (char *s1, const char *);
|
||||
static struct stoken processString (const char*, int);
|
||||
static int processInt (const char *, const char *, const char *);
|
||||
static int processReal (const char *);
|
||||
static int processId (const char *, int);
|
||||
static struct stoken processId (const char *, int);
|
||||
static int processAttribute (const char *);
|
||||
static int find_dot_all (const char *);
|
||||
|
||||
@ -70,24 +71,13 @@ static int find_dot_all (const char *);
|
||||
lexptr += 1; \
|
||||
}
|
||||
|
||||
static char *tempbuf = NULL;
|
||||
static int tempbufsize = 0;
|
||||
static int tempbuf_len;
|
||||
static struct block *left_block_context;
|
||||
|
||||
static void resize_tempbuf (unsigned int);
|
||||
|
||||
static void block_lookup (char *, char *);
|
||||
|
||||
static int name_lookup (char *, char *, int *, int);
|
||||
|
||||
static int find_dot_all (const char *);
|
||||
|
||||
%}
|
||||
|
||||
%option case-insensitive interactive nodefault
|
||||
|
||||
%s IN_STRING BEFORE_QUAL_QUOTE
|
||||
%s BEFORE_QUAL_QUOTE
|
||||
|
||||
%%
|
||||
|
||||
@ -155,37 +145,15 @@ static int find_dot_all (const char *);
|
||||
return CHARLIT;
|
||||
}
|
||||
|
||||
<INITIAL>\" {
|
||||
tempbuf_len = 0;
|
||||
BEGIN IN_STRING;
|
||||
}
|
||||
|
||||
<IN_STRING>{GRAPHIC}*\" {
|
||||
resize_tempbuf (yyleng+tempbuf_len);
|
||||
strncpy (tempbuf+tempbuf_len, yytext, yyleng-1);
|
||||
tempbuf_len += yyleng-1;
|
||||
yylval.sval.ptr = tempbuf;
|
||||
yylval.sval.length = tempbuf_len;
|
||||
BEGIN INITIAL;
|
||||
\"({GRAPHIC}|"[\""({HEXDIG}{2}|\")"\"]")*\" {
|
||||
yylval.sval = processString (yytext+1, yyleng-2);
|
||||
return STRING;
|
||||
}
|
||||
|
||||
<IN_STRING>{GRAPHIC}*"[\""{HEXDIG}{2}"\"]" {
|
||||
int n;
|
||||
resize_tempbuf (yyleng-5+tempbuf_len+1);
|
||||
strncpy (tempbuf+tempbuf_len, yytext, yyleng-6);
|
||||
sscanf(yytext+yyleng-4, "%2x", &n);
|
||||
tempbuf[yyleng-6+tempbuf_len] = (char) n;
|
||||
tempbuf_len += yyleng-5;
|
||||
\" {
|
||||
error ("ill-formed or non-terminated string literal");
|
||||
}
|
||||
|
||||
<IN_STRING>{GRAPHIC}*"[\"\"\"]" {
|
||||
int n;
|
||||
resize_tempbuf (yyleng-4+tempbuf_len+1);
|
||||
strncpy (tempbuf+tempbuf_len, yytext, yyleng-6);
|
||||
tempbuf[yyleng-5+tempbuf_len] = '"';
|
||||
tempbuf_len += yyleng-4;
|
||||
}
|
||||
|
||||
if {
|
||||
while (*lexptr != 'i' && *lexptr != 'I')
|
||||
@ -205,6 +173,7 @@ new { return NEW; }
|
||||
not { return NOT; }
|
||||
null { return NULL_PTR; }
|
||||
or { return OR; }
|
||||
others { return OTHERS; }
|
||||
rem { return REM; }
|
||||
then { return THEN; }
|
||||
xor { return XOR; }
|
||||
@ -254,62 +223,34 @@ xor { return XOR; }
|
||||
"."{WHITE}*all { return DOT_ALL; }
|
||||
|
||||
"."{WHITE}*{ID} {
|
||||
processId (yytext+1, yyleng-1);
|
||||
yylval.sval = processId (yytext+1, yyleng-1);
|
||||
return DOT_ID;
|
||||
}
|
||||
|
||||
{ID}({WHITE}*"."{WHITE}*({ID}|\"{OPER}\"))*(" "*"'")? {
|
||||
int all_posn = find_dot_all (yytext);
|
||||
int token_type, segments, k;
|
||||
int quote_follows;
|
||||
|
||||
if (all_posn == -1 && yytext[yyleng-1] == '\'')
|
||||
{
|
||||
quote_follows = 1;
|
||||
do {
|
||||
yyless (yyleng-1);
|
||||
} while (yytext[yyleng-1] == ' ');
|
||||
BEGIN BEFORE_QUAL_QUOTE;
|
||||
yyless (yyleng-1);
|
||||
}
|
||||
else
|
||||
quote_follows = 0;
|
||||
|
||||
if (all_posn >= 0)
|
||||
else if (all_posn >= 0)
|
||||
yyless (all_posn);
|
||||
processId(yytext, yyleng);
|
||||
segments = name_lookup (ada_encode (yylval.ssym.stoken.ptr),
|
||||
yylval.ssym.stoken.ptr,
|
||||
&token_type,
|
||||
MAX_RENAMING_CHAIN_LENGTH);
|
||||
left_block_context = NULL;
|
||||
for (k = yyleng; segments > 0 && k > 0; k -= 1)
|
||||
{
|
||||
if (yytext[k-1] == '.')
|
||||
segments -= 1;
|
||||
quote_follows = 0;
|
||||
}
|
||||
if (k <= 0)
|
||||
error ("confused by name %s", yytext);
|
||||
yyless (k);
|
||||
if (quote_follows)
|
||||
BEGIN BEFORE_QUAL_QUOTE;
|
||||
return token_type;
|
||||
}
|
||||
yylval.sval = processId (yytext, yyleng);
|
||||
return NAME;
|
||||
}
|
||||
|
||||
|
||||
/* GDB EXPRESSION CONSTRUCTS */
|
||||
|
||||
|
||||
"'"[^']+"'"{WHITE}*:: {
|
||||
processId(yytext, yyleng-2);
|
||||
block_lookup (yylval.ssym.stoken.ptr, yylval.ssym.stoken.ptr);
|
||||
return BLOCKNAME;
|
||||
yyless (yyleng - 2);
|
||||
yylval.sval = processId (yytext, yyleng);
|
||||
return NAME;
|
||||
}
|
||||
|
||||
{ID}({WHITE}*"."{WHITE}*({ID}|\"{OPER}\"))*{WHITE}*:: {
|
||||
processId(yytext, yyleng-2);
|
||||
block_lookup (ada_encode (yylval.ssym.stoken.ptr),
|
||||
yylval.ssym.stoken.ptr);
|
||||
return BLOCKNAME;
|
||||
}
|
||||
"::" { return COLONCOLON; }
|
||||
|
||||
[{}@] { return yytext[0]; }
|
||||
|
||||
@ -329,7 +270,8 @@ xor { return XOR; }
|
||||
#include <ctype.h>
|
||||
#include "gdb_string.h"
|
||||
|
||||
/* Initialize the lexer for processing new expression */
|
||||
/* Initialize the lexer for processing new expression. */
|
||||
|
||||
void
|
||||
lexer_init (FILE *inp)
|
||||
{
|
||||
@ -338,18 +280,6 @@ lexer_init (FILE *inp)
|
||||
}
|
||||
|
||||
|
||||
/* Make sure that tempbuf points at an array at least N characters long. */
|
||||
|
||||
static void
|
||||
resize_tempbuf (unsigned int n)
|
||||
{
|
||||
if (tempbufsize < n)
|
||||
{
|
||||
tempbufsize = (n+63) & ~63;
|
||||
tempbuf = xrealloc (tempbuf, tempbufsize);
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy S2 to S1, removing all underscores, and downcasing all letters. */
|
||||
|
||||
static void
|
||||
@ -392,6 +322,7 @@ digit_to_int (unsigned char c)
|
||||
}
|
||||
|
||||
/* As for strtoul, but for ULONGEST results. */
|
||||
|
||||
ULONGEST
|
||||
strtoulst (const char *num, const char **trailer, int base)
|
||||
{
|
||||
@ -427,13 +358,12 @@ strtoulst (const char *num, const char **trailer, int base)
|
||||
return result + ((ULONGEST) high_part << HIGH_BYTE_POSN);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Interprets the prefix of NUM that consists of digits of the given BASE
|
||||
as an integer of that BASE, with the string EXP as an exponent.
|
||||
Puts value in yylval, and returns INT, if the string is valid. Causes
|
||||
an error if the number is improperly formated. BASE, if NULL, defaults
|
||||
to "10", and EXP to "1". The EXP does not contain a leading 'e' or 'E'. */
|
||||
to "10", and EXP to "1". The EXP does not contain a leading 'e' or 'E'.
|
||||
*/
|
||||
|
||||
static int
|
||||
processInt (const char *base0, const char *num0, const char *exp0)
|
||||
@ -532,11 +462,27 @@ processReal (const char *num0)
|
||||
return FLOAT;
|
||||
}
|
||||
|
||||
static int
|
||||
|
||||
/* Store a canonicalized version of NAME0[0..LEN-1] in yylval.ssym. The
|
||||
resulting string is valid until the next call to ada_parse. It differs
|
||||
from NAME0 in that:
|
||||
+ Characters between '...' or <...> are transfered verbatim to
|
||||
yylval.ssym.
|
||||
+ <, >, and trailing "'" characters in quoted sequences are removed
|
||||
(a leading quote is preserved to indicate that the name is not to be
|
||||
GNAT-encoded).
|
||||
+ Unquoted whitespace is removed.
|
||||
+ Unquoted alphabetic characters are mapped to lower case.
|
||||
Result is returned as a struct stoken, but for convenience, the string
|
||||
is also null-terminated. Result string valid until the next call of
|
||||
ada_parse.
|
||||
*/
|
||||
static struct stoken
|
||||
processId (const char *name0, int len)
|
||||
{
|
||||
char *name = obstack_alloc (&temp_parse_space, len + 11);
|
||||
int i0, i;
|
||||
struct stoken result;
|
||||
|
||||
while (len > 0 && isspace (name0[len-1]))
|
||||
len -= 1;
|
||||
@ -558,12 +504,12 @@ processId (const char *name0, int len)
|
||||
i0 += 1;
|
||||
break;
|
||||
case '\'':
|
||||
i0 += 1;
|
||||
while (i0 < len && name0[i0] != '\'')
|
||||
do
|
||||
{
|
||||
name[i] = name0[i0];
|
||||
i += 1; i0 += 1;
|
||||
}
|
||||
while (i0 < len && name0[i0] != '\'');
|
||||
i0 += 1;
|
||||
break;
|
||||
case '<':
|
||||
@ -579,259 +525,58 @@ processId (const char *name0, int len)
|
||||
}
|
||||
name[i] = '\000';
|
||||
|
||||
yylval.ssym.sym = NULL;
|
||||
yylval.ssym.stoken.ptr = name;
|
||||
yylval.ssym.stoken.length = i;
|
||||
return NAME;
|
||||
result.ptr = name;
|
||||
result.length = i;
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
block_lookup (char *name, char *err_name)
|
||||
/* Return TEXT[0..LEN-1], a string literal without surrounding quotes,
|
||||
with special hex character notations replaced with characters.
|
||||
Result valid until the next call to ada_parse. */
|
||||
|
||||
static struct stoken
|
||||
processString (const char *text, int len)
|
||||
{
|
||||
struct ada_symbol_info *syms;
|
||||
int nsyms;
|
||||
struct symtab *symtab;
|
||||
nsyms = ada_lookup_symbol_list (name, left_block_context,
|
||||
VAR_DOMAIN, &syms);
|
||||
if (left_block_context == NULL &&
|
||||
(nsyms == 0 || SYMBOL_CLASS (syms[0].sym) != LOC_BLOCK))
|
||||
symtab = lookup_symtab (name);
|
||||
else
|
||||
symtab = NULL;
|
||||
const char *p;
|
||||
char *q;
|
||||
const char *lim = text + len;
|
||||
struct stoken result;
|
||||
|
||||
if (symtab != NULL)
|
||||
left_block_context = yylval.bval =
|
||||
BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), STATIC_BLOCK);
|
||||
else if (nsyms == 0 || SYMBOL_CLASS (syms[0].sym) != LOC_BLOCK)
|
||||
q = result.ptr = obstack_alloc (&temp_parse_space, len);
|
||||
p = text;
|
||||
while (p < lim)
|
||||
{
|
||||
if (left_block_context == NULL)
|
||||
error ("No file or function \"%s\".", err_name);
|
||||
else
|
||||
error ("No function \"%s\" in specified context.", err_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
left_block_context = yylval.bval = SYMBOL_BLOCK_VALUE (syms[0].sym);
|
||||
if (nsyms > 1)
|
||||
warning ("Function name \"%s\" ambiguous here", err_name);
|
||||
}
|
||||
}
|
||||
|
||||
/* Look up NAME0 (assumed to be encoded) as a name in VAR_DOMAIN,
|
||||
setting *TOKEN_TYPE to NAME or TYPENAME, depending on what is
|
||||
found. Try first the entire name, then the name without the last
|
||||
segment (i.e., after the last .id), etc., and return the number of
|
||||
segments that had to be removed to get a match. Try only the full
|
||||
name if it starts with "standard__". Calls error if no
|
||||
matches are found, using ERR_NAME in any error message. When
|
||||
exactly one symbol match is found, it is placed in yylval. When
|
||||
the symbol is a renaming, follow at most DEPTH steps to find the
|
||||
ultimate definition; cause error if depth exceeded. */
|
||||
|
||||
static int
|
||||
name_lookup (char *name0, char *err_name, int *token_type, int depth)
|
||||
{
|
||||
struct ada_symbol_info *syms;
|
||||
struct type *type;
|
||||
int len0 = strlen (name0);
|
||||
char *name = obsavestring (name0, len0, &temp_parse_space);
|
||||
int nsyms;
|
||||
int segments;
|
||||
|
||||
if (depth <= 0)
|
||||
error ("Could not find renamed symbol \"%s\"", err_name);
|
||||
|
||||
yylval.ssym.stoken.ptr = name;
|
||||
yylval.ssym.stoken.length = strlen (name);
|
||||
for (segments = 0; ; segments += 1)
|
||||
{
|
||||
struct type *preferred_type;
|
||||
int i, preferred_index;
|
||||
|
||||
if (left_block_context == NULL)
|
||||
nsyms = ada_lookup_symbol_list (name, expression_context_block,
|
||||
VAR_DOMAIN, &syms);
|
||||
else
|
||||
nsyms = ada_lookup_symbol_list (name, left_block_context,
|
||||
VAR_DOMAIN, &syms);
|
||||
|
||||
|
||||
/* Check for a type renaming. */
|
||||
|
||||
if (nsyms == 1 && !ada_is_object_renaming (syms[0].sym))
|
||||
{
|
||||
struct symbol *renaming_sym =
|
||||
ada_find_renaming_symbol (SYMBOL_LINKAGE_NAME (syms[0].sym),
|
||||
syms[0].block);
|
||||
|
||||
if (renaming_sym != NULL)
|
||||
syms[0].sym = renaming_sym;
|
||||
}
|
||||
|
||||
/* Check for a type definition. */
|
||||
|
||||
/* Look for a symbol that doesn't denote void. This is (I think) a */
|
||||
/* temporary kludge to get around problems in GNAT output. */
|
||||
preferred_index = -1; preferred_type = NULL;
|
||||
for (i = 0; i < nsyms; i += 1)
|
||||
switch (SYMBOL_CLASS (syms[i].sym))
|
||||
{
|
||||
case LOC_TYPEDEF:
|
||||
if (ada_prefer_type (SYMBOL_TYPE (syms[i].sym), preferred_type))
|
||||
{
|
||||
preferred_index = i;
|
||||
preferred_type = SYMBOL_TYPE (syms[i].sym);
|
||||
}
|
||||
break;
|
||||
case LOC_REGISTER:
|
||||
case LOC_ARG:
|
||||
case LOC_REF_ARG:
|
||||
case LOC_REGPARM:
|
||||
case LOC_REGPARM_ADDR:
|
||||
case LOC_LOCAL:
|
||||
case LOC_LOCAL_ARG:
|
||||
case LOC_BASEREG:
|
||||
case LOC_BASEREG_ARG:
|
||||
case LOC_COMPUTED:
|
||||
case LOC_COMPUTED_ARG:
|
||||
goto NotType;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (preferred_type != NULL)
|
||||
{
|
||||
if (TYPE_CODE (preferred_type) == TYPE_CODE_VOID)
|
||||
error ("`%s' matches only void type name(s)",
|
||||
ada_decode (name));
|
||||
else if (ada_is_object_renaming (syms[preferred_index].sym))
|
||||
{
|
||||
yylval.ssym.sym = syms[preferred_index].sym;
|
||||
*token_type = OBJECT_RENAMING;
|
||||
return segments;
|
||||
}
|
||||
else if (ada_renaming_type (SYMBOL_TYPE (syms[preferred_index].sym))
|
||||
!= NULL)
|
||||
{
|
||||
int result;
|
||||
char *renaming
|
||||
= ada_simple_renamed_entity (syms[preferred_index].sym);
|
||||
char *new_name
|
||||
= (char *) obstack_alloc (&temp_parse_space,
|
||||
strlen (renaming) + len0
|
||||
- yylval.ssym.stoken.length + 1);
|
||||
strcpy (new_name, renaming);
|
||||
xfree (renaming);
|
||||
strcat (new_name, name0 + yylval.ssym.stoken.length);
|
||||
result = name_lookup (new_name, err_name, token_type, depth - 1);
|
||||
if (result > segments)
|
||||
error ("Confused by renamed symbol.");
|
||||
return result;
|
||||
}
|
||||
else if (segments == 0)
|
||||
{
|
||||
yylval.tval = preferred_type;
|
||||
*token_type = TYPENAME;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (segments == 0)
|
||||
{
|
||||
type = language_lookup_primitive_type_by_name (current_language,
|
||||
current_gdbarch,
|
||||
name);
|
||||
if (type == NULL && strcmp ("system__address", name) == 0)
|
||||
type = type_system_address ();
|
||||
if (type != NULL)
|
||||
{
|
||||
/* First check to see if we have a regular definition of this
|
||||
type that just didn't happen to have been read yet. */
|
||||
int ntypes;
|
||||
struct symbol *sym;
|
||||
char *expanded_name =
|
||||
(char *) alloca (strlen (name) + sizeof ("standard__"));
|
||||
strcpy (expanded_name, "standard__");
|
||||
strcat (expanded_name, name);
|
||||
sym = ada_lookup_symbol (expanded_name, NULL,
|
||||
VAR_DOMAIN, NULL, NULL);
|
||||
if (sym != NULL && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
|
||||
type = SYMBOL_TYPE (sym);
|
||||
|
||||
yylval.tval = type;
|
||||
*token_type = TYPENAME;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
NotType:
|
||||
if (nsyms == 1)
|
||||
{
|
||||
*token_type = NAME;
|
||||
yylval.ssym.sym = syms[0].sym;
|
||||
yylval.ssym.msym = NULL;
|
||||
yylval.ssym.block = syms[0].block;
|
||||
return segments;
|
||||
}
|
||||
else if (nsyms == 0) {
|
||||
int i;
|
||||
yylval.ssym.msym = ada_lookup_simple_minsym (name);
|
||||
if (yylval.ssym.msym != NULL)
|
||||
{
|
||||
yylval.ssym.sym = NULL;
|
||||
yylval.ssym.block = NULL;
|
||||
*token_type = NAME;
|
||||
return segments;
|
||||
}
|
||||
|
||||
if (segments == 0
|
||||
&& strncmp (name, "standard__", sizeof ("standard__") - 1) == 0)
|
||||
error ("No definition of \"%s\" found.", err_name);
|
||||
|
||||
for (i = yylval.ssym.stoken.length - 1; i > 0; i -= 1)
|
||||
{
|
||||
if (name[i] == '.')
|
||||
{
|
||||
name[i] = '\0';
|
||||
yylval.ssym.stoken.length = i;
|
||||
break;
|
||||
}
|
||||
else if (name[i] == '_' && name[i-1] == '_')
|
||||
{
|
||||
i -= 1;
|
||||
name[i] = '\0';
|
||||
yylval.ssym.stoken.length = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i <= 0)
|
||||
{
|
||||
if (!have_full_symbols () && !have_partial_symbols ()
|
||||
&& left_block_context == NULL)
|
||||
error ("No symbol table is loaded. Use the \"file\" command.");
|
||||
if (left_block_context == NULL)
|
||||
error ("No definition of \"%s\" in current context.",
|
||||
err_name);
|
||||
else
|
||||
error ("No definition of \"%s\" in specified context.",
|
||||
err_name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*token_type = NAME;
|
||||
yylval.ssym.sym = NULL;
|
||||
yylval.ssym.msym = NULL;
|
||||
if (left_block_context == NULL)
|
||||
yylval.ssym.block = expression_context_block;
|
||||
else
|
||||
yylval.ssym.block = left_block_context;
|
||||
return segments;
|
||||
}
|
||||
}
|
||||
if (p[0] == '[' && p[1] == '"' && p+2 < lim)
|
||||
{
|
||||
if (p[2] == '"') /* "...["""]... */
|
||||
{
|
||||
*q = '"';
|
||||
p += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
int chr;
|
||||
sscanf (p+2, "%2x", &chr);
|
||||
*q = (char) chr;
|
||||
p += 5;
|
||||
}
|
||||
}
|
||||
else
|
||||
*q = *p;
|
||||
q += 1;
|
||||
p += 1;
|
||||
}
|
||||
result.length = q - result.ptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Returns the position within STR of the '.' in a
|
||||
'.{WHITE}*all' component of a dotted name, or -1 if there is none. */
|
||||
'.{WHITE}*all' component of a dotted name, or -1 if there is none.
|
||||
Note: we actually don't need this routine, since 'all' can never be an
|
||||
Ada identifier. Thus, looking up foo.all or foo.all.x as a name
|
||||
must fail, and will eventually be interpreted as (foo).all or
|
||||
(foo).all.x. However, this does avoid an extraneous lookup. */
|
||||
|
||||
static int
|
||||
find_dot_all (const char *str)
|
||||
{
|
||||
@ -844,7 +589,7 @@ find_dot_all (const char *str)
|
||||
do
|
||||
i += 1;
|
||||
while (isspace (str[i]));
|
||||
if (strcmp (str+i, "all") == 0
|
||||
if (strncmp (str+i, "all", 3) == 0
|
||||
&& ! isalnum (str[i+3]) && str[i+3] != '_')
|
||||
return i0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user