12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907 |
- /* YACC parser for Ada expressions, for GDB.
- Copyright (C) 1986-2022 Free Software Foundation, Inc.
- This file is part of GDB.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
- /* Parse an Ada expression from text in a string,
- and return the result as a struct expression pointer.
- That structure contains arithmetic operations in reverse polish,
- with constants represented by operations that are followed by special data.
- See expression.h for the details of the format.
- What is important here is that it can be built up sequentially
- during the process of parsing; the lower levels of the tree always
- come first in the result.
- malloc's and realloc's in this file are transformed to
- xmalloc and xrealloc respectively by the same sed command in the
- makefile that remaps any other malloc/realloc inserted by the parser
- generator. Doing this with #defines and trying to control the interaction
- with include files (<malloc.h> and <stdlib.h> for example) just became
- too messy, particularly when such includes can be inserted at random
- times by the parser generator. */
- %{
- #include "defs.h"
- #include <ctype.h>
- #include "expression.h"
- #include "value.h"
- #include "parser-defs.h"
- #include "language.h"
- #include "ada-lang.h"
- #include "bfd.h" /* Required by objfiles.h. */
- #include "symfile.h" /* Required by objfiles.h. */
- #include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
- #include "frame.h"
- #include "block.h"
- #include "ada-exp.h"
- #define parse_type(ps) builtin_type (ps->gdbarch ())
- /* Remap normal yacc parser interface names (yyparse, yylex, yyerror,
- etc). */
- #define GDB_YY_REMAP_PREFIX ada_
- #include "yy-remap.h"
- struct name_info {
- struct symbol *sym;
- struct minimal_symbol *msym;
- const struct block *block;
- struct stoken stoken;
- };
- /* The state of the parser, used internally when we are parsing the
- expression. */
- static struct parser_state *pstate = NULL;
- /* The original expression string. */
- static const char *original_expr;
- int yyparse (void);
- static int yylex (void);
- static void yyerror (const char *);
- static void write_int (struct parser_state *, LONGEST, struct type *);
- static void write_object_renaming (struct parser_state *,
- const struct block *, const char *, int,
- const char *, int);
- static struct type* write_var_or_type (struct parser_state *,
- const struct block *, struct stoken);
- static struct type *write_var_or_type_completion (struct parser_state *,
- const struct block *,
- struct stoken);
- static void write_name_assoc (struct parser_state *, struct stoken);
- static const struct block *block_lookup (const struct block *, const char *);
- static void write_ambiguous_var (struct parser_state *,
- const struct block *, const char *, int);
- static struct type *type_int (struct parser_state *);
- static struct type *type_long (struct parser_state *);
- static struct type *type_long_long (struct parser_state *);
- static struct type *type_long_double (struct parser_state *);
- static struct type *type_for_char (struct parser_state *, ULONGEST);
- static struct type *type_boolean (struct parser_state *);
- static struct type *type_system_address (struct parser_state *);
- static std::string find_completion_bounds (struct parser_state *);
- using namespace expr;
- /* Handle Ada type resolution for OP. DEPROCEDURE_P and CONTEXT_TYPE
- are passed to the resolve method, if called. */
- static operation_up
- resolve (operation_up &&op, bool deprocedure_p, struct type *context_type)
- {
- operation_up result = std::move (op);
- ada_resolvable *res = dynamic_cast<ada_resolvable *> (result.get ());
- if (res != nullptr)
- return res->replace (std::move (result),
- pstate->expout.get (),
- deprocedure_p,
- pstate->parse_completion,
- pstate->block_tracker,
- context_type);
- return result;
- }
- /* Like parser_state::pop, but handles Ada type resolution.
- DEPROCEDURE_P and CONTEXT_TYPE are passed to the resolve method, if
- called. */
- static operation_up
- ada_pop (bool deprocedure_p = true, struct type *context_type = nullptr)
- {
- /* Of course it's ok to call parser_state::pop here... */
- return resolve (pstate->pop (), deprocedure_p, context_type);
- }
- /* Like parser_state::wrap, but use ada_pop to pop the value. */
- template<typename T>
- void
- ada_wrap ()
- {
- operation_up arg = ada_pop ();
- pstate->push_new<T> (std::move (arg));
- }
- /* Create and push an address-of operation, as appropriate for Ada.
- If TYPE is not NULL, the resulting operation will be wrapped in a
- cast to TYPE. */
- static void
- ada_addrof (struct type *type = nullptr)
- {
- operation_up arg = ada_pop (false);
- operation_up addr = make_operation<unop_addr_operation> (std::move (arg));
- operation_up wrapped
- = make_operation<ada_wrapped_operation> (std::move (addr));
- if (type != nullptr)
- wrapped = make_operation<unop_cast_operation> (std::move (wrapped), type);
- pstate->push (std::move (wrapped));
- }
- /* Handle operator overloading. Either returns a function all
- operation wrapping the arguments, or it returns null, leaving the
- caller to construct the appropriate operation. If RHS is null, a
- unary operator is assumed. */
- static operation_up
- maybe_overload (enum exp_opcode op, operation_up &lhs, operation_up &rhs)
- {
- struct value *args[2];
- int nargs = 1;
- args[0] = lhs->evaluate (nullptr, pstate->expout.get (),
- EVAL_AVOID_SIDE_EFFECTS);
- if (rhs == nullptr)
- args[1] = nullptr;
- else
- {
- args[1] = rhs->evaluate (nullptr, pstate->expout.get (),
- EVAL_AVOID_SIDE_EFFECTS);
- ++nargs;
- }
- block_symbol fn = ada_find_operator_symbol (op, pstate->parse_completion,
- nargs, args);
- if (fn.symbol == nullptr)
- return {};
- if (symbol_read_needs_frame (fn.symbol))
- pstate->block_tracker->update (fn.block, INNERMOST_BLOCK_FOR_SYMBOLS);
- operation_up callee = make_operation<ada_var_value_operation> (fn);
- std::vector<operation_up> argvec;
- argvec.push_back (std::move (lhs));
- if (rhs != nullptr)
- argvec.push_back (std::move (rhs));
- return make_operation<ada_funcall_operation> (std::move (callee),
- std::move (argvec));
- }
- /* Like parser_state::wrap, but use ada_pop to pop the value, and
- handle unary overloading. */
- template<typename T>
- void
- ada_wrap_overload (enum exp_opcode op)
- {
- operation_up arg = ada_pop ();
- operation_up empty;
- operation_up call = maybe_overload (op, arg, empty);
- if (call == nullptr)
- call = make_operation<T> (std::move (arg));
- pstate->push (std::move (call));
- }
- /* A variant of parser_state::wrap2 that uses ada_pop to pop both
- operands, and then pushes a new Ada-wrapped operation of the
- template type T. */
- template<typename T>
- void
- ada_un_wrap2 (enum exp_opcode op)
- {
- operation_up rhs = ada_pop ();
- operation_up lhs = ada_pop ();
- operation_up wrapped = maybe_overload (op, lhs, rhs);
- if (wrapped == nullptr)
- {
- wrapped = make_operation<T> (std::move (lhs), std::move (rhs));
- wrapped = make_operation<ada_wrapped_operation> (std::move (wrapped));
- }
- pstate->push (std::move (wrapped));
- }
- /* A variant of parser_state::wrap2 that uses ada_pop to pop both
- operands. Unlike ada_un_wrap2, ada_wrapped_operation is not
- used. */
- template<typename T>
- void
- ada_wrap2 (enum exp_opcode op)
- {
- operation_up rhs = ada_pop ();
- operation_up lhs = ada_pop ();
- operation_up call = maybe_overload (op, lhs, rhs);
- if (call == nullptr)
- call = make_operation<T> (std::move (lhs), std::move (rhs));
- pstate->push (std::move (call));
- }
- /* A variant of parser_state::wrap2 that uses ada_pop to pop both
- operands. OP is also passed to the constructor of the new binary
- operation. */
- template<typename T>
- void
- ada_wrap_op (enum exp_opcode op)
- {
- operation_up rhs = ada_pop ();
- operation_up lhs = ada_pop ();
- operation_up call = maybe_overload (op, lhs, rhs);
- if (call == nullptr)
- call = make_operation<T> (op, std::move (lhs), std::move (rhs));
- pstate->push (std::move (call));
- }
- /* Pop three operands using ada_pop, then construct a new ternary
- operation of type T and push it. */
- template<typename T>
- void
- ada_wrap3 ()
- {
- operation_up rhs = ada_pop ();
- operation_up mid = ada_pop ();
- operation_up lhs = ada_pop ();
- pstate->push_new<T> (std::move (lhs), std::move (mid), std::move (rhs));
- }
- /* Pop NARGS operands, then a callee operand, and use these to
- construct and push a new Ada function call operation. */
- static void
- ada_funcall (int nargs)
- {
- /* We use the ordinary pop here, because we're going to do
- resolution in a separate step, in order to handle array
- indices. */
- std::vector<operation_up> args = pstate->pop_vector (nargs);
- /* Call parser_state::pop here, because we don't want to
- function-convert the callee slot of a call we're already
- constructing. */
- operation_up callee = pstate->pop ();
- ada_var_value_operation *vvo
- = dynamic_cast<ada_var_value_operation *> (callee.get ());
- int array_arity = 0;
- struct type *callee_t = nullptr;
- if (vvo == nullptr
- || vvo->get_symbol ()->domain () != UNDEF_DOMAIN)
- {
- struct value *callee_v = callee->evaluate (nullptr,
- pstate->expout.get (),
- EVAL_AVOID_SIDE_EFFECTS);
- callee_t = ada_check_typedef (value_type (callee_v));
- array_arity = ada_array_arity (callee_t);
- }
- for (int i = 0; i < nargs; ++i)
- {
- struct type *subtype = nullptr;
- if (i < array_arity)
- subtype = ada_index_type (callee_t, i + 1, "array type");
- args[i] = resolve (std::move (args[i]), true, subtype);
- }
- std::unique_ptr<ada_funcall_operation> funcall
- (new ada_funcall_operation (std::move (callee), std::move (args)));
- funcall->resolve (pstate->expout.get (), true, pstate->parse_completion,
- pstate->block_tracker, nullptr);
- pstate->push (std::move (funcall));
- }
- /* The components being constructed during this parse. */
- static std::vector<ada_component_up> components;
- /* Create a new ada_component_up of the indicated type and arguments,
- and push it on the global 'components' vector. */
- template<typename T, typename... Arg>
- void
- push_component (Arg... args)
- {
- components.emplace_back (new T (std::forward<Arg> (args)...));
- }
- /* Examine the final element of the 'components' vector, and return it
- as a pointer to an ada_choices_component. The caller is
- responsible for ensuring that the final element is in fact an
- ada_choices_component. */
- static ada_choices_component *
- choice_component ()
- {
- ada_component *last = components.back ().get ();
- ada_choices_component *result = dynamic_cast<ada_choices_component *> (last);
- gdb_assert (result != nullptr);
- return result;
- }
- /* Pop the most recent component from the global stack, and return
- it. */
- static ada_component_up
- pop_component ()
- {
- ada_component_up result = std::move (components.back ());
- components.pop_back ();
- return result;
- }
- /* Pop the N most recent components from the global stack, and return
- them in a vector. */
- static std::vector<ada_component_up>
- pop_components (int n)
- {
- std::vector<ada_component_up> result (n);
- for (int i = 1; i <= n; ++i)
- result[n - i] = pop_component ();
- return result;
- }
- /* The associations being constructed during this parse. */
- static std::vector<ada_association_up> associations;
- /* Create a new ada_association_up of the indicated type and
- arguments, and push it on the global 'associations' vector. */
- template<typename T, typename... Arg>
- void
- push_association (Arg... args)
- {
- associations.emplace_back (new T (std::forward<Arg> (args)...));
- }
- /* Pop the most recent association from the global stack, and return
- it. */
- static ada_association_up
- pop_association ()
- {
- ada_association_up result = std::move (associations.back ());
- associations.pop_back ();
- return result;
- }
- /* Pop the N most recent associations from the global stack, and
- return them in a vector. */
- static std::vector<ada_association_up>
- pop_associations (int n)
- {
- std::vector<ada_association_up> result (n);
- for (int i = 1; i <= n; ++i)
- result[n - i] = pop_association ();
- return result;
- }
- /* Expression completer for attributes. */
- struct ada_tick_completer : public expr_completion_base
- {
- explicit ada_tick_completer (std::string &&name)
- : m_name (std::move (name))
- {
- }
- bool complete (struct expression *exp,
- completion_tracker &tracker) override;
- private:
- std::string m_name;
- };
- /* Make a new ada_tick_completer and wrap it in a unique pointer. */
- static std::unique_ptr<expr_completion_base>
- make_tick_completer (struct stoken tok)
- {
- return (std::unique_ptr<expr_completion_base>
- (new ada_tick_completer (std::string (tok.ptr, tok.length))));
- }
- %}
- %union
- {
- LONGEST lval;
- struct {
- LONGEST val;
- struct type *type;
- } typed_val;
- struct {
- gdb_byte val[16];
- struct type *type;
- } typed_val_float;
- struct type *tval;
- struct stoken sval;
- const struct block *bval;
- struct internalvar *ivar;
- }
- %type <lval> positional_list component_groups component_associations
- %type <lval> aggregate_component_list
- %type <tval> var_or_type type_prefix opt_type_prefix
- %token <typed_val> INT NULL_PTR CHARLIT
- %token <typed_val_float> FLOAT
- %token TRUEKEYWORD FALSEKEYWORD
- %token COLONCOLON
- %token <sval> STRING NAME DOT_ID TICK_COMPLETE DOT_COMPLETE NAME_COMPLETE
- %type <bval> block
- %type <lval> arglist tick_arglist
- /* Special type cases, put in to allow the parser to distinguish different
- legal basetypes. */
- %token <sval> DOLLAR_VARIABLE
- %nonassoc ASSIGN
- %left _AND_ OR XOR THEN ELSE
- %left '=' NOTEQUAL '<' '>' LEQ GEQ IN DOTDOT
- %left '@'
- %left '+' '-' '&'
- %left UNARY
- %left '*' '/' MOD REM
- %right STARSTAR ABS NOT
- /* Artificial token to give NAME => ... and NAME | priority over reducing
- NAME to <primary> and to give <primary>' priority over reducing <primary>
- to <simple_exp>. */
- %nonassoc VAR
- %nonassoc ARROW '|'
- %right TICK_ACCESS TICK_ADDRESS TICK_FIRST TICK_LAST TICK_LENGTH
- %right TICK_MAX TICK_MIN TICK_MODULUS
- %right TICK_POS TICK_RANGE TICK_SIZE TICK_TAG TICK_VAL
- %right TICK_COMPLETE
- /* The following are right-associative only so that reductions at this
- precedence have lower precedence than '.' and '('. The syntax still
- forces a.b.c, e.g., to be LEFT-associated. */
- %right '.' '(' '[' DOT_ID DOT_COMPLETE
- %token NEW OTHERS
- %%
- start : exp1
- ;
- /* Expressions, including the sequencing operator. */
- exp1 : exp
- | exp1 ';' exp
- { ada_wrap2<comma_operation> (BINOP_COMMA); }
- | primary ASSIGN exp /* Extension for convenience */
- {
- operation_up rhs = pstate->pop ();
- operation_up lhs = ada_pop ();
- value *lhs_val
- = lhs->evaluate (nullptr, pstate->expout.get (),
- EVAL_AVOID_SIDE_EFFECTS);
- rhs = resolve (std::move (rhs), true,
- value_type (lhs_val));
- pstate->push_new<ada_assign_operation>
- (std::move (lhs), std::move (rhs));
- }
- ;
- /* Expressions, not including the sequencing operator. */
- primary : primary DOT_ID
- {
- if (strcmp ($2.ptr, "all") == 0)
- ada_wrap<ada_unop_ind_operation> ();
- else
- {
- operation_up arg = ada_pop ();
- pstate->push_new<ada_structop_operation>
- (std::move (arg), copy_name ($2));
- }
- }
- ;
- primary : primary DOT_COMPLETE
- {
- /* This is done even for ".all", because
- that might be a prefix. */
- operation_up arg = ada_pop ();
- ada_structop_operation *str_op
- = (new ada_structop_operation
- (std::move (arg), copy_name ($2)));
- str_op->set_prefix (find_completion_bounds (pstate));
- pstate->push (operation_up (str_op));
- pstate->mark_struct_expression (str_op);
- }
- ;
- primary : primary '(' arglist ')'
- { ada_funcall ($3); }
- | var_or_type '(' arglist ')'
- {
- if ($1 != NULL)
- {
- if ($3 != 1)
- error (_("Invalid conversion"));
- operation_up arg = ada_pop ();
- pstate->push_new<unop_cast_operation>
- (std::move (arg), $1);
- }
- else
- ada_funcall ($3);
- }
- ;
- primary : var_or_type '\'' '(' exp ')'
- {
- if ($1 == NULL)
- error (_("Type required for qualification"));
- operation_up arg = ada_pop (true,
- check_typedef ($1));
- pstate->push_new<ada_qual_operation>
- (std::move (arg), $1);
- }
- ;
- primary :
- primary '(' simple_exp DOTDOT simple_exp ')'
- { ada_wrap3<ada_ternop_slice_operation> (); }
- | var_or_type '(' simple_exp DOTDOT simple_exp ')'
- { if ($1 == NULL)
- ada_wrap3<ada_ternop_slice_operation> ();
- else
- error (_("Cannot slice a type"));
- }
- ;
- primary : '(' exp1 ')' { }
- ;
- /* The following rule causes a conflict with the type conversion
- var_or_type (exp)
- To get around it, we give '(' higher priority and add bridge rules for
- var_or_type (exp, exp, ...)
- var_or_type (exp .. exp)
- We also have the action for var_or_type(exp) generate a function call
- when the first symbol does not denote a type. */
- primary : var_or_type %prec VAR
- { if ($1 != NULL)
- pstate->push_new<type_operation> ($1);
- }
- ;
- primary : DOLLAR_VARIABLE /* Various GDB extensions */
- { pstate->push_dollar ($1); }
- ;
- primary : aggregate
- {
- pstate->push_new<ada_aggregate_operation>
- (pop_component ());
- }
- ;
- simple_exp : primary
- ;
- simple_exp : '-' simple_exp %prec UNARY
- { ada_wrap_overload<ada_neg_operation> (UNOP_NEG); }
- ;
- simple_exp : '+' simple_exp %prec UNARY
- {
- operation_up arg = ada_pop ();
- operation_up empty;
- /* If an overloaded operator was found, use
- it. Otherwise, unary + has no effect and
- the argument can be pushed instead. */
- operation_up call = maybe_overload (UNOP_PLUS, arg,
- empty);
- if (call != nullptr)
- arg = std::move (call);
- pstate->push (std::move (arg));
- }
- ;
- simple_exp : NOT simple_exp %prec UNARY
- {
- ada_wrap_overload<unary_logical_not_operation>
- (UNOP_LOGICAL_NOT);
- }
- ;
- simple_exp : ABS simple_exp %prec UNARY
- { ada_wrap_overload<ada_abs_operation> (UNOP_ABS); }
- ;
- arglist : { $$ = 0; }
- ;
- arglist : exp
- { $$ = 1; }
- | NAME ARROW exp
- { $$ = 1; }
- | arglist ',' exp
- { $$ = $1 + 1; }
- | arglist ',' NAME ARROW exp
- { $$ = $1 + 1; }
- ;
- primary : '{' var_or_type '}' primary %prec '.'
- /* GDB extension */
- {
- if ($2 == NULL)
- error (_("Type required within braces in coercion"));
- operation_up arg = ada_pop ();
- pstate->push_new<unop_memval_operation>
- (std::move (arg), $2);
- }
- ;
- /* Binary operators in order of decreasing precedence. */
- simple_exp : simple_exp STARSTAR simple_exp
- { ada_wrap2<ada_binop_exp_operation> (BINOP_EXP); }
- ;
- simple_exp : simple_exp '*' simple_exp
- { ada_wrap2<ada_binop_mul_operation> (BINOP_MUL); }
- ;
- simple_exp : simple_exp '/' simple_exp
- { ada_wrap2<ada_binop_div_operation> (BINOP_DIV); }
- ;
- simple_exp : simple_exp REM simple_exp /* May need to be fixed to give correct Ada REM */
- { ada_wrap2<ada_binop_rem_operation> (BINOP_REM); }
- ;
- simple_exp : simple_exp MOD simple_exp
- { ada_wrap2<ada_binop_mod_operation> (BINOP_MOD); }
- ;
- simple_exp : simple_exp '@' simple_exp /* GDB extension */
- { ada_wrap2<repeat_operation> (BINOP_REPEAT); }
- ;
- simple_exp : simple_exp '+' simple_exp
- { ada_wrap_op<ada_binop_addsub_operation> (BINOP_ADD); }
- ;
- simple_exp : simple_exp '&' simple_exp
- { ada_wrap2<ada_concat_operation> (BINOP_CONCAT); }
- ;
- simple_exp : simple_exp '-' simple_exp
- { ada_wrap_op<ada_binop_addsub_operation> (BINOP_SUB); }
- ;
- relation : simple_exp
- ;
- relation : simple_exp '=' simple_exp
- { ada_wrap_op<ada_binop_equal_operation> (BINOP_EQUAL); }
- ;
- relation : simple_exp NOTEQUAL simple_exp
- { ada_wrap_op<ada_binop_equal_operation> (BINOP_NOTEQUAL); }
- ;
- relation : simple_exp LEQ simple_exp
- { ada_un_wrap2<leq_operation> (BINOP_LEQ); }
- ;
- relation : simple_exp IN simple_exp DOTDOT simple_exp
- { ada_wrap3<ada_ternop_range_operation> (); }
- | simple_exp IN primary TICK_RANGE tick_arglist
- {
- operation_up rhs = ada_pop ();
- operation_up lhs = ada_pop ();
- pstate->push_new<ada_binop_in_bounds_operation>
- (std::move (lhs), std::move (rhs), $5);
- }
- | simple_exp IN var_or_type %prec TICK_ACCESS
- {
- if ($3 == NULL)
- error (_("Right operand of 'in' must be type"));
- operation_up arg = ada_pop ();
- pstate->push_new<ada_unop_range_operation>
- (std::move (arg), $3);
- }
- | simple_exp NOT IN simple_exp DOTDOT simple_exp
- { ada_wrap3<ada_ternop_range_operation> ();
- ada_wrap<unary_logical_not_operation> (); }
- | simple_exp NOT IN primary TICK_RANGE tick_arglist
- {
- operation_up rhs = ada_pop ();
- operation_up lhs = ada_pop ();
- pstate->push_new<ada_binop_in_bounds_operation>
- (std::move (lhs), std::move (rhs), $6);
- ada_wrap<unary_logical_not_operation> ();
- }
- | simple_exp NOT IN var_or_type %prec TICK_ACCESS
- {
- if ($4 == NULL)
- error (_("Right operand of 'in' must be type"));
- operation_up arg = ada_pop ();
- pstate->push_new<ada_unop_range_operation>
- (std::move (arg), $4);
- ada_wrap<unary_logical_not_operation> ();
- }
- ;
- relation : simple_exp GEQ simple_exp
- { ada_un_wrap2<geq_operation> (BINOP_GEQ); }
- ;
- relation : simple_exp '<' simple_exp
- { ada_un_wrap2<less_operation> (BINOP_LESS); }
- ;
- relation : simple_exp '>' simple_exp
- { ada_un_wrap2<gtr_operation> (BINOP_GTR); }
- ;
- exp : relation
- | and_exp
- | and_then_exp
- | or_exp
- | or_else_exp
- | xor_exp
- ;
- and_exp :
- relation _AND_ relation
- { ada_wrap2<ada_bitwise_and_operation>
- (BINOP_BITWISE_AND); }
- | and_exp _AND_ relation
- { ada_wrap2<ada_bitwise_and_operation>
- (BINOP_BITWISE_AND); }
- ;
- and_then_exp :
- relation _AND_ THEN relation
- { ada_wrap2<logical_and_operation>
- (BINOP_LOGICAL_AND); }
- | and_then_exp _AND_ THEN relation
- { ada_wrap2<logical_and_operation>
- (BINOP_LOGICAL_AND); }
- ;
- or_exp :
- relation OR relation
- { ada_wrap2<ada_bitwise_ior_operation>
- (BINOP_BITWISE_IOR); }
- | or_exp OR relation
- { ada_wrap2<ada_bitwise_ior_operation>
- (BINOP_BITWISE_IOR); }
- ;
- or_else_exp :
- relation OR ELSE relation
- { ada_wrap2<logical_or_operation> (BINOP_LOGICAL_OR); }
- | or_else_exp OR ELSE relation
- { ada_wrap2<logical_or_operation> (BINOP_LOGICAL_OR); }
- ;
- xor_exp : relation XOR relation
- { ada_wrap2<ada_bitwise_xor_operation>
- (BINOP_BITWISE_XOR); }
- | xor_exp XOR relation
- { ada_wrap2<ada_bitwise_xor_operation>
- (BINOP_BITWISE_XOR); }
- ;
- /* Primaries can denote types (OP_TYPE). In cases such as
- primary TICK_ADDRESS, where a type would be invalid, it will be
- caught when evaluate_subexp in ada-lang.c tries to evaluate the
- primary, expecting a value. Precedence rules resolve the ambiguity
- in NAME TICK_ACCESS in favor of shifting to form a var_or_type. A
- construct such as aType'access'access will again cause an error when
- aType'access evaluates to a type that evaluate_subexp attempts to
- evaluate. */
- primary : primary TICK_ACCESS
- { ada_addrof (); }
- | primary TICK_ADDRESS
- { ada_addrof (type_system_address (pstate)); }
- | primary TICK_COMPLETE
- {
- pstate->mark_completion (make_tick_completer ($2));
- }
- | primary TICK_FIRST tick_arglist
- {
- operation_up arg = ada_pop ();
- pstate->push_new<ada_unop_atr_operation>
- (std::move (arg), OP_ATR_FIRST, $3);
- }
- | primary TICK_LAST tick_arglist
- {
- operation_up arg = ada_pop ();
- pstate->push_new<ada_unop_atr_operation>
- (std::move (arg), OP_ATR_LAST, $3);
- }
- | primary TICK_LENGTH tick_arglist
- {
- operation_up arg = ada_pop ();
- pstate->push_new<ada_unop_atr_operation>
- (std::move (arg), OP_ATR_LENGTH, $3);
- }
- | primary TICK_SIZE
- { ada_wrap<ada_atr_size_operation> (); }
- | primary TICK_TAG
- { ada_wrap<ada_atr_tag_operation> (); }
- | opt_type_prefix TICK_MIN '(' exp ',' exp ')'
- { ada_wrap2<ada_binop_min_operation> (BINOP_MIN); }
- | opt_type_prefix TICK_MAX '(' exp ',' exp ')'
- { ada_wrap2<ada_binop_max_operation> (BINOP_MAX); }
- | opt_type_prefix TICK_POS '(' exp ')'
- { ada_wrap<ada_pos_operation> (); }
- | type_prefix TICK_VAL '(' exp ')'
- {
- operation_up arg = ada_pop ();
- pstate->push_new<ada_atr_val_operation>
- ($1, std::move (arg));
- }
- | type_prefix TICK_MODULUS
- {
- struct type *type_arg = check_typedef ($1);
- if (!ada_is_modular_type (type_arg))
- error (_("'modulus must be applied to modular type"));
- write_int (pstate, ada_modulus (type_arg),
- TYPE_TARGET_TYPE (type_arg));
- }
- ;
- tick_arglist : %prec '('
- { $$ = 1; }
- | '(' INT ')'
- { $$ = $2.val; }
- ;
- type_prefix :
- var_or_type
- {
- if ($1 == NULL)
- error (_("Prefix must be type"));
- $$ = $1;
- }
- ;
- opt_type_prefix :
- type_prefix
- { $$ = $1; }
- | /* EMPTY */
- { $$ = parse_type (pstate)->builtin_void; }
- ;
- primary : INT
- { write_int (pstate, (LONGEST) $1.val, $1.type); }
- ;
- primary : CHARLIT
- {
- pstate->push_new<ada_char_operation> ($1.type, $1.val);
- }
- ;
- primary : FLOAT
- {
- float_data data;
- std::copy (std::begin ($1.val), std::end ($1.val),
- std::begin (data));
- pstate->push_new<float_const_operation>
- ($1.type, data);
- ada_wrap<ada_wrapped_operation> ();
- }
- ;
- primary : NULL_PTR
- {
- struct type *null_ptr_type
- = lookup_pointer_type (parse_type (pstate)->builtin_int0);
- write_int (pstate, 0, null_ptr_type);
- }
- ;
- primary : STRING
- {
- pstate->push_new<ada_string_operation>
- (copy_name ($1));
- }
- ;
- primary : TRUEKEYWORD
- { write_int (pstate, 1, type_boolean (pstate)); }
- | FALSEKEYWORD
- { write_int (pstate, 0, type_boolean (pstate)); }
- ;
- primary : NEW NAME
- { error (_("NEW not implemented.")); }
- ;
- var_or_type: NAME %prec VAR
- { $$ = write_var_or_type (pstate, NULL, $1); }
- | NAME_COMPLETE %prec VAR
- {
- $$ = write_var_or_type_completion (pstate,
- NULL,
- $1);
- }
- | block NAME %prec VAR
- { $$ = write_var_or_type (pstate, $1, $2); }
- | block NAME_COMPLETE %prec VAR
- {
- $$ = write_var_or_type_completion (pstate,
- $1,
- $2);
- }
- | NAME TICK_ACCESS
- {
- $$ = write_var_or_type (pstate, NULL, $1);
- if ($$ == NULL)
- ada_addrof ();
- else
- $$ = lookup_pointer_type ($$);
- }
- | block NAME TICK_ACCESS
- {
- $$ = write_var_or_type (pstate, $1, $2);
- if ($$ == NULL)
- ada_addrof ();
- else
- $$ = lookup_pointer_type ($$);
- }
- ;
- /* GDB extension */
- block : NAME COLONCOLON
- { $$ = block_lookup (NULL, $1.ptr); }
- | block NAME COLONCOLON
- { $$ = block_lookup ($1, $2.ptr); }
- ;
- aggregate :
- '(' aggregate_component_list ')'
- {
- std::vector<ada_component_up> components
- = pop_components ($2);
- push_component<ada_aggregate_component>
- (std::move (components));
- }
- ;
- aggregate_component_list :
- component_groups { $$ = $1; }
- | positional_list exp
- {
- push_component<ada_positional_component>
- ($1, ada_pop ());
- $$ = $1 + 1;
- }
- | positional_list component_groups
- { $$ = $1 + $2; }
- ;
- positional_list :
- exp ','
- {
- push_component<ada_positional_component>
- (0, ada_pop ());
- $$ = 1;
- }
- | positional_list exp ','
- {
- push_component<ada_positional_component>
- ($1, ada_pop ());
- $$ = $1 + 1;
- }
- ;
- component_groups:
- others { $$ = 1; }
- | component_group { $$ = 1; }
- | component_group ',' component_groups
- { $$ = $3 + 1; }
- ;
- others : OTHERS ARROW exp
- {
- push_component<ada_others_component> (ada_pop ());
- }
- ;
- component_group :
- component_associations
- {
- ada_choices_component *choices = choice_component ();
- choices->set_associations (pop_associations ($1));
- }
- ;
- /* We use this somewhat obscure definition in order to handle NAME => and
- NAME | differently from exp => and exp |. ARROW and '|' have a precedence
- above that of the reduction of NAME to var_or_type. By delaying
- decisions until after the => or '|', we convert the ambiguity to a
- resolved shift/reduce conflict. */
- component_associations :
- NAME ARROW exp
- {
- push_component<ada_choices_component> (ada_pop ());
- write_name_assoc (pstate, $1);
- $$ = 1;
- }
- | simple_exp ARROW exp
- {
- push_component<ada_choices_component> (ada_pop ());
- push_association<ada_name_association> (ada_pop ());
- $$ = 1;
- }
- | simple_exp DOTDOT simple_exp ARROW exp
- {
- push_component<ada_choices_component> (ada_pop ());
- operation_up rhs = ada_pop ();
- operation_up lhs = ada_pop ();
- push_association<ada_discrete_range_association>
- (std::move (lhs), std::move (rhs));
- $$ = 1;
- }
- | NAME '|' component_associations
- {
- write_name_assoc (pstate, $1);
- $$ = $3 + 1;
- }
- | simple_exp '|' component_associations
- {
- push_association<ada_name_association> (ada_pop ());
- $$ = $3 + 1;
- }
- | simple_exp DOTDOT simple_exp '|' component_associations
- {
- operation_up rhs = ada_pop ();
- operation_up lhs = ada_pop ();
- push_association<ada_discrete_range_association>
- (std::move (lhs), std::move (rhs));
- $$ = $5 + 1;
- }
- ;
- /* Some extensions borrowed from C, for the benefit of those who find they
- can't get used to Ada notation in GDB. */
- primary : '*' primary %prec '.'
- { ada_wrap<ada_unop_ind_operation> (); }
- | '&' primary %prec '.'
- { ada_addrof (); }
- | primary '[' exp ']'
- {
- ada_wrap2<subscript_operation> (BINOP_SUBSCRIPT);
- ada_wrap<ada_wrapped_operation> ();
- }
- ;
- %%
- /* yylex defined in ada-lex.c: Reads one token, getting characters */
- /* through lexptr. */
- /* Remap normal flex interface names (yylex) as well as gratuitiously */
- /* global symbol names, so we can have multiple flex-generated parsers */
- /* in gdb. */
- /* (See note above on previous definitions for YACC.) */
- #define yy_create_buffer ada_yy_create_buffer
- #define yy_delete_buffer ada_yy_delete_buffer
- #define yy_init_buffer ada_yy_init_buffer
- #define yy_load_buffer_state ada_yy_load_buffer_state
- #define yy_switch_to_buffer ada_yy_switch_to_buffer
- #define yyrestart ada_yyrestart
- #define yytext ada_yytext
- static struct obstack temp_parse_space;
- /* The following kludge was found necessary to prevent conflicts between */
- /* defs.h and non-standard stdlib.h files. */
- #define qsort __qsort__dummy
- #include "ada-lex.c"
- int
- ada_parse (struct parser_state *par_state)
- {
- /* Setting up the parser state. */
- scoped_restore pstate_restore = make_scoped_restore (&pstate);
- gdb_assert (par_state != NULL);
- pstate = par_state;
- original_expr = par_state->lexptr;
- scoped_restore restore_yydebug = make_scoped_restore (&yydebug,
- parser_debug);
- lexer_init (yyin); /* (Re-)initialize lexer. */
- obstack_free (&temp_parse_space, NULL);
- obstack_init (&temp_parse_space);
- components.clear ();
- associations.clear ();
- int result = yyparse ();
- if (!result)
- {
- struct type *context_type = nullptr;
- if (par_state->void_context_p)
- context_type = parse_type (par_state)->builtin_void;
- pstate->set_operation (ada_pop (true, context_type));
- }
- return result;
- }
- static void
- yyerror (const char *msg)
- {
- error (_("Error in expression, near `%s'."), pstate->lexptr);
- }
- /* Emit expression to access an instance of SYM, in block BLOCK (if
- non-NULL). */
- static void
- write_var_from_sym (struct parser_state *par_state, block_symbol sym)
- {
- if (symbol_read_needs_frame (sym.symbol))
- par_state->block_tracker->update (sym.block, INNERMOST_BLOCK_FOR_SYMBOLS);
- par_state->push_new<ada_var_value_operation> (sym);
- }
- /* Write integer or boolean constant ARG of type TYPE. */
- static void
- write_int (struct parser_state *par_state, LONGEST arg, struct type *type)
- {
- pstate->push_new<long_const_operation> (type, arg);
- ada_wrap<ada_wrapped_operation> ();
- }
- /* Emit expression corresponding to the renamed object named
- designated by RENAMED_ENTITY[0 .. RENAMED_ENTITY_LEN-1] in the
- context of ORIG_LEFT_CONTEXT, to which is applied the operations
- encoded by RENAMING_EXPR. MAX_DEPTH is the maximum number of
- cascaded renamings to allow. If ORIG_LEFT_CONTEXT is null, it
- defaults to the currently selected block. ORIG_SYMBOL is the
- symbol that originally encoded the renaming. It is needed only
- because its prefix also qualifies any index variables used to index
- or slice an array. It should not be necessary once we go to the
- new encoding entirely (FIXME pnh 7/20/2007). */
- static void
- write_object_renaming (struct parser_state *par_state,
- const struct block *orig_left_context,
- const char *renamed_entity, int renamed_entity_len,
- const char *renaming_expr, int max_depth)
- {
- char *name;
- enum { SIMPLE_INDEX, LOWER_BOUND, UPPER_BOUND } slice_state;
- struct block_symbol sym_info;
- if (max_depth <= 0)
- error (_("Could not find renamed symbol"));
- if (orig_left_context == NULL)
- orig_left_context = get_selected_block (NULL);
- name = obstack_strndup (&temp_parse_space, renamed_entity,
- renamed_entity_len);
- ada_lookup_encoded_symbol (name, orig_left_context, VAR_DOMAIN, &sym_info);
- if (sym_info.symbol == NULL)
- error (_("Could not find renamed variable: %s"), ada_decode (name).c_str ());
- else if (sym_info.symbol->aclass () == LOC_TYPEDEF)
- /* We have a renaming of an old-style renaming symbol. Don't
- trust the block information. */
- sym_info.block = orig_left_context;
- {
- const char *inner_renamed_entity;
- int inner_renamed_entity_len;
- const char *inner_renaming_expr;
- switch (ada_parse_renaming (sym_info.symbol, &inner_renamed_entity,
- &inner_renamed_entity_len,
- &inner_renaming_expr))
- {
- case ADA_NOT_RENAMING:
- write_var_from_sym (par_state, sym_info);
- break;
- case ADA_OBJECT_RENAMING:
- write_object_renaming (par_state, sym_info.block,
- inner_renamed_entity, inner_renamed_entity_len,
- inner_renaming_expr, max_depth - 1);
- break;
- default:
- goto BadEncoding;
- }
- }
- slice_state = SIMPLE_INDEX;
- while (*renaming_expr == 'X')
- {
- renaming_expr += 1;
- switch (*renaming_expr) {
- case 'A':
- renaming_expr += 1;
- ada_wrap<ada_unop_ind_operation> ();
- break;
- case 'L':
- slice_state = LOWER_BOUND;
- /* FALLTHROUGH */
- case 'S':
- renaming_expr += 1;
- if (isdigit (*renaming_expr))
- {
- char *next;
- long val = strtol (renaming_expr, &next, 10);
- if (next == renaming_expr)
- goto BadEncoding;
- renaming_expr = next;
- write_int (par_state, val, type_int (par_state));
- }
- else
- {
- const char *end;
- char *index_name;
- struct block_symbol index_sym_info;
- end = strchr (renaming_expr, 'X');
- if (end == NULL)
- end = renaming_expr + strlen (renaming_expr);
- index_name = obstack_strndup (&temp_parse_space, renaming_expr,
- end - renaming_expr);
- renaming_expr = end;
- ada_lookup_encoded_symbol (index_name, orig_left_context,
- VAR_DOMAIN, &index_sym_info);
- if (index_sym_info.symbol == NULL)
- error (_("Could not find %s"), index_name);
- else if (index_sym_info.symbol->aclass () == LOC_TYPEDEF)
- /* Index is an old-style renaming symbol. */
- index_sym_info.block = orig_left_context;
- write_var_from_sym (par_state, index_sym_info);
- }
- if (slice_state == SIMPLE_INDEX)
- ada_funcall (1);
- else if (slice_state == LOWER_BOUND)
- slice_state = UPPER_BOUND;
- else if (slice_state == UPPER_BOUND)
- {
- ada_wrap3<ada_ternop_slice_operation> ();
- slice_state = SIMPLE_INDEX;
- }
- break;
- case 'R':
- {
- const char *end;
- renaming_expr += 1;
- if (slice_state != SIMPLE_INDEX)
- goto BadEncoding;
- end = strchr (renaming_expr, 'X');
- if (end == NULL)
- end = renaming_expr + strlen (renaming_expr);
- operation_up arg = ada_pop ();
- pstate->push_new<ada_structop_operation>
- (std::move (arg), std::string (renaming_expr,
- end - renaming_expr));
- renaming_expr = end;
- break;
- }
- default:
- goto BadEncoding;
- }
- }
- if (slice_state == SIMPLE_INDEX)
- return;
- BadEncoding:
- error (_("Internal error in encoding of renaming declaration"));
- }
- static const struct block*
- block_lookup (const struct block *context, const char *raw_name)
- {
- const char *name;
- struct symtab *symtab;
- const struct block *result = NULL;
- std::string name_storage;
- if (raw_name[0] == '\'')
- {
- raw_name += 1;
- name = raw_name;
- }
- else
- {
- name_storage = ada_encode (raw_name);
- name = name_storage.c_str ();
- }
- std::vector<struct block_symbol> syms
- = ada_lookup_symbol_list (name, context, VAR_DOMAIN);
- if (context == NULL
- && (syms.empty () || syms[0].symbol->aclass () != LOC_BLOCK))
- symtab = lookup_symtab (name);
- else
- symtab = NULL;
- if (symtab != NULL)
- result = BLOCKVECTOR_BLOCK (symtab->compunit ()->blockvector (),
- STATIC_BLOCK);
- else if (syms.empty () || syms[0].symbol->aclass () != LOC_BLOCK)
- {
- if (context == NULL)
- error (_("No file or function \"%s\"."), raw_name);
- else
- error (_("No function \"%s\" in specified context."), raw_name);
- }
- else
- {
- if (syms.size () > 1)
- warning (_("Function name \"%s\" ambiguous here"), raw_name);
- result = SYMBOL_BLOCK_VALUE (syms[0].symbol);
- }
- return result;
- }
- static struct symbol*
- select_possible_type_sym (const std::vector<struct block_symbol> &syms)
- {
- int i;
- int preferred_index;
- struct type *preferred_type;
-
- preferred_index = -1; preferred_type = NULL;
- for (i = 0; i < syms.size (); i += 1)
- switch (syms[i].symbol->aclass ())
- {
- case LOC_TYPEDEF:
- if (ada_prefer_type (syms[i].symbol->type (), preferred_type))
- {
- preferred_index = i;
- preferred_type = syms[i].symbol->type ();
- }
- break;
- case LOC_REGISTER:
- case LOC_ARG:
- case LOC_REF_ARG:
- case LOC_REGPARM_ADDR:
- case LOC_LOCAL:
- case LOC_COMPUTED:
- return NULL;
- default:
- break;
- }
- if (preferred_type == NULL)
- return NULL;
- return syms[preferred_index].symbol;
- }
- static struct type*
- find_primitive_type (struct parser_state *par_state, const char *name)
- {
- struct type *type;
- type = language_lookup_primitive_type (par_state->language (),
- par_state->gdbarch (),
- name);
- if (type == NULL && strcmp ("system__address", name) == 0)
- type = type_system_address (par_state);
- if (type != NULL)
- {
- /* Check to see if we have a regular definition of this
- type that just didn't happen to have been read yet. */
- 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).symbol;
- if (sym != NULL && sym->aclass () == LOC_TYPEDEF)
- type = sym->type ();
- }
- return type;
- }
- static int
- chop_selector (const char *name, int end)
- {
- int i;
- for (i = end - 1; i > 0; i -= 1)
- if (name[i] == '.' || (name[i] == '_' && name[i+1] == '_'))
- return i;
- return -1;
- }
- /* If NAME is a string beginning with a separator (either '__', or
- '.'), chop this separator and return the result; else, return
- NAME. */
- static const char *
- chop_separator (const char *name)
- {
- if (*name == '.')
- return name + 1;
- if (name[0] == '_' && name[1] == '_')
- return name + 2;
- return name;
- }
- /* Given that SELS is a string of the form (<sep><identifier>)*, where
- <sep> is '__' or '.', write the indicated sequence of
- STRUCTOP_STRUCT expression operators. Returns a pointer to the
- last operation that was pushed. */
- static ada_structop_operation *
- write_selectors (struct parser_state *par_state, const char *sels)
- {
- ada_structop_operation *result = nullptr;
- while (*sels != '\0')
- {
- const char *p = chop_separator (sels);
- sels = p;
- while (*sels != '\0' && *sels != '.'
- && (sels[0] != '_' || sels[1] != '_'))
- sels += 1;
- operation_up arg = ada_pop ();
- result = new ada_structop_operation (std::move (arg),
- std::string (p, sels - p));
- pstate->push (operation_up (result));
- }
- return result;
- }
- /* Write a variable access (OP_VAR_VALUE) to ambiguous encoded name
- NAME[0..LEN-1], in block context BLOCK, to be resolved later. Writes
- a temporary symbol that is valid until the next call to ada_parse.
- */
- static void
- write_ambiguous_var (struct parser_state *par_state,
- const struct block *block, const char *name, int len)
- {
- struct symbol *sym = new (&temp_parse_space) symbol ();
- sym->set_domain (UNDEF_DOMAIN);
- sym->set_linkage_name (obstack_strndup (&temp_parse_space, name, len));
- sym->set_language (language_ada, nullptr);
- block_symbol bsym { sym, block };
- par_state->push_new<ada_var_value_operation> (bsym);
- }
- /* A convenient wrapper around ada_get_field_index that takes
- a non NUL-terminated FIELD_NAME0 and a FIELD_NAME_LEN instead
- of a NUL-terminated field name. */
- static int
- ada_nget_field_index (const struct type *type, const char *field_name0,
- int field_name_len, int maybe_missing)
- {
- char *field_name = (char *) alloca ((field_name_len + 1) * sizeof (char));
- strncpy (field_name, field_name0, field_name_len);
- field_name[field_name_len] = '\0';
- return ada_get_field_index (type, field_name, maybe_missing);
- }
- /* If encoded_field_name is the name of a field inside symbol SYM,
- then return the type of that field. Otherwise, return NULL.
- This function is actually recursive, so if ENCODED_FIELD_NAME
- doesn't match one of the fields of our symbol, then try to see
- if ENCODED_FIELD_NAME could not be a succession of field names
- (in other words, the user entered an expression of the form
- TYPE_NAME.FIELD1.FIELD2.FIELD3), in which case we evaluate
- each field name sequentially to obtain the desired field type.
- In case of failure, we return NULL. */
- static struct type *
- get_symbol_field_type (struct symbol *sym, const char *encoded_field_name)
- {
- const char *field_name = encoded_field_name;
- const char *subfield_name;
- struct type *type = sym->type ();
- int fieldno;
- if (type == NULL || field_name == NULL)
- return NULL;
- type = check_typedef (type);
- while (field_name[0] != '\0')
- {
- field_name = chop_separator (field_name);
- fieldno = ada_get_field_index (type, field_name, 1);
- if (fieldno >= 0)
- return type->field (fieldno).type ();
- subfield_name = field_name;
- while (*subfield_name != '\0' && *subfield_name != '.'
- && (subfield_name[0] != '_' || subfield_name[1] != '_'))
- subfield_name += 1;
- if (subfield_name[0] == '\0')
- return NULL;
- fieldno = ada_nget_field_index (type, field_name,
- subfield_name - field_name, 1);
- if (fieldno < 0)
- return NULL;
- type = type->field (fieldno).type ();
- field_name = subfield_name;
- }
- return NULL;
- }
- /* Look up NAME0 (an unencoded identifier or dotted name) in BLOCK (or
- expression_block_context if NULL). If it denotes a type, return
- that type. Otherwise, write expression code to evaluate it as an
- object and return NULL. In this second case, NAME0 will, in general,
- have the form <name>(.<selector_name>)*, where <name> is an object
- or renaming encoded in the debugging data. Calls error if no
- prefix <name> matches a name in the debugging data (i.e., matches
- either a complete name or, as a wild-card match, the final
- identifier). */
- static struct type*
- write_var_or_type (struct parser_state *par_state,
- const struct block *block, struct stoken name0)
- {
- int depth;
- char *encoded_name;
- int name_len;
- if (block == NULL)
- block = par_state->expression_context_block;
- std::string name_storage = ada_encode (name0.ptr);
- name_len = name_storage.size ();
- encoded_name = obstack_strndup (&temp_parse_space, name_storage.c_str (),
- name_len);
- for (depth = 0; depth < MAX_RENAMING_CHAIN_LENGTH; depth += 1)
- {
- int tail_index;
-
- tail_index = name_len;
- while (tail_index > 0)
- {
- struct symbol *type_sym;
- struct symbol *renaming_sym;
- const char* renaming;
- int renaming_len;
- const char* renaming_expr;
- int terminator = encoded_name[tail_index];
- encoded_name[tail_index] = '\0';
- /* In order to avoid double-encoding, we want to only pass
- the decoded form to lookup functions. */
- std::string decoded_name = ada_decode (encoded_name);
- encoded_name[tail_index] = terminator;
- std::vector<struct block_symbol> syms
- = ada_lookup_symbol_list (decoded_name.c_str (), block, VAR_DOMAIN);
- type_sym = select_possible_type_sym (syms);
- if (type_sym != NULL)
- renaming_sym = type_sym;
- else if (syms.size () == 1)
- renaming_sym = syms[0].symbol;
- else
- renaming_sym = NULL;
- switch (ada_parse_renaming (renaming_sym, &renaming,
- &renaming_len, &renaming_expr))
- {
- case ADA_NOT_RENAMING:
- break;
- case ADA_PACKAGE_RENAMING:
- case ADA_EXCEPTION_RENAMING:
- case ADA_SUBPROGRAM_RENAMING:
- {
- int alloc_len = renaming_len + name_len - tail_index + 1;
- char *new_name
- = (char *) obstack_alloc (&temp_parse_space, alloc_len);
- strncpy (new_name, renaming, renaming_len);
- strcpy (new_name + renaming_len, encoded_name + tail_index);
- encoded_name = new_name;
- name_len = renaming_len + name_len - tail_index;
- goto TryAfterRenaming;
- }
- case ADA_OBJECT_RENAMING:
- write_object_renaming (par_state, block, renaming, renaming_len,
- renaming_expr, MAX_RENAMING_CHAIN_LENGTH);
- write_selectors (par_state, encoded_name + tail_index);
- return NULL;
- default:
- internal_error (__FILE__, __LINE__,
- _("impossible value from ada_parse_renaming"));
- }
- if (type_sym != NULL)
- {
- struct type *field_type;
-
- if (tail_index == name_len)
- return type_sym->type ();
- /* We have some extraneous characters after the type name.
- If this is an expression "TYPE_NAME.FIELD0.[...].FIELDN",
- then try to get the type of FIELDN. */
- field_type
- = get_symbol_field_type (type_sym, encoded_name + tail_index);
- if (field_type != NULL)
- return field_type;
- else
- error (_("Invalid attempt to select from type: \"%s\"."),
- name0.ptr);
- }
- else if (tail_index == name_len && syms.empty ())
- {
- struct type *type = find_primitive_type (par_state,
- encoded_name);
- if (type != NULL)
- return type;
- }
- if (syms.size () == 1)
- {
- write_var_from_sym (par_state, syms[0]);
- write_selectors (par_state, encoded_name + tail_index);
- return NULL;
- }
- else if (syms.empty ())
- {
- struct bound_minimal_symbol msym
- = ada_lookup_simple_minsym (decoded_name.c_str ());
- if (msym.minsym != NULL)
- {
- par_state->push_new<ada_var_msym_value_operation> (msym);
- /* Maybe cause error here rather than later? FIXME? */
- write_selectors (par_state, encoded_name + tail_index);
- return NULL;
- }
- if (tail_index == name_len
- && strncmp (encoded_name, "standard__",
- sizeof ("standard__") - 1) == 0)
- error (_("No definition of \"%s\" found."), name0.ptr);
- tail_index = chop_selector (encoded_name, tail_index);
- }
- else
- {
- write_ambiguous_var (par_state, block, encoded_name,
- tail_index);
- write_selectors (par_state, encoded_name + tail_index);
- return NULL;
- }
- }
- if (!have_full_symbols () && !have_partial_symbols () && block == NULL)
- error (_("No symbol table is loaded. Use the \"file\" command."));
- if (block == par_state->expression_context_block)
- error (_("No definition of \"%s\" in current context."), name0.ptr);
- else
- error (_("No definition of \"%s\" in specified context."), name0.ptr);
-
- TryAfterRenaming: ;
- }
- error (_("Could not find renamed symbol \"%s\""), name0.ptr);
- }
- /* Because ada_completer_word_break_characters does not contain '.' --
- and it cannot easily be added, this breaks other completions -- we
- have to recreate the completion word-splitting here, so that we can
- provide a prefix that is then used when completing field names.
- Without this, an attempt like "complete print abc.d" will give a
- result like "print def" rather than "print abc.def". */
- static std::string
- find_completion_bounds (struct parser_state *par_state)
- {
- const char *end = pstate->lexptr;
- /* First the end of the prefix. Here we stop at the token start or
- at '.' or space. */
- for (; end > original_expr && end[-1] != '.' && !isspace (end[-1]); --end)
- {
- /* Nothing. */
- }
- /* Now find the start of the prefix. */
- const char *ptr = end;
- /* Here we allow '.'. */
- for (;
- ptr > original_expr && (ptr[-1] == '.'
- || ptr[-1] == '_'
- || (ptr[-1] >= 'a' && ptr[-1] <= 'z')
- || (ptr[-1] >= 'A' && ptr[-1] <= 'Z')
- || (ptr[-1] & 0xff) >= 0x80);
- --ptr)
- {
- /* Nothing. */
- }
- /* ... except, skip leading spaces. */
- ptr = skip_spaces (ptr);
- return std::string (ptr, end);
- }
- /* A wrapper for write_var_or_type that is used specifically when
- completion is requested for the last of a sequence of
- identifiers. */
- static struct type *
- write_var_or_type_completion (struct parser_state *par_state,
- const struct block *block, struct stoken name0)
- {
- int tail_index = chop_selector (name0.ptr, name0.length);
- /* If there's no separator, just defer to ordinary symbol
- completion. */
- if (tail_index == -1)
- return write_var_or_type (par_state, block, name0);
- std::string copy (name0.ptr, tail_index);
- struct type *type = write_var_or_type (par_state, block,
- { copy.c_str (),
- (int) copy.length () });
- /* For completion purposes, it's enough that we return a type
- here. */
- if (type != nullptr)
- return type;
- ada_structop_operation *op = write_selectors (par_state,
- name0.ptr + tail_index);
- op->set_prefix (find_completion_bounds (par_state));
- par_state->mark_struct_expression (op);
- return nullptr;
- }
- /* Write a left side of a component association (e.g., NAME in NAME =>
- exp). If NAME has the form of a selected component, write it as an
- ordinary expression. If it is a simple variable that unambiguously
- corresponds to exactly one symbol that does not denote a type or an
- object renaming, also write it normally as an OP_VAR_VALUE.
- Otherwise, write it as an OP_NAME.
- Unfortunately, we don't know at this point whether NAME is supposed
- to denote a record component name or the value of an array index.
- Therefore, it is not appropriate to disambiguate an ambiguous name
- as we normally would, nor to replace a renaming with its referent.
- As a result, in the (one hopes) rare case that one writes an
- aggregate such as (R => 42) where R renames an object or is an
- ambiguous name, one must write instead ((R) => 42). */
-
- static void
- write_name_assoc (struct parser_state *par_state, struct stoken name)
- {
- if (strchr (name.ptr, '.') == NULL)
- {
- std::vector<struct block_symbol> syms
- = ada_lookup_symbol_list (name.ptr,
- par_state->expression_context_block,
- VAR_DOMAIN);
- if (syms.size () != 1 || syms[0].symbol->aclass () == LOC_TYPEDEF)
- pstate->push_new<ada_string_operation> (copy_name (name));
- else
- write_var_from_sym (par_state, syms[0]);
- }
- else
- if (write_var_or_type (par_state, NULL, name) != NULL)
- error (_("Invalid use of type."));
- push_association<ada_name_association> (ada_pop ());
- }
- static struct type *
- type_int (struct parser_state *par_state)
- {
- return parse_type (par_state)->builtin_int;
- }
- static struct type *
- type_long (struct parser_state *par_state)
- {
- return parse_type (par_state)->builtin_long;
- }
- static struct type *
- type_long_long (struct parser_state *par_state)
- {
- return parse_type (par_state)->builtin_long_long;
- }
- static struct type *
- type_long_double (struct parser_state *par_state)
- {
- return parse_type (par_state)->builtin_long_double;
- }
- static struct type *
- type_for_char (struct parser_state *par_state, ULONGEST value)
- {
- if (value <= 0xff)
- return language_string_char_type (par_state->language (),
- par_state->gdbarch ());
- else if (value <= 0xffff)
- return language_lookup_primitive_type (par_state->language (),
- par_state->gdbarch (),
- "wide_character");
- return language_lookup_primitive_type (par_state->language (),
- par_state->gdbarch (),
- "wide_wide_character");
- }
- static struct type *
- type_boolean (struct parser_state *par_state)
- {
- return parse_type (par_state)->builtin_bool;
- }
- static struct type *
- type_system_address (struct parser_state *par_state)
- {
- struct type *type
- = language_lookup_primitive_type (par_state->language (),
- par_state->gdbarch (),
- "system__address");
- return type != NULL ? type : parse_type (par_state)->builtin_data_ptr;
- }
- void _initialize_ada_exp ();
- void
- _initialize_ada_exp ()
- {
- obstack_init (&temp_parse_space);
- }
|