/****************************************************************************** * Copyright (c) 2000-2021 Ericsson Telecom AB * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v2.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html * * Contributors: * Balasko, Jeno * Baranyi, Botond * Cserveni, Akos * Feher, Csaba * Forstner, Matyas * Gecse, Roland * Raduly, Csaba * Szabados, Kristof * Szabo, Janos Zoltan – initial implementation * Tatarka, Gabor * ******************************************************************************/ #include "Ref.hh" #include "../Identifier.hh" #include "AST_asn1.hh" #include "Block.hh" #include "TokenBuf.hh" namespace Asn { // ================================= // ===== Ref_pard // ================================= Ref_pard::Ref_pard(Ref_defd_simple *p_refds, Block *p_block) : Ref_defd(), ref_parass(p_refds), block(p_block), refd_ass_is_not_pard(false), asss(0), ref_ds(0) { if (!p_refds || !p_block) FATAL_ERROR("NULL parameter: Asn::Ref_pard::Ref_pard()"); } Ref_pard::Ref_pard(const Ref_pard& p) : Ref_defd(p), refd_ass_is_not_pard(p.refd_ass_is_not_pard), asss(0), ref_ds(0) { ref_parass = p.ref_parass->clone(); block=p.block?p.block->clone():0; asss=p.asss?p.asss->clone():0; } Ref_pard::~Ref_pard() { delete ref_parass; delete block; delete asss; delete ref_ds; } Ref_pard *Ref_pard::clone() const { return new Ref_pard(*this); } void Ref_pard::set_fullname(const string& p_fullname) { Ref_defd::set_fullname(p_fullname); ref_parass->set_fullname(p_fullname); if (block) block->set_fullname(p_fullname + ".<block>"); if (asss) asss->set_fullname(p_fullname + "." + ref_parass->get_dispname() + "{}"); if (ref_ds) ref_ds->set_fullname(p_fullname); } void Ref_pard::set_my_scope(Scope *p_scope) { Ref_defd::set_my_scope(p_scope); ref_parass->set_my_scope(p_scope); if (ref_ds) ref_ds->set_my_scope(p_scope); } bool Ref_pard::get_is_erroneous() { get_ref_defd_simple(); return is_erroneous; } string Ref_pard::get_dispname() { if (ref_ds) return ref_ds->get_dispname(); else return ref_parass->get_dispname()+"{}"; } Ref_defd_simple* Ref_pard::get_ref_defd_simple() { if(ref_ds) return ref_ds; if(is_erroneous) return 0; if(refd_ass_is_not_pard) return ref_parass; Module *my_mod = dynamic_cast<Module*>(my_scope->get_scope_mod()); if(!my_mod) FATAL_ERROR("Asn::Ref_pard::get_ref_defd_simple()"); /* search the referenced parameterized assignment */ Assignment *parass=ref_parass->get_refd_ass(); if(!parass) { is_erroneous=true; delete block; block=0; return 0; } Ass_pard *ass_pard=parass->get_ass_pard(); if(!ass_pard) { /* error: this is not a parameterized assignment */ refd_ass_is_not_pard=true; delete block; block=0; return ref_parass; } size_t nof_formal_pars=ass_pard->get_nof_pars(); if(nof_formal_pars==0) { /* error in parameterized assignment */ is_erroneous=true; return 0; } Error_Context cntxt (this, "While instantiating parameterized reference `%s'", ref_parass->get_dispname().c_str()); if(block) { /* splitting the actual parameterlist */ vector<TokenBuf> act_pars; // actual parameters { TokenBuf *act_pars_tb=block->get_TokenBuf(); TokenBuf *tmp_tb=new TokenBuf(); for(bool ok=false; !ok; ) { Token *token=act_pars_tb->pop_front_token(); switch(token->get_token()) { case '\0': // EOF ok=true; // no break case ',': token->set_token('\0'); tmp_tb->push_back_token(token); act_pars.add(tmp_tb); tmp_tb=new TokenBuf(); break; default: tmp_tb->push_back_token(token); } // switch(token->token) } delete tmp_tb; delete block; block=0; } /* checking the number of parameters */ size_t nof_act_pars=act_pars.size(); if(nof_act_pars != nof_formal_pars) error("Too %s parameters: %lu was expected instead of %lu", nof_act_pars<nof_formal_pars?"few":"many", static_cast<unsigned long>( nof_formal_pars), static_cast<unsigned long>( nof_act_pars)); /* building the new assignments */ asss=new Assignments(); for(size_t i=0; i<nof_formal_pars; i++) { const Identifier& tmp_id=ass_pard->get_nth_dummyref(i); Error_Context cntxt2(this, "While examining parameter `%s'", tmp_id.get_dispname().c_str()); Assignment *tmp_ass=0; if(i<nof_act_pars) { TokenBuf *tmp_tb=ass_pard->clone_nth_governor(i); tmp_tb->move_tokens_from(act_pars[i]); tmp_tb->push_back_kw_token('\0'); Block *tmp_block=new Block(tmp_tb); Node *tmp_node=tmp_block->parse(KW_Block_Assignment); delete tmp_block; tmp_ass=dynamic_cast<Assignment*>(tmp_node); if(!tmp_ass) delete tmp_node; } // substitution of missing parameters (for error recovery) if(!tmp_ass) tmp_ass=new Ass_Error(tmp_id.clone(), 0); tmp_ass->set_location(*this); asss->add_ass(tmp_ass); } // for i for(size_t i=0; i<nof_act_pars; i++) delete act_pars[i]; act_pars.clear(); } Assignment *new_ass = parass->new_instance(my_scope->get_scope_mod_gen()); my_mod->add_ass(new_ass); const Identifier& new_ass_id = new_ass->get_id(); const string& new_ass_dispname = new_ass_id.get_dispname(); asss->set_right_scope(my_scope); asss->set_parent_scope(parass->get_my_scope()); asss->set_parent_scope_gen(my_scope); asss->set_scope_name(new_ass_dispname); asss->set_fullname(get_fullname() + "." + ref_parass->get_dispname() + "{}"); asss->chk(); new_ass->set_fullname(my_mod->get_fullname() + "." + new_ass_dispname); new_ass->set_my_scope(asss); new_ass->set_location(*this); new_ass->set_dontgen(); new_ass->chk(); if (Common::Assignment::A_TYPE == new_ass->get_asstype()) { new_ass->get_Type()->set_pard_type_instance(); } ref_ds=new Ref_defd_simple(new Identifier(my_mod->get_modid()), new Identifier(new_ass_id)); ref_ds->set_fullname(get_fullname()); ref_ds->set_my_scope(my_mod); return ref_ds; } void Ref_pard::dump(unsigned level) const { DEBUG(level, "Parameterized reference: %s", const_cast<Ref_pard*>(this)->get_dispname().c_str()); if(asss) { DEBUG(level, "with parameters"); level++; asss->dump(level); } } // ================================= // ===== FieldName // ================================= FieldName::FieldName(const FieldName& p) : Node(p) { for(size_t i=0; i<p.fields.size(); i++) add_field(p.fields[i]->clone()); } FieldName::~FieldName() { for(size_t i=0; i<fields.size(); i++) delete fields[i]; fields.clear(); } FieldName *FieldName::clone() const { return new FieldName(*this); } void FieldName::add_field(Identifier *p_id) { if(!p_id) FATAL_ERROR("NULL parameter: Asn::FieldName::add_field()"); fields.add(p_id); } string FieldName::get_dispname() const { string s; size_t nof_fields = fields.size(); for (size_t i = 0; i < nof_fields; i++) { s += '.'; s += fields[i]->get_dispname(); } return s; } // ================================= // ===== FromObj // ================================= FromObj::FromObj(Ref_defd *p_ref_defd, FieldName *p_fn) : Common::Reference(), setting(0), setting_cache(0) { if (!p_ref_defd || !p_fn) FATAL_ERROR("NULL parameter: Asn::FromObj::FromObj()"); ref_defd=p_ref_defd; fn=p_fn; } FromObj::FromObj(const FromObj& p) : Common::Reference(p), setting(0), setting_cache(0) { ref_defd=p.ref_defd->clone(); fn=p.fn->clone(); } FromObj::~FromObj() { delete ref_defd; delete fn; delete setting; } FromObj *FromObj::clone() const { return new FromObj(*this); } void FromObj::set_fullname(const string& p_fullname) { Common::Reference::set_fullname(p_fullname); ref_defd->set_fullname(p_fullname); fn->set_fullname(p_fullname + ".<fieldnames>"); } void FromObj::set_my_scope(Scope *p_scope) { Common::Reference::set_my_scope(p_scope); ref_defd->set_my_scope(p_scope); } string FromObj::get_dispname() { return ref_defd->get_dispname()+fn->get_dispname(); } bool FromObj::get_is_erroneous() { get_refd_setting(); return is_erroneous; } /** \todo enhance */ Setting* FromObj::get_refd_setting() { if(setting_cache) return setting_cache; Error_Context ec_0 (this, "In InformationFromObjects construct `%s'", get_dispname().c_str()); enum { UNKNOWN, OC, OS, O } curr = UNKNOWN; OC_defn *t_oc=0; OS_defn *t_os=0; Obj_defn *t_o=0; OS_defn *fromobjs = 0; // temporary storage size_t nof_fields = fn->get_nof_fields(); Setting *t_setting = ref_defd->get_refd_setting(); if(!t_setting) goto error; /* the first part */ switch(t_setting->get_st()) { case Setting::S_OS: { curr=OS; t_os=dynamic_cast<ObjectSet*>(t_setting)->get_refd_last(); t_oc=t_os->get_my_governor()->get_refd_last(); OSEV_objcollctr objcoll(t_os, t_oc); objcoll.visit_ObjectSet(*t_os); fromobjs=new OS_defn(objcoll.give_objs()); fromobjs->set_my_governor(t_oc); break; } case Setting::S_O: curr=O; t_o=dynamic_cast<Object*>(t_setting)->get_refd_last(); t_oc=t_o->get_my_governor()->get_refd_last(); break; case Setting::S_OC: curr=OC; t_oc=dynamic_cast<ObjectClass*>(t_setting)->get_refd_last(); break; case Setting::S_ERROR: goto error; default: error("Invalid reference `%s' " "(ObjectClass, ObjectSet or Object reference was expected)", get_dispname().c_str()); goto error; } // switch st /* the middle part */ for(size_t i=0; i<nof_fields-1; i++) { Identifier *curr_fn = fn->get_field_byIndex(i); Error_Context ec_1(this, "While examining part #%lu (`%s') of FieldName", static_cast<unsigned long> (i + 1), curr_fn->get_dispname().c_str()); FieldSpec *curr_fspec = t_oc->get_fss()->get_fs_byId(*curr_fn)->get_last(); if(curr_fspec->get_fstype()==FieldSpec::FS_ERROR) goto error; switch(curr) { case OC: switch(curr_fspec->get_fstype()) { case FieldSpec::FS_O: { FieldSpec_O *tmp_fspec= dynamic_cast<FieldSpec_O*>(curr_fspec); t_oc=tmp_fspec->get_oc()->get_refd_last(); break;} case FieldSpec::FS_OS: { FieldSpec_OS *tmp_fspec= dynamic_cast<FieldSpec_OS*>(curr_fspec); t_oc=tmp_fspec->get_oc()->get_refd_last(); break;} case FieldSpec::FS_ERROR: goto error; default: error("This notation is not permitted (object or objectset" " fieldreference was expected)"); goto error; } // switch fspec.fstype break; case OS: switch(curr_fspec->get_fstype()) { case FieldSpec::FS_O: { FieldSpec_O *tmp_fspec= dynamic_cast<FieldSpec_O*>(curr_fspec); t_oc=tmp_fspec->get_oc()->get_refd_last(); OSEV_objcollctr objcoll(this, t_oc); Objects *t_objs = fromobjs->get_objs(); for(size_t j=0; j<t_objs->get_nof_objs(); j++) { t_o=t_objs->get_obj_byIndex(j)->get_refd_last(); if(!t_o->has_fs_withName_dflt(*curr_fn)) continue; t_setting=t_o->get_setting_byName_dflt(*curr_fn); t_o=dynamic_cast<Object*>(t_setting)->get_refd_last(); objcoll.visit_Object(*t_o); } delete fromobjs; fromobjs=new OS_defn(objcoll.give_objs()); fromobjs->set_location(*this); fromobjs->set_my_governor(t_oc); break;} case FieldSpec::FS_OS: { FieldSpec_OS *tmp_fspec= dynamic_cast<FieldSpec_OS*>(curr_fspec); t_oc=tmp_fspec->get_oc()->get_refd_last(); OSEV_objcollctr objcoll(this, t_oc); Objects *t_objs = fromobjs->get_objs(); for(size_t j=0; j<t_objs->get_nof_objs(); j++) { t_o=t_objs->get_obj_byIndex(j)->get_refd_last(); if(!t_o->has_fs_withName_dflt(*curr_fn)) continue; t_setting=t_o->get_setting_byName_dflt(*curr_fn); t_os=dynamic_cast<ObjectSet*>(t_setting)->get_refd_last(); objcoll.visit_ObjectSet(*t_os); } delete fromobjs; fromobjs=new OS_defn(objcoll.give_objs()); fromobjs->set_location(*this); fromobjs->set_my_governor(t_oc); break;} case FieldSpec::FS_ERROR: goto error; default: error("This notation is not permitted (object or objectset" " fieldreference was expected)"); goto error; } // switch fspec.fstype break; case O: switch(curr_fspec->get_fstype()) { case FieldSpec::FS_O: { FieldSpec_O *tmp_fspec= dynamic_cast<FieldSpec_O*>(curr_fspec); t_oc=tmp_fspec->get_oc()->get_refd_last(); t_setting=t_o->get_setting_byName_dflt(*curr_fn); t_o=dynamic_cast<Object*>(t_setting)->get_refd_last(); break;} case FieldSpec::FS_OS: { curr=OS; FieldSpec_OS *tmp_fspec= dynamic_cast<FieldSpec_OS*>(curr_fspec); t_oc=tmp_fspec->get_oc()->get_refd_last(); OSEV_objcollctr objcoll(*fromobjs); Objects *t_objs = fromobjs->get_objs(); for(size_t j=0; j<t_objs->get_nof_objs(); j++) { t_o=t_objs->get_obj_byIndex(j)->get_refd_last(); if(!t_o->has_fs_withName_dflt(*curr_fn)) continue; t_setting=t_o->get_setting_byName_dflt(*curr_fn); t_os=dynamic_cast<ObjectSet*>(t_setting)->get_refd_last(); objcoll.visit_ObjectSet(*t_os); } delete fromobjs; fromobjs=new OS_defn(objcoll.give_objs()); fromobjs->set_location(*this); fromobjs->set_my_governor(t_oc); break;} case FieldSpec::FS_ERROR: goto error; default: error("This notation is not permitted (object or objectset" " fieldreference was expected)"); goto error; } // switch fspec.fstype break; default: FATAL_ERROR("Asn::FromObj::get_refd_setting()"); } // switch curr } // for i /* and the last part... */ { Identifier *curr_fn = fn->get_field_byIndex(nof_fields-1); Error_Context ec_1 (this, "While examining last part (`%s') of FieldName", curr_fn->get_dispname().c_str()); FieldSpec *curr_fspec = t_oc->get_fss()->get_fs_byId(*curr_fn)->get_last(); switch(curr) { case OC: switch(curr_fspec->get_fstype()) { case FieldSpec::FS_T: { Type *opentype = new Type(Type::T_OPENTYPE, t_oc, curr_fn); opentype->set_location(*this); setting = opentype; break; } case FieldSpec::FS_V_FT: { FieldSpec_V_FT *tmp_fspec= dynamic_cast<FieldSpec_V_FT*>(curr_fspec); Type *ocft = new Type(Type::T_OCFT, tmp_fspec->get_type(), t_oc, curr_fn); ocft->set_location(*this); setting = ocft; break;} case FieldSpec::FS_V_VT: case FieldSpec::FS_VS_FT: case FieldSpec::FS_VS_VT: error("Sorry, this construct is not supported"); goto error; case FieldSpec::FS_O: case FieldSpec::FS_OS: error("This notation is not permitted (type, (fixed- or" " variabletype) value or valueset fieldreference was" " expected)"); // no break case FieldSpec::FS_ERROR: goto error; default: FATAL_ERROR("Unhandled fieldspec type"); } // switch fspec.fstype break; case OS: switch(curr_fspec->get_fstype()) { case FieldSpec::FS_O: { FieldSpec_O *tmp_fspec= dynamic_cast<FieldSpec_O*>(curr_fspec); t_oc=tmp_fspec->get_oc()->get_refd_last(); OSEV_objcollctr objcoll(this, t_oc); Objects *t_objs = fromobjs->get_objs(); for(size_t j=0; j<t_objs->get_nof_objs(); j++) { t_o=t_objs->get_obj_byIndex(j)->get_refd_last(); if(!t_o->has_fs_withName_dflt(*curr_fn)) continue; t_setting=t_o->get_setting_byName_dflt(*curr_fn); t_o=dynamic_cast<Object*>(t_setting)->get_refd_last(); objcoll.visit_Object(*t_o); } delete fromobjs; fromobjs=new OS_defn(objcoll.give_objs()); fromobjs->set_location(*this); fromobjs->set_my_governor(t_oc); fromobjs->set_my_scope(my_scope); setting = fromobjs; break;} case FieldSpec::FS_OS: { FieldSpec_OS *tmp_fspec= dynamic_cast<FieldSpec_OS*>(curr_fspec); t_oc=tmp_fspec->get_oc()->get_refd_last(); OSEV_objcollctr objcoll(this, t_oc); Objects *t_objs = fromobjs->get_objs(); for(size_t j=0; j<t_objs->get_nof_objs(); j++) { t_o=t_objs->get_obj_byIndex(j)->get_refd_last(); if(!t_o->has_fs_withName_dflt(*curr_fn)) continue; t_setting=t_o->get_setting_byName_dflt(*curr_fn); t_os=dynamic_cast<ObjectSet*>(t_setting)->get_refd_last(); objcoll.visit_ObjectSet(*t_os); } delete fromobjs; fromobjs=new OS_defn(objcoll.give_objs()); fromobjs->set_location(*this); fromobjs->set_my_governor(t_oc); fromobjs->set_my_scope(my_scope); setting = fromobjs; break;} case FieldSpec::FS_V_FT: case FieldSpec::FS_VS_FT: error("Sorry, ValueSetFromObjects not supported"); // no break case FieldSpec::FS_ERROR: goto error; default: error("This notation is not permitted (object, objectset," " (fixed type) value or valueset fieldreference was" " expected)"); goto error; } // switch fspec.fstype break; case O: setting_cache = t_o->get_setting_byName_dflt(*curr_fn); break; default: FATAL_ERROR("Asn::FromObj::get_refd_setting()"); } // switch curr } // errorcontext-block if (!setting_cache) setting_cache = setting; goto end; error: delete fromobjs; is_erroneous=true; setting_cache=get_refd_setting_error(); end: return setting_cache; } Common::Assignment* FromObj::get_refd_assignment(bool check_parlist) { return ref_defd->get_refd_assignment(check_parlist); } bool FromObj::has_single_expr() { FATAL_ERROR("FromObj::has_single_expr()"); return false; } void FromObj::generate_code(expression_struct_t *) { FATAL_ERROR("FromObj::generate_code()"); } void FromObj::generate_code_const_ref(expression_struct_t */*expr*/) { FATAL_ERROR("FromObj::generate_code_const_ref()"); } } // namespace Asn