mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-05-31 10:09:16 +08:00
* 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:
@ -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>
|
2006-01-02 Paul N. Hilfinger <hilfinger@adacore.com>
|
||||||
|
|
||||||
* ada-lang.c (process_raise_exception_name): Remove extraneous
|
* ada-lang.c (process_raise_exception_name): Remove extraneous
|
||||||
|
803
gdb/ada-exp.y
803
gdb/ada-exp.y
File diff suppressed because it is too large
Load Diff
754
gdb/ada-lang.c
754
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). */
|
type TYPE (typically a subrange). */
|
||||||
UNOP_IN_RANGE,
|
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 */
|
/* End marker */
|
||||||
OP_ADA_LAST
|
OP_ADA_LAST
|
||||||
};
|
};
|
||||||
|
419
gdb/ada-lex.l
419
gdb/ada-lex.l
@ -50,9 +50,10 @@ POSEXP (e"+"?{NUM10})
|
|||||||
/* Temporary staging for numeric literals. */
|
/* Temporary staging for numeric literals. */
|
||||||
static char numbuf[NUMERAL_WIDTH];
|
static char numbuf[NUMERAL_WIDTH];
|
||||||
static void canonicalizeNumeral (char *s1, const char *);
|
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 processInt (const char *, const char *, const char *);
|
||||||
static int processReal (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 processAttribute (const char *);
|
||||||
static int find_dot_all (const char *);
|
static int find_dot_all (const char *);
|
||||||
|
|
||||||
@ -70,24 +71,13 @@ static int find_dot_all (const char *);
|
|||||||
lexptr += 1; \
|
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 *);
|
static int find_dot_all (const char *);
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%option case-insensitive interactive nodefault
|
%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;
|
return CHARLIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
<INITIAL>\" {
|
\"({GRAPHIC}|"[\""({HEXDIG}{2}|\")"\"]")*\" {
|
||||||
tempbuf_len = 0;
|
yylval.sval = processString (yytext+1, yyleng-2);
|
||||||
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;
|
|
||||||
return STRING;
|
return STRING;
|
||||||
}
|
}
|
||||||
|
|
||||||
<IN_STRING>{GRAPHIC}*"[\""{HEXDIG}{2}"\"]" {
|
\" {
|
||||||
int n;
|
error ("ill-formed or non-terminated string literal");
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
<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 {
|
if {
|
||||||
while (*lexptr != 'i' && *lexptr != 'I')
|
while (*lexptr != 'i' && *lexptr != 'I')
|
||||||
@ -205,6 +173,7 @@ new { return NEW; }
|
|||||||
not { return NOT; }
|
not { return NOT; }
|
||||||
null { return NULL_PTR; }
|
null { return NULL_PTR; }
|
||||||
or { return OR; }
|
or { return OR; }
|
||||||
|
others { return OTHERS; }
|
||||||
rem { return REM; }
|
rem { return REM; }
|
||||||
then { return THEN; }
|
then { return THEN; }
|
||||||
xor { return XOR; }
|
xor { return XOR; }
|
||||||
@ -254,62 +223,34 @@ xor { return XOR; }
|
|||||||
"."{WHITE}*all { return DOT_ALL; }
|
"."{WHITE}*all { return DOT_ALL; }
|
||||||
|
|
||||||
"."{WHITE}*{ID} {
|
"."{WHITE}*{ID} {
|
||||||
processId (yytext+1, yyleng-1);
|
yylval.sval = processId (yytext+1, yyleng-1);
|
||||||
return DOT_ID;
|
return DOT_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
{ID}({WHITE}*"."{WHITE}*({ID}|\"{OPER}\"))*(" "*"'")? {
|
{ID}({WHITE}*"."{WHITE}*({ID}|\"{OPER}\"))*(" "*"'")? {
|
||||||
int all_posn = find_dot_all (yytext);
|
int all_posn = find_dot_all (yytext);
|
||||||
int token_type, segments, k;
|
|
||||||
int quote_follows;
|
|
||||||
|
|
||||||
if (all_posn == -1 && yytext[yyleng-1] == '\'')
|
if (all_posn == -1 && yytext[yyleng-1] == '\'')
|
||||||
{
|
{
|
||||||
quote_follows = 1;
|
|
||||||
do {
|
|
||||||
yyless (yyleng-1);
|
|
||||||
} while (yytext[yyleng-1] == ' ');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
quote_follows = 0;
|
|
||||||
|
|
||||||
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;
|
BEGIN BEFORE_QUAL_QUOTE;
|
||||||
return token_type;
|
yyless (yyleng-1);
|
||||||
}
|
}
|
||||||
|
else if (all_posn >= 0)
|
||||||
|
yyless (all_posn);
|
||||||
|
yylval.sval = processId (yytext, yyleng);
|
||||||
|
return NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* GDB EXPRESSION CONSTRUCTS */
|
/* GDB EXPRESSION CONSTRUCTS */
|
||||||
|
|
||||||
|
|
||||||
"'"[^']+"'"{WHITE}*:: {
|
"'"[^']+"'"{WHITE}*:: {
|
||||||
processId(yytext, yyleng-2);
|
yyless (yyleng - 2);
|
||||||
block_lookup (yylval.ssym.stoken.ptr, yylval.ssym.stoken.ptr);
|
yylval.sval = processId (yytext, yyleng);
|
||||||
return BLOCKNAME;
|
return NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
{ID}({WHITE}*"."{WHITE}*({ID}|\"{OPER}\"))*{WHITE}*:: {
|
"::" { return COLONCOLON; }
|
||||||
processId(yytext, yyleng-2);
|
|
||||||
block_lookup (ada_encode (yylval.ssym.stoken.ptr),
|
|
||||||
yylval.ssym.stoken.ptr);
|
|
||||||
return BLOCKNAME;
|
|
||||||
}
|
|
||||||
|
|
||||||
[{}@] { return yytext[0]; }
|
[{}@] { return yytext[0]; }
|
||||||
|
|
||||||
@ -329,7 +270,8 @@ xor { return XOR; }
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include "gdb_string.h"
|
#include "gdb_string.h"
|
||||||
|
|
||||||
/* Initialize the lexer for processing new expression */
|
/* Initialize the lexer for processing new expression. */
|
||||||
|
|
||||||
void
|
void
|
||||||
lexer_init (FILE *inp)
|
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. */
|
/* Copy S2 to S1, removing all underscores, and downcasing all letters. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -392,6 +322,7 @@ digit_to_int (unsigned char c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* As for strtoul, but for ULONGEST results. */
|
/* As for strtoul, but for ULONGEST results. */
|
||||||
|
|
||||||
ULONGEST
|
ULONGEST
|
||||||
strtoulst (const char *num, const char **trailer, int base)
|
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);
|
return result + ((ULONGEST) high_part << HIGH_BYTE_POSN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Interprets the prefix of NUM that consists of digits of the given BASE
|
/* 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.
|
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
|
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
|
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
|
static int
|
||||||
processInt (const char *base0, const char *num0, const char *exp0)
|
processInt (const char *base0, const char *num0, const char *exp0)
|
||||||
@ -532,11 +462,27 @@ processReal (const char *num0)
|
|||||||
return FLOAT;
|
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)
|
processId (const char *name0, int len)
|
||||||
{
|
{
|
||||||
char *name = obstack_alloc (&temp_parse_space, len + 11);
|
char *name = obstack_alloc (&temp_parse_space, len + 11);
|
||||||
int i0, i;
|
int i0, i;
|
||||||
|
struct stoken result;
|
||||||
|
|
||||||
while (len > 0 && isspace (name0[len-1]))
|
while (len > 0 && isspace (name0[len-1]))
|
||||||
len -= 1;
|
len -= 1;
|
||||||
@ -558,12 +504,12 @@ processId (const char *name0, int len)
|
|||||||
i0 += 1;
|
i0 += 1;
|
||||||
break;
|
break;
|
||||||
case '\'':
|
case '\'':
|
||||||
i0 += 1;
|
do
|
||||||
while (i0 < len && name0[i0] != '\'')
|
|
||||||
{
|
{
|
||||||
name[i] = name0[i0];
|
name[i] = name0[i0];
|
||||||
i += 1; i0 += 1;
|
i += 1; i0 += 1;
|
||||||
}
|
}
|
||||||
|
while (i0 < len && name0[i0] != '\'');
|
||||||
i0 += 1;
|
i0 += 1;
|
||||||
break;
|
break;
|
||||||
case '<':
|
case '<':
|
||||||
@ -579,259 +525,58 @@ processId (const char *name0, int len)
|
|||||||
}
|
}
|
||||||
name[i] = '\000';
|
name[i] = '\000';
|
||||||
|
|
||||||
yylval.ssym.sym = NULL;
|
result.ptr = name;
|
||||||
yylval.ssym.stoken.ptr = name;
|
result.length = i;
|
||||||
yylval.ssym.stoken.length = i;
|
|
||||||
return NAME;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
block_lookup (char *name, char *err_name)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
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;
|
return result;
|
||||||
}
|
}
|
||||||
else if (segments == 0)
|
|
||||||
{
|
|
||||||
yylval.tval = preferred_type;
|
|
||||||
*token_type = TYPENAME;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (segments == 0)
|
/* Return TEXT[0..LEN-1], a string literal without surrounding quotes,
|
||||||
{
|
with special hex character notations replaced with characters.
|
||||||
type = language_lookup_primitive_type_by_name (current_language,
|
Result valid until the next call to ada_parse. */
|
||||||
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;
|
static struct stoken
|
||||||
*token_type = TYPENAME;
|
processString (const char *text, int len)
|
||||||
return 0;
|
{
|
||||||
}
|
const char *p;
|
||||||
}
|
char *q;
|
||||||
|
const char *lim = text + len;
|
||||||
|
struct stoken result;
|
||||||
|
|
||||||
NotType:
|
q = result.ptr = obstack_alloc (&temp_parse_space, len);
|
||||||
if (nsyms == 1)
|
p = text;
|
||||||
|
while (p < lim)
|
||||||
{
|
{
|
||||||
*token_type = NAME;
|
if (p[0] == '[' && p[1] == '"' && p+2 < lim)
|
||||||
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;
|
if (p[2] == '"') /* "...["""]... */
|
||||||
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] == '.')
|
*q = '"';
|
||||||
{
|
p += 4;
|
||||||
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
|
else
|
||||||
{
|
{
|
||||||
*token_type = NAME;
|
int chr;
|
||||||
yylval.ssym.sym = NULL;
|
sscanf (p+2, "%2x", &chr);
|
||||||
yylval.ssym.msym = NULL;
|
*q = (char) chr;
|
||||||
if (left_block_context == NULL)
|
p += 5;
|
||||||
yylval.ssym.block = expression_context_block;
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
yylval.ssym.block = left_block_context;
|
*q = *p;
|
||||||
return segments;
|
q += 1;
|
||||||
}
|
p += 1;
|
||||||
}
|
}
|
||||||
|
result.length = q - result.ptr;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns the position within STR of the '.' in a
|
/* 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
|
static int
|
||||||
find_dot_all (const char *str)
|
find_dot_all (const char *str)
|
||||||
{
|
{
|
||||||
@ -844,7 +589,7 @@ find_dot_all (const char *str)
|
|||||||
do
|
do
|
||||||
i += 1;
|
i += 1;
|
||||||
while (isspace (str[i]));
|
while (isspace (str[i]));
|
||||||
if (strcmp (str+i, "all") == 0
|
if (strncmp (str+i, "all", 3) == 0
|
||||||
&& ! isalnum (str[i+3]) && str[i+3] != '_')
|
&& ! isalnum (str[i+3]) && str[i+3] != '_')
|
||||||
return i0;
|
return i0;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user