Merge github.com:eclipse/titan.core
[deliverable/titan.core.git] / compiler2 / asn1 / TableConstraint.cc
1 /******************************************************************************
2 * Copyright (c) 2000-2016 Ericsson Telecom AB
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * Balasko, Jeno
10 * Delic, Adam
11 * Raduly, Csaba
12 *
13 ******************************************************************************/
14 #include "TableConstraint.hh"
15 #include "../Identifier.hh"
16 #include "Object.hh"
17 #include "Ref.hh"
18 #include "TokenBuf.hh"
19 // FIXME TableConstraint does not use Token or TokenBuf at all.
20 // TokenBuf.hh just happens to drag in everything that TableConstraint needs.
21
22 #include "../CompField.hh"
23
24 namespace Asn {
25
26 // =================================
27 // ===== AtNotation
28 // =================================
29
30 AtNotation::AtNotation(int p_levels, FieldName *p_cids)
31 : Node(), levels(p_levels), cids(p_cids), oc_fieldname(0),
32 firstcomp(0), lastcomp(0)
33 {
34 if(!p_cids)
35 FATAL_ERROR("NULL parameter: Asn::AtNotation::AtNotation()");
36 }
37
38 AtNotation::AtNotation(const AtNotation& p)
39 : Node(p), levels(p.levels), oc_fieldname(0),
40 firstcomp(0), lastcomp(0)
41 {
42 cids=p.cids->clone();
43 }
44
45 AtNotation::~AtNotation()
46 {
47 delete cids;
48 delete oc_fieldname;
49 }
50
51 void AtNotation::set_oc_fieldname(const Identifier& p_oc_fieldname)
52 {
53 if(oc_fieldname)
54 FATAL_ERROR("Asn::AtNotation::set_ocfieldname()");
55 oc_fieldname=p_oc_fieldname.clone();
56 }
57
58 string AtNotation::get_dispname() const
59 {
60 string s('@');
61 for(int i=0; i<levels; i++) s+=".";
62 s+=cids->get_dispname();
63 return s;
64 }
65
66 // =================================
67 // ===== AtNotations
68 // =================================
69
70 AtNotations::AtNotations(const AtNotations& p)
71 : Node(p)
72 {
73 for(size_t i=0; i<p.ans.size(); i++)
74 ans.add(p.ans[i]->clone());
75 }
76
77 AtNotations::~AtNotations()
78 {
79 for(size_t i=0; i<ans.size(); i++) delete ans[i];
80 ans.clear();
81 }
82
83 void AtNotations::add_an(AtNotation *p_an)
84 {
85 if(!p_an)
86 FATAL_ERROR("NULL parameter: Asn::AtNotations::add_an()");
87 ans.add(p_an);
88 }
89
90 // =================================
91 // ===== TableConstraint
92 // =================================
93
94 TableConstraint::TableConstraint(Block *p_block_os, Block *p_block_ans)
95 : Constraint(CT_TABLE), block_os(p_block_os), block_ans(p_block_ans),
96 os(0), ans(0), consdtype(0), oc_fieldname(0)
97 {
98 if(!block_os)
99 FATAL_ERROR("NULL parameter: Asn::TableConstraint::TableConstraint()");
100 }
101
102 TableConstraint::TableConstraint(const TableConstraint& p)
103 : Constraint(p), consdtype(0), oc_fieldname(0)
104 {
105 block_os=p.block_os?p.block_os->clone():0;
106 block_ans=p.block_ans?p.block_ans->clone():0;
107 os=p.os?p.os->clone():0;
108 ans=p.ans?p.ans->clone():0;
109 }
110
111 TableConstraint::~TableConstraint()
112 {
113 delete block_os;
114 delete block_ans;
115 delete os;
116 delete ans;
117 }
118
119 void TableConstraint::chk()
120 {
121 if(checked) return;
122 checked=true;
123 parse_blocks();
124 if(!my_type)
125 FATAL_ERROR("Asn::TableConstraint::chk()");
126 os->set_my_scope(my_type->get_my_scope());
127 os->set_fullname(my_type->get_fullname()+".<tableconstraint-os>");
128 os->set_genname(my_type->get_genname_own(), string("os"));
129 // search the constrained type (not the reference to it)
130 consdtype=my_type;
131 bool ok=false;
132 while(true) {
133 Type::typetype_t t=consdtype->get_typetype();
134 if(t==Type::T_OPENTYPE || t==Type::T_OCFT) {
135 ok=true;
136 break;
137 }
138 else if(t==Type::T_ERROR) {
139 return;
140 }
141 else if(consdtype->is_ref())
142 consdtype=consdtype->get_type_refd();
143 else break;
144 }
145 if(!ok) {
146 my_type->error("TableConstraint can only be applied to"
147 " ObjectClassFieldType");
148 return;
149 }
150 // consdtype is ok
151 if(consdtype->get_typetype()==Type::T_OCFT) {
152 // componentrelationconstraint ignored for this...
153 oc_fieldname=&consdtype->get_oc_fieldname();
154 os->set_my_governor(consdtype->get_my_oc());
155 os->chk();
156 }
157 else if(consdtype->get_typetype()==Type::T_OPENTYPE) {
158 consdtype->set_my_tableconstraint(this);
159 oc_fieldname=&consdtype->get_oc_fieldname();
160 os->set_my_governor(consdtype->get_my_oc());
161 os->chk();
162 if(ans) {
163 // componentrelationconstraint...
164 // search the outermost textually enclosing seq, set or choice
165 Type *outermostparent=0;
166 Type *t_type=my_type;
167 do {
168 if(t_type->is_secho())
169 outermostparent=t_type;
170 } while((t_type=t_type->get_parent_type()));
171 if(!outermostparent) {
172 my_type->error("Invalid use of ComponentRelationConstraint"
173 " (cannot determine parent type)");
174 return;
175 }
176 outermostparent->set_opentype_outermost();
177 // set has_opentypes for enclosing types
178 t_type=my_type;
179 do {
180 t_type=t_type->get_parent_type();
181 t_type->set_has_opentypes();
182 } while(t_type!=outermostparent);
183 // checking of atnotations
184 for(size_t i=0; i<ans->get_nof_ans(); i++) {
185 AtNotation *an=ans->get_an_byIndex(i);
186 Type *parent = NULL;
187 if(an->get_levels()==0) parent=outermostparent;
188 else {
189 parent=my_type;
190 for(int level=an->get_levels(); level>0; level--) {
191 parent=parent->get_parent_type();
192 if(!parent) {
193 my_type->error("Too many dots. This component has only"
194 " %d parents.", an->get_levels()-level);
195 return;
196 } // ! parent
197 } // for level
198 } // not the outermost
199 t_type=parent;
200 an->set_firstcomp(parent);
201 // component identifiers... do they exist?
202 FieldName* cids=an->get_cids();
203 for(size_t j=0; j<cids->get_nof_fields(); j++) {
204 if(!t_type->is_secho()) {
205 my_type->error("Type `%s' is not a SEQUENCE, SET of CHOICE"
206 " type.", t_type->get_fullname().c_str());
207 return;
208 } // ! secho
209 const Identifier *id=cids->get_field_byIndex(j);
210 if(!t_type->has_comp_withName(*id)) {
211 my_type->error("Type `%s' has no component with name `%s'.",
212 t_type->get_fullname().c_str(),
213 id->get_dispname().c_str());
214 return;
215 } // no component with that name
216 t_type=t_type->get_comp_byName(*id)->get_type();
217 } // for j
218 an->set_lastcomp(t_type);
219 /* check if the referenced component is constrained by the
220 * same objectset... */
221 ok=false;
222 do {
223 // t_type->chk_constraints();
224 Constraints *t_cons=t_type->get_constraints();
225 if(!t_cons) break;
226 t_cons->chk_table();
227 TableConstraint *t_tc=dynamic_cast<TableConstraint*>
228 (t_cons->get_tableconstraint());
229 if(!t_tc) break;
230 Type *t_ocft=t_tc->consdtype;
231 if(t_ocft->get_typetype()!=Type::T_OCFT) break;
232 an->set_oc_fieldname(t_ocft->get_oc_fieldname());
233 // is the same objectset?
234 if(t_tc->os->get_refd_last()!=os->get_refd_last()) break;
235 ok=true;
236 } while(false);
237 if(!ok) {
238 my_type->error
239 ("The referenced components must be value (set) fields"
240 " constrained by the same objectset"
241 " as the referencing component");
242 return;
243 }
244 } // for i
245 // well, the atnotations seems to be ok, let's produce the
246 // alternatives for the opentype
247 Type *t_ot=consdtype; // opentype
248 DEBUG(1, "Adding alternatives to open type `%s'",
249 t_ot->get_fullname().c_str());
250 Objects *objs=os->get_refd_last()->get_objs();
251 for(size_t i=0; i<objs->get_nof_objs(); i++) {
252 Obj_defn *obj=objs->get_obj_byIndex(i);
253 if(!obj->has_fs_withName_dflt(*oc_fieldname))
254 continue;
255 t_type=dynamic_cast<Type*>
256 (obj->get_setting_byName_dflt(*oc_fieldname));
257 bool is_strange;
258 const Common::Identifier& altname = t_type->get_otaltname(is_strange);
259 if(!t_ot->has_comp_withName(altname)) {
260 Type * otype = new Type(Type::T_REFDSPEC, t_type);
261 otype->set_genname(t_type->get_genname_own());
262 t_ot->add_comp(new CompField(altname.clone(),
263 otype));
264 const char *dispname_str = altname.get_dispname().c_str();
265 DEBUG(2, "Alternative `%s' added", dispname_str);
266 if (is_strange)
267 t_ot->warning("Strange alternative name (`%s') was added to "
268 "open type `%s'", dispname_str, t_ot->get_fullname().c_str());
269 } // t_ot ! has the type
270 } // for i (objs)
271 t_ot->set_my_scope(t_ot->get_my_scope());
272 t_ot->set_fullname(t_ot->get_fullname());
273 t_ot->chk();
274 } // if ans
275 } // opentype check
276
277 // this cannot be inside another constraint
278 if (my_parent) {
279 error("Table constraint cannot be inside a %s", my_parent->get_name());
280 }
281
282 } // member function
283
284 void TableConstraint::parse_blocks()
285 {
286 if(block_os) {
287 if(block_ans) { // ComponentRelationConstraint
288 Node *node=block_os->parse(KW_Block_DefinedObjectSetBlock);
289 os=dynamic_cast<ObjectSet*>(node);
290 delete block_os; block_os=0;
291 node=block_ans->parse(KW_Block_AtNotationList);
292 ans=dynamic_cast<AtNotations*>(node);
293 delete block_ans; block_ans=0;
294 if(!ans)
295 /* syntax error */
296 ans=new AtNotations();
297 }
298 else { // SimpleTableConstraint
299 Node *node=block_os->parse(KW_Block_ObjectSetSpec);
300 os=dynamic_cast<ObjectSet*>(node);
301 delete block_os; block_os=0;
302 }
303 if(!os) {
304 /* syntax error */
305 os=new OS_defn();
306 }
307 }
308 }
309
310 } // namespace Asn
This page took 0.039637 seconds and 5 git commands to generate.