Merge pull request #1551 from DOCGroup/plm_jira_333
[ACE_TAO.git] / TAO / orbsvcs / IFR_Service / ifr_adding_visitor_union.cpp
blob37915ca0a5f8503ded24349f4447026f0157632c
1 /* -*- c++ -*- */
2 #include "orbsvcs/Log_Macros.h"
3 #include "ast_enum.h"
4 #include "ast_expression.h"
5 #include "ast_union.h"
6 #include "ast_union_branch.h"
7 #include "ast_union_label.h"
8 #include "utl_identifier.h"
10 #include "ifr_adding_visitor_union.h"
11 #include "ifr_adding_visitor_structure.h"
13 #include "tao/AnyTypeCode/Any_Unknown_IDL_Type.h"
14 #include "tao/CDR.h"
16 ifr_adding_visitor_union::ifr_adding_visitor_union (AST_Decl *scope)
17 : ifr_adding_visitor (scope)
21 ifr_adding_visitor_union::~ifr_adding_visitor_union (void)
25 // Specialized visit_scope method for unions only.
26 int
27 ifr_adding_visitor_union::visit_scope (UTL_Scope *node)
29 // If the union has members that are scopes but not unions,
30 // the regular visit_scope method should be called instead.
31 if (node->scope_node_type () != AST_Decl::NT_union)
33 return ifr_adding_visitor::visit_scope (node);
36 AST_Union *u = dynamic_cast<AST_Union*> (node);
38 CORBA::ULong const nfields = static_cast<CORBA::ULong> (u->nfields ());
40 this->members_.length (nfields);
42 AST_Field **f = 0;
44 // Index into members_.
45 CORBA::ULong index = 0;
47 try
49 // Visit each field.
50 for (CORBA::ULong i = 0; i < nfields; ++i)
52 if (u->field (f, i) != 0)
54 ORBSVCS_ERROR_RETURN ((
55 LM_ERROR,
56 ACE_TEXT ("(%N:%l) ifr_adding_visitor_union::")
57 ACE_TEXT ("visit_scope -")
58 ACE_TEXT (" field node access failed\n")
64 AST_Type *ft = (*f)->field_type ();
66 bool defined_here = ft->is_child (this->scope_);
68 // If the union member is defined in the union, we have to
69 // do some visiting - otherwise we can just look up the entry.
70 if (defined_here)
72 if (ft->node_type () == AST_Decl::NT_union)
74 // Since the enclosing scope hasn't been created yet,
75 // we make a special visitor to create this member
76 // at global scope and move it into the union later.
77 ifr_adding_visitor_union visitor (ft);
79 if (ft->ast_accept (&visitor) == -1)
81 ORBSVCS_ERROR_RETURN ((
82 LM_ERROR,
83 ACE_TEXT ("(%N:%l) ifr_adding_visitor_union::")
84 ACE_TEXT ("visit_scope -")
85 ACE_TEXT (" failed to accept visitor\n")),
86 -1);
89 this->ir_current_ =
90 CORBA::IDLType::_duplicate (visitor.ir_current ());
92 else
94 if (ft->ast_accept (this) == -1)
96 ORBSVCS_ERROR_RETURN ((
97 LM_ERROR,
98 ACE_TEXT ("(%N:%l) ifr_adding_visitor_union::")
99 ACE_TEXT ("visit_scope -")
100 ACE_TEXT (" failed to accept visitor\n")),
101 -1);
105 else
107 // Updates ir_current_.
108 this->get_referenced_type (ft);
111 // Get the case label(s).
113 AST_UnionLabel *case_label = 0;
114 AST_UnionBranch *ub = dynamic_cast<AST_UnionBranch*> (*f);
115 unsigned long len = ub->label_list_length ();
117 // If there are multiple case labels, we will have an element
118 // in the UnionMemberSeq for each label, not just for each member,
119 // so the list length and the loop terminator must both be
120 // increased accordingly.
121 if (len > 1)
123 this->members_.length (this->members_.length () + len - 1);
126 for (unsigned long j = 0; j < len; ++j)
128 case_label = ub->label (j);
130 // Is this a regular label or default label?
131 if (case_label->label_kind () == AST_UnionLabel::UL_label)
133 AST_Expression::AST_ExprValue *ev =
134 case_label->label_val ()->ev ();
136 // If the discriminator is an enum, we can't just insert
137 // a ulong into the Any member of struct UnionMember.
138 if (u->disc_type ()->node_type () == AST_Decl::NT_enum)
140 TAO_OutputCDR cdr;
141 cdr.write_ulong (ev->u.ulval);
142 TAO_InputCDR in_cdr (cdr);
143 TAO::Unknown_IDL_Type *unk = 0;
144 ACE_NEW_RETURN (unk,
145 TAO::Unknown_IDL_Type (
146 this->disc_tc_.in (),
147 in_cdr),
148 -1);
149 this->members_[index].label.replace (unk);
151 else
153 this->load_any (ev,
154 this->members_[index].label);
157 else // Default case label.
159 this->members_[index].label <<= CORBA::Any::from_octet (0);
162 this->members_[index].name =
163 CORBA::string_dup ((*f)->local_name ()->get_string ());
165 // IfR method create_union does not use this - it just needs
166 // to be non-zero for marshaling.
167 this->members_[index].type =
168 CORBA::TypeCode::_duplicate (CORBA::_tc_void);
170 this->members_[index++].type_def =
171 CORBA::IDLType::_duplicate (this->ir_current_.in ());
175 catch (const CORBA::Exception& ex)
177 ex._tao_print_exception (
178 ACE_TEXT (
179 "ifr_adding_visitor_union::visit_scope"));
181 return -1;
184 return 0;
188 ifr_adding_visitor_union::visit_structure (AST_Structure *node)
192 // Is this struct already in the respository?
193 CORBA::Contained_var prev_def =
194 be_global->repository ()->lookup_id (node->repoID ());
196 // If not, create a new entry.
197 if (CORBA::is_nil (prev_def.in ()))
199 ifr_adding_visitor_structure visitor (node);
200 int retval = visitor.visit_structure (node);
202 if (retval == 0)
204 // Get the result of the visit.
205 this->ir_current_ =
206 CORBA::IDLType::_duplicate (visitor.ir_current ());
209 return retval;
211 else
213 // If the line below is true, we are clobbering a previous
214 // entry (from another IDL file) of another type. In that
215 // case we do what other ORB vendors do, and destroy the
216 // original entry, create the new one, and let the user beware.
217 if (!node->ifr_added ())
219 prev_def->destroy ();
221 // This call will take the other branch.
222 return this->visit_structure (node);
225 this->ir_current_ =
226 CORBA::IDLType::_narrow (prev_def.in ());
229 catch (const CORBA::Exception& ex)
231 ex._tao_print_exception (
232 ACE_TEXT (
233 "ifr_adding_visitor_union::visit_structure"));
235 return -1;
238 return 0;
242 ifr_adding_visitor_union::visit_enum (AST_Enum *node)
246 // Is this enum already in the respository?
247 CORBA::Contained_var prev_def =
248 be_global->repository ()->lookup_id (node->repoID ());
250 // If not, create a new entry.
251 if (CORBA::is_nil (prev_def.in ()))
253 CORBA::ULong member_count =
254 static_cast<CORBA::ULong> (node->member_count ());
256 CORBA::EnumMemberSeq members (member_count);
257 members.length (member_count);
259 UTL_ScopedName *member_name = 0;
261 // Get a list of the member names.
262 for (CORBA::ULong i = 0; i < member_count; ++i)
264 member_name = node->value_to_name (i);
266 members[i] =
267 CORBA::string_dup (
268 member_name->last_component ()->get_string ());
271 this->ir_current_ =
272 be_global->repository ()->create_enum (
273 node->repoID (),
274 node->local_name ()->get_string (),
275 node->version (),
276 members
279 node->ifr_added (true);
281 else
283 // If the line below is true, we are clobbering a previous
284 // entry (from another IDL file) of another type. In that
285 // case we do what other ORB vendors do, and destroy the
286 // original entry, create the new one, and let the user beware.
287 if (!node->ifr_added ())
289 prev_def->destroy ();
291 // This call will take the other branch.
292 return this->visit_enum (node);
295 this->ir_current_ =
296 CORBA::IDLType::_narrow (prev_def.in ());
299 catch (const CORBA::Exception& ex)
301 ex._tao_print_exception (
302 ACE_TEXT (
303 "ifr_adding_visitor_union::visit_enum"));
305 return -1;
308 return 0;
312 ifr_adding_visitor_union::visit_union (AST_Union *node)
316 // This will put the discriminator in ir_current_.
317 if (node->disc_type ()->ast_accept (this) == -1)
319 ORBSVCS_ERROR_RETURN ((
320 LM_ERROR,
321 ACE_TEXT ("(%N:%l) ifr_adding_visitor_union::")
322 ACE_TEXT ("visit_union -")
323 ACE_TEXT (" visit of discriminator failed\n")),
324 -1);
327 this->disc_tc_ = this->ir_current_->type ();
329 CORBA::UnionDef_var union_def;
330 CORBA::Contained_var prev_def =
331 be_global->repository ()->lookup_id (node->repoID ());
333 if (CORBA::is_nil (prev_def.in ()))
335 CORBA::UnionMemberSeq dummyMembers;
336 dummyMembers.length (0);
337 CORBA::Container_ptr current_scope = CORBA::Container::_nil ();
339 if (be_global->ifr_scopes ().top (current_scope) != 0)
341 ORBSVCS_ERROR_RETURN ((
342 LM_ERROR,
343 ACE_TEXT ("(%N:%l) ifr_adding_visitor_union::")
344 ACE_TEXT ("visit_union -")
345 ACE_TEXT (" scope stack is empty\n")),
346 -1);
349 // First create the named union without any members.
350 union_def =
351 current_scope->create_union (
352 node->repoID (),
353 node->local_name ()->get_string (),
354 node->version (),
355 this->ir_current_.in (),
356 dummyMembers
359 if (be_global->ifr_scopes ().push (union_def.in ()) != 0)
361 ORBSVCS_ERROR_RETURN ((
362 LM_ERROR,
363 ACE_TEXT ("(%N:%l) ifr_adding_visitor_union::")
364 ACE_TEXT ("visit_union -")
365 ACE_TEXT (" scope push failed\n")
371 // Then add the real union members (which corrupts ir_current_).
372 if (this->add_members (node, union_def.in ()) == -1)
374 ORBSVCS_ERROR_RETURN ((
375 LM_ERROR,
376 ACE_TEXT ("(%N:%l) ifr_adding_visitor_union::visit_union -")
377 ACE_TEXT (" visit_scope failed\n")),
378 -1);
381 this->ir_current_ = CORBA::IDLType::_narrow (union_def.in ());
383 CORBA::Container_ptr used_scope =
384 CORBA::Container::_nil ();
386 // Pop the new IR object back off the scope stack.
387 if (be_global->ifr_scopes ().pop (used_scope) != 0)
389 ORBSVCS_ERROR_RETURN ((
390 LM_ERROR,
391 ACE_TEXT ("(%N:%l) ifr_adding_visitor_union::")
392 ACE_TEXT ("visit_union -")
393 ACE_TEXT (" scope pop failed\n")
398 } // if (CORBA::is_nil (...))
399 else
401 // We are seeing the full definition of a forward
402 // declaration - just add the members so repo
403 // entries referencing the UnionDef will stay valid.
404 // Also we know node->ifr_fwd_added_ is true.
405 union_def = CORBA::UnionDef::_narrow (prev_def.in ());
406 union_def->discriminator_type_def (this->ir_current_.in ());
408 if (be_global->ifr_scopes ().push (union_def.in ()) != 0)
410 ORBSVCS_ERROR_RETURN ((
411 LM_ERROR,
412 ACE_TEXT ("(%N:%l) ifr_adding_visitor_union::")
413 ACE_TEXT ("visit_union -")
414 ACE_TEXT (" scope push failed\n")
420 if (this->add_members (node, union_def.in ()) == -1)
422 ORBSVCS_ERROR_RETURN ((
423 LM_ERROR,
424 ACE_TEXT ("(%N:%l) ifr_adding_visitor_union::")
425 ACE_TEXT ("visit_union -")
426 ACE_TEXT (" visit_scope failed\n")),
427 -1);
430 this->ir_current_ = CORBA::IDLType::_narrow (prev_def.in ());
432 CORBA::Container_ptr used_scope =
433 CORBA::Container::_nil ();
435 // Pop the new IR object back off the scope stack.
436 if (be_global->ifr_scopes ().pop (used_scope) != 0)
438 ORBSVCS_ERROR_RETURN ((
439 LM_ERROR,
440 ACE_TEXT ("(%N:%l) ifr_adding_visitor_union::")
441 ACE_TEXT ("visit_union -")
442 ACE_TEXT (" scope pop failed\n")
449 catch (const CORBA::Exception& ex)
451 ex._tao_print_exception (
452 ACE_TEXT (
453 "ifr_adding_visitor_union::visit_union"));
455 return -1;
458 return 0;
461 CORBA::IDLType_ptr
462 ifr_adding_visitor_union::ir_current (void) const
464 return this->ir_current_.in ();
468 ifr_adding_visitor_union::add_members (AST_Union *node,
469 CORBA::UnionDef_ptr union_def)
471 if (this->visit_scope (node) == -1)
473 ORBSVCS_ERROR_RETURN ((
474 LM_ERROR,
475 ACE_TEXT ("(%N:%l) ifr_adding_visitor_union::visit_union -")
476 ACE_TEXT (" visit_scope failed\n")),
477 -1);
480 // Correct ir_current_ and move the real union members into the union.
481 this->ir_current_= CORBA::UnionDef::_duplicate (union_def);
482 union_def->members (this->members_);
484 node->ifr_added (true);
485 return 0;