OpenDDS  Snapshot(2023/04/28-20:55)
dds_generator.cpp
Go to the documentation of this file.
1 /*
2  * Distributed under the OpenDDS License.
3  * See: http://www.opendds.org/license.html
4  */
5 
6 #include "dds_generator.h"
7 
8 #include "field_info.h"
9 
10 #include <utl_identifier.h>
11 
12 using namespace std;
13 using namespace AstTypeClassification;
14 
16 
17 namespace {
18  const std::string cxx_escape = "_cxx_";
19 }
20 
21 bool dds_generator::cxx_escaped(const std::string& s)
22 {
23  return s.substr(0, cxx_escape.size()) == cxx_escape;
24 }
25 
26 std::string dds_generator::valid_var_name(const std::string& str)
27 {
28  // Replace invalid characters with a single underscore
29  // Replace existing "_" with "_9" to prevent collision
30  const std::string invalid_chars("<>()[]*.: ");
31  std::string s;
32  char last_char = '\0';
33  for (size_t i = 0; i < str.size(); ++i) {
34  const char c = str[i];
35  if (invalid_chars.find(c) == std::string::npos) {
36  s.push_back(c);
37  last_char = c;
38  if (c == '_') {
39  s.push_back('9');
40  last_char = '9';
41  }
42  } else if (last_char != '_') {
43  s.push_back('_');
44  last_char = '_';
45  }
46  }
47 
48  // Remove underscores at start and end
49  if (s.size() > 1 && s[0] == '_') {
50  if (!cxx_escaped(s)) {
51  s.erase(0, 1);
52  }
53  }
54  if (s.size() > 1 && s[s.size() - 1] == '_') {
55  s.erase(s.size() - 1, 1);
56  }
57 
58  return s;
59 }
60 
61 std::string dds_generator::get_tag_name(const std::string& base_name, const std::string& qualifier)
62 {
63  return valid_var_name(base_name) + qualifier + "_tag";
64 }
65 
66 std::string dds_generator::get_xtag_name(UTL_ScopedName* name)
67 {
68  return scoped_helper(name, "_") + "_xtag";
69 }
70 
72 {
73  string str = id->get_string();
74  switch (ec) {
76  if (id->escaped()) {
77  // If it was escaped in the input, it must be escaped in generated IDL.
78  if (cxx_escaped(str)) {
79  // Strip "_cxx"
80  str = str.substr(cxx_escape.size() - 1);
81  } else {
82  str = '_' + str;
83  }
84  }
85  break;
88  if (id->escaped() && cxx_escaped(str)) {
89  // If this is a C++ keyword that was inserted into generated IDL, the
90  // "_cxx_" was stripped.
91  str = str.substr(cxx_escape.size());
92  }
93  break;
95  break;
96  }
97  return str;
98 }
99 
100 string dds_generator::scoped_helper(UTL_ScopedName* sn, const char* sep, EscapeContext ec)
101 {
102  string sname;
103 
104  for (; sn; sn = static_cast<UTL_ScopedName*>(sn->tail())) {
105  const bool not_last = sn->tail();
106  sname += to_string(sn->head(),
107  (ec == EscapeContext_FromGenIdl && not_last) ? EscapeContext_Normal : ec);
108 
109  if (sname.size() && not_last) {
110  sname += sep;
111  }
112  }
113 
114  return sname;
115 }
116 
117 string dds_generator::module_scope_helper(UTL_ScopedName* sn, const char* sep, EscapeContext ec)
118 {
119  string sname;
120 
121  for (; sn && sn->tail(); sn = static_cast<UTL_ScopedName*>(sn->tail())) {
122  sname += to_string(sn->head(), ec == EscapeContext_FromGenIdl ? EscapeContext_Normal : ec);
123 
124  if (sname.size()) {
125  sname += sep;
126  }
127  }
128 
129  return sname;
130 }
131 
133 {
134  for (vector<dds_generator*>::iterator it(components_.begin());
135  it != components_.end(); ++it) {
136  (*it)->gen_prologue();
137  }
138 }
139 
141 {
142  for (vector<dds_generator*>::iterator it(components_.begin());
143  it != components_.end(); ++it) {
144  (*it)->gen_epilogue();
145  }
146 }
147 
148 bool composite_generator::gen_const(UTL_ScopedName* name, bool nestedInInteface,
149  AST_Constant* constant)
150 {
151  for (vector<dds_generator*>::iterator it(components_.begin());
152  it != components_.end(); ++it) {
153  if (!constant->imported() || (*it)->do_included_files())
154  if (!(*it)->gen_const(name, nestedInInteface, constant))
155  return false;
156  }
157 
158  return true;
159 }
160 
161 bool composite_generator::gen_enum(AST_Enum* node, UTL_ScopedName* name,
162  const std::vector<AST_EnumVal*>& contents, const char* repoid)
163 {
164  for (vector<dds_generator*>::iterator it(components_.begin());
165  it != components_.end(); ++it) {
166  if (!node->imported() || (*it)->do_included_files())
167  if (!(*it)->gen_enum(node, name, contents, repoid))
168  return false;
169  }
170 
171  return true;
172 }
173 
174 bool composite_generator::gen_struct(AST_Structure* node, UTL_ScopedName* name,
175  const vector<AST_Field*>& fields, AST_Type::SIZE_TYPE size,
176  const char* repoid)
177 {
178  for (vector<dds_generator*>::iterator it(components_.begin());
179  it != components_.end(); ++it) {
180  if (!node->imported() || (*it)->do_included_files())
181  if (!(*it)->gen_struct(node, name, fields, size, repoid))
182  return false;
183  }
184 
185  return true;
186 }
187 
189  AST_Type::SIZE_TYPE size)
190 {
191  for (vector<dds_generator*>::iterator it(components_.begin());
192  it != components_.end(); ++it) {
193  if (!(*it)->gen_struct_fwd(name, size))
194  return false;
195  }
196 
197  return true;
198 }
199 
200 bool composite_generator::gen_typedef(AST_Typedef* node, UTL_ScopedName* name, AST_Type* base,
201  const char* repoid)
202 {
203  for (vector<dds_generator*>::iterator it(components_.begin());
204  it != components_.end(); ++it) {
205  if (!node->imported() || (*it)->do_included_files())
206  if (!(*it)->gen_typedef(node, name, base, repoid))
207  return false;
208  }
209 
210  return true;
211 }
212 
213 bool composite_generator::gen_interf(AST_Interface* node, UTL_ScopedName* name, bool local,
214  const std::vector<AST_Interface*>& inherits,
215  const std::vector<AST_Interface*>& inh_flat,
216  const std::vector<AST_Attribute*>& attrs,
217  const std::vector<AST_Operation*>& ops, const char* repoid)
218 {
219  for (vector<dds_generator*>::iterator it(components_.begin());
220  it != components_.end(); ++it) {
221  if (!node->imported() || (*it)->do_included_files())
222  if (!(*it)->gen_interf(node, name, local, inherits, inh_flat,
223  attrs, ops, repoid))
224  return false;
225  }
226 
227  return true;
228 }
229 
231 {
232  for (vector<dds_generator*>::iterator it(components_.begin());
233  it != components_.end(); ++it) {
234  if (!(*it)->gen_interf_fwd(name))
235  return false;
236  }
237 
238  return true;
239 }
240 
241 bool composite_generator::gen_native(AST_Native* node, UTL_ScopedName* name, const char* repoid)
242 {
243  for (vector<dds_generator*>::iterator it(components_.begin());
244  it != components_.end(); ++it) {
245  if (!node->imported() || (*it)->do_included_files())
246  if (!(*it)->gen_native(node, name, repoid))
247  return false;
248  }
249 
250  return true;
251 }
252 
253 bool composite_generator::gen_union(AST_Union* node,
254  UTL_ScopedName* name,
255  const std::vector<AST_UnionBranch*>& branches,
256  AST_Type* discriminator,
257  const char* repoid)
258 {
259  for (vector<dds_generator*>::iterator it(components_.begin());
260  it != components_.end(); ++it) {
261  if (!node->imported() || (*it)->do_included_files())
262  if (!(*it)->gen_union(node, name, branches, discriminator, repoid))
263  return false;
264  }
265 
266  return true;
267 }
268 
269 bool composite_generator::gen_union_fwd(AST_UnionFwd* uf, UTL_ScopedName* name,
270  AST_Type::SIZE_TYPE size)
271 {
272  for (vector<dds_generator*>::iterator it(components_.begin());
273  it != components_.end(); ++it) {
274  if (!(*it)->gen_union_fwd(uf, name, size))
275  return false;
276  }
277 
278  return true;
279 }
280 
281 NestedForLoops::NestedForLoops(const char* type, const char* prefix,
282  AST_Array* arr, std::string& indent,
283  bool followTypedefs)
284  : n_(arr->n_dims())
285  , indent_(indent)
286 {
287  std::ostringstream index_oss;
288  size_t i = 0, j = 0;
289  while (true) {
290  for (; i < n_; ++i) {
291  be_global->impl_ <<
292  indent << "for (" << type << ' ' << prefix << i << " = 0; " <<
293  prefix << i << " < " << arr->dims()[i - j]->ev()->u.ulval << "; ++" <<
294  prefix << i << ") {\n";
295  indent += " ";
296  index_oss << "[" << prefix << i << "]";
297  }
298  if (!followTypedefs) {
299  break;
300  }
301  AST_Type* const base =
303  if (base->node_type() == AST_Decl::NT_array) {
304  arr = dynamic_cast<AST_Array*>(base);
305  n_ += arr->n_dims();
306  j = i;
307  } else {
308  break;
309  }
310  }
311  index_ = index_oss.str();
312 }
313 
315 {
316  for (size_t i = 0; i < n_; ++i) {
317  indent_.resize(indent_.size() - 2);
318  be_global->impl_ << indent_ << "}\n";
319  }
320 }
321 
322 string type_to_default_array(const std::string& indent, AST_Type* type, const string& name,
323  bool is_anonymous, bool is_union, bool use_cxx11, Classification fld_cls)
324 {
325  // TODO: Most of what's in here looks like it could be replaced with RefWrapper
326  string val;
327  string temp = name;
328  if (temp.size() > 2 && temp.substr(temp.size() - 2, 2) == "()") {
329  temp.erase(temp.size() - 2);
330  }
331  temp += "_temp";
332  replace(temp.begin(), temp.end(), '.', '_');
333  replace(temp.begin(), temp.end(), '[', '_');
334  replace(temp.begin(), temp.end(), ']', '_');
335  if (use_cxx11) {
336  string n = scoped(deepest_named_type(type)->name());
337  if (is_anonymous) {
338  n = n.substr(0, n.rfind("::") + 2) + "AnonymousType_" + type->local_name()->get_string();
339  n = (fld_cls == AST_Decl::NT_sequence) ? (n + "_seq") : n;
340  }
341  val += indent + "set_default(IDL::DistinctType<" + n + ", " + dds_generator::get_tag_name(n) + ">(" +
342  (is_union ? "tmp" : name) + "));\n";
343  } else {
344  string n = scoped(type->name());
345  if (is_anonymous) {
346  n = n.substr(0, n.rfind("::") + 2) + "_" + type->local_name()->get_string();
347  n = (fld_cls == AST_Decl::NT_sequence) ? (n + "_seq") : n;
348  }
349  val = indent + n + "_forany " + temp + "(const_cast<"
350  + n + "_slice*>(" + (is_union ? "tmp": name) + "));\n";
351  val += indent + "set_default(" + temp + ");\n";
352  }
353  if (is_union) {
354  val += indent + name + "(tmp);\n";
355  }
356  return val;
357 }
358 
359 string type_to_default(const std::string& indent, AST_Type* type, const string& name,
360  bool is_anonymous, bool is_union)
361 {
362  AST_Type* actual_type = resolveActualType(type);
363  Classification fld_cls = classify(actual_type);
364  const bool use_cxx11 = be_global->language_mapping() == BE_GlobalData::LANGMAP_CXX11;
365  string def_val;
366  std::string pre = " = ";
367  std::string post;
368  if (is_union) {
369  pre = "(";
370  post = ")";
371  }
372  if (fld_cls & (CL_STRUCTURE | CL_UNION)) {
373  return indent + "set_default(" + name + (is_union ? "()" : "") + ");\n";
374  } else if (fld_cls & CL_ARRAY) {
375  return type_to_default_array(
376  indent, type, name, is_anonymous, is_union, use_cxx11, fld_cls);
377  } else if (fld_cls & CL_ENUM) {
378  // For now, simply return the first value of the enumeration.
379  // Must be changed, if support for @default_literal is desired.
380  AST_Enum* enu = dynamic_cast<AST_Enum*>(actual_type);
381  UTL_ScopeActiveIterator i(enu, UTL_Scope::IK_decls);
382  AST_EnumVal *item = dynamic_cast<AST_EnumVal*>(i.item());
383  if (use_cxx11) {
384  def_val = scoped(type->name()) + "::" + item->local_name()->get_string();
385  } else {
386  def_val = scoped(item->name());
387  }
388  } else if (fld_cls & CL_SEQUENCE) {
389  string seq_resize_func = (use_cxx11) ? "resize" : "length";
390  if (is_union) {
391  return indent + "tmp." + seq_resize_func + "(0);\n"
392  + indent + name + "(tmp);\n";
393  } else {
394  return indent + name + "." + seq_resize_func + "(0);\n";
395  }
396  } else if (fld_cls & CL_STRING) {
397  def_val = (fld_cls & CL_WIDE) ? "L\"\"" : "\"\"";
398  if (!use_cxx11 && (fld_cls & CL_WIDE)) def_val = "TAO::WString_Manager::s_traits::default_initializer()";
399  } else if (fld_cls & (CL_PRIMITIVE | CL_FIXED)) {
400  AST_PredefinedType* pt = dynamic_cast<AST_PredefinedType*>(actual_type);
401  if (pt && (pt->pt() == AST_PredefinedType::PT_longdouble)) {
402  if (use_cxx11) {
403  def_val = "0.0L";
404  } else {
405  string temp_val = "ACE_CDR::LongDouble val = ACE_CDR_LONG_DOUBLE_INITIALIZER";
406  if (is_union) {
407  def_val = "val";
408  return indent + temp_val + ";\n" +
409  indent + name + pre + def_val + post + ";\n";
410  } else {
411  def_val = "ACE_CDR_LONG_DOUBLE_ASSIGNMENT(" + name + ", val)";
412  return indent + "{\n"
413  " " + indent + temp_val + ";\n"
414  " " + indent + def_val + ";\n" +
415  indent + "}\n";
416  }
417  }
418  } else {
419  def_val = "0";
420  }
421  }
422  return indent + name + pre + def_val + post + ";\n";
423 }
424 
425 std::string field_type_name(AST_Field* field, AST_Type* field_type)
426 {
427  if (!field_type) {
428  field_type = field->field_type();
429  }
430  const Classification cls = classify(field_type);
431  const std::string name = (cls & CL_STRING) ?
432  string_type(cls) : scoped(deepest_named_type(field_type)->name());
433  if (field) {
434  FieldInfo af(*field);
435  if (af.as_base_ && af.type_->anonymous()) {
436  return af.scoped_type_;
437  }
438  }
439  return name;
440 }
441 
442 AST_Type* deepest_named_type(AST_Type* type)
443 {
444  AST_Type* consider = type;
445  AST_Type* named_type = type;
446  while (consider->node_type() == AST_Decl::NT_typedef) {
447  named_type = consider;
448  consider = dynamic_cast<AST_Typedef*>(named_type)->base_type();
449  }
450  return named_type;
451 }
Classification classify(AST_Type *type)
static std::string scoped_helper(UTL_ScopedName *sn, const char *sep, EscapeContext cxt=EscapeContext_Normal)
std::string string_type(AstTypeClassification::Classification cls)
const Classification CL_STRING
string type_to_default(const std::string &indent, AST_Type *type, const string &name, bool is_anonymous, bool is_union)
const Classification CL_WIDE
string Identifier
std::string field_type_name(AST_Field *field, AST_Type *field_type)
virtual ~dds_generator()=0
const Classification CL_PRIMITIVE
static std::string get_xtag_name(UTL_ScopedName *name)
bool gen_union(AST_Union *node, UTL_ScopedName *name, const std::vector< AST_UnionBranch *> &branches, AST_Type *discriminator, const char *repoid)
NestedForLoops(const char *type, const char *prefix, AST_Array *arr, std::string &indent, bool followTypedefs=false)
bool gen_const(UTL_ScopedName *name, bool nestedInInteface, AST_Constant *constant)
static std::string get_tag_name(const std::string &base_name, const std::string &qualifier="")
bool gen_interf_fwd(UTL_ScopedName *name)
AST_Type * deepest_named_type(AST_Type *type)
bool gen_native(AST_Native *node, UTL_ScopedName *name, const char *repoid)
This is for everything else.
Definition: dds_generator.h:45
bool gen_interf(AST_Interface *node, UTL_ScopedName *name, bool local, const std::vector< AST_Interface *> &inherits, const std::vector< AST_Interface *> &inherits_flat, const std::vector< AST_Attribute *> &attrs, const std::vector< AST_Operation *> &ops, const char *repoid)
std::string & indent_
const Classification CL_ARRAY
static bool cxx_escaped(const std::string &s)
Strip any escapes.
Definition: dds_generator.h:43
std::string index_
string type_to_default_array(const std::string &indent, AST_Type *type, const string &name, bool is_anonymous, bool is_union, bool use_cxx11, Classification fld_cls)
STL namespace.
static std::string to_string(Identifier *id, EscapeContext ec=EscapeContext_Normal)
const std::string scoped_type_
Definition: field_info.h:42
bool gen_typedef(AST_Typedef *node, UTL_ScopedName *name, AST_Type *base, const char *repoid)
static std::string valid_var_name(const std::string &str)
AST_Type * resolveActualType(AST_Type *element)
This is for generated IDL. (Like *TypeSupport.idl)
Definition: dds_generator.h:39
This is for a name coming from generated IDL. (Like *TypeSupportC.h)
Definition: dds_generator.h:41
static std::string module_scope_helper(UTL_ScopedName *sn, const char *sep, EscapeContext cxt=EscapeContext_Normal)
const char *const name
Definition: debug.cpp:60
const Classification CL_FIXED
std::string scoped(UTL_ScopedName *sn, EscapeContext ec=EscapeContext_Normal)
AST_Type * type_
Definition: field_info.h:40
const Classification CL_STRUCTURE
AST_Type * as_base_
Definition: field_info.h:50
BE_GlobalData * be_global
Definition: be_global.cpp:44
const char * to_string(MessageId value)
bool gen_struct_fwd(UTL_ScopedName *name, AST_Type::SIZE_TYPE size)
EscapeContext
Definition: dds_generator.h:37
const Classification CL_ENUM
const Classification CL_SEQUENCE
bool gen_union_fwd(AST_UnionFwd *, UTL_ScopedName *name, AST_Type::SIZE_TYPE size)
bool gen_struct(AST_Structure *node, UTL_ScopedName *name, const std::vector< AST_Field *> &fields, AST_Type::SIZE_TYPE size, const char *repoid)
const Classification CL_UNION
bool gen_enum(AST_Enum *node, UTL_ScopedName *name, const std::vector< AST_EnumVal *> &contents, const char *repoid)