OpenDDS  Snapshot(2023/04/28-20:55)
be_global.cpp
Go to the documentation of this file.
1 /*
2  *
3  *
4  * Distributed under the OpenDDS License.
5  * See: http://www.opendds.org/license.html
6  */
7 
8 #include "be_global.h"
9 
10 #include "be_util.h"
11 #include "be_extern.h"
12 #include "dds_generator.h"
13 
15 
16 #include <ast_generator.h>
17 #include <global_extern.h>
18 #include <idl_defines.h>
19 #include <utl_err.h>
20 #include <utl_string.h>
21 #include <ast_decl.h>
22 #include <ast_structure.h>
23 #include <ast_field.h>
24 #include <ast_union.h>
25 #include <ast_annotation_decl.h>
26 #include <ast_annotation_member.h>
27 
28 #include <ace/OS_NS_strings.h>
29 #include <ace/OS_NS_sys_stat.h>
30 #include <ace/ARGV.h>
31 #include <ace/OS_NS_stdlib.h>
32 
33 #include <algorithm>
34 #include <iostream>
35 #include <fstream>
36 #include <sstream>
37 #include <string>
38 #include <cstring>
39 #include <vector>
40 #include <set>
41 
42 using namespace std;
43 
45 
47  : filename_(0)
48  , java_(false)
49  , suppress_idl_(false)
50  , suppress_typecode_(false)
51  , suppress_xtypes_(false)
52  , no_default_gen_(false)
53  , generate_itl_(false)
54  , generate_value_reader_writer_(true)
55  , generate_xtypes_complete_(false)
56  , face_ts_(false)
57  , filename_only_includes_(false)
58  , sequence_suffix_("Seq")
59  , language_mapping_(LANGMAP_NONE)
60  , root_default_nested_(true)
61  , warn_about_dcps_data_type_(true)
62  , default_extensibility_(extensibilitykind_appendable)
63  , default_enum_extensibility_zero_(false)
64  , root_default_autoid_(autoidkind_sequential)
65  , default_try_construct_(tryconstructfailaction_discard)
66  , old_typeobject_encoding_(false)
67  , old_typeobject_member_order_(false)
68 {
69  default_data_representation_.set_all(true);
70 
71  platforms_.insert("*");
72  platforms_.insert("DDS");
73  platforms_.insert("OpenDDS");
74 }
75 
77 {
78 }
79 
80 void
82 {
83 }
84 
85 const char*
87 {
88  return this->filename_;
89 }
90 
91 void
92 BE_GlobalData::filename(const char* fname)
93 {
94  this->filename_ = fname;
95 }
96 
97 ACE_CString BE_GlobalData::export_macro() const
98 {
99  return this->export_macro_;
100 }
101 
102 void BE_GlobalData::export_macro(const ACE_CString& str)
103 {
104  this->export_macro_ = str;
105 }
106 
107 ACE_CString BE_GlobalData::export_include() const
108 {
109  return this->export_include_;
110 }
111 
112 void BE_GlobalData::export_include(const ACE_CString& str)
113 {
114  this->export_include_ = str;
115 }
116 
117 ACE_CString BE_GlobalData::versioning_name() const
118 {
119  return this->versioning_name_;
120 }
121 
122 void BE_GlobalData::versioning_name(const ACE_CString& str)
123 {
124  this->versioning_name_ = str;
125 }
126 
127 ACE_CString BE_GlobalData::versioning_begin() const
128 {
129  return this->versioning_begin_;
130 }
131 
132 void BE_GlobalData::versioning_begin(const ACE_CString& str)
133 {
134  this->versioning_begin_ = str;
135 }
136 
137 ACE_CString BE_GlobalData::versioning_end() const
138 {
139  return this->versioning_end_;
140 }
141 
142 void BE_GlobalData::versioning_end(const ACE_CString& str)
143 {
144  this->versioning_end_ = str;
145 }
146 
147 void BE_GlobalData::pch_include(const ACE_CString& str)
148 {
149  this->pch_include_ = str;
150 }
151 
152 ACE_CString BE_GlobalData::pch_include() const
153 {
154  return this->pch_include_;
155 }
156 
157 void BE_GlobalData::add_cpp_include(const string& str)
158 {
159  this->cpp_includes_.insert(make_pair(str, ""));
160 }
161 
162 const set<pair<string, string> >& BE_GlobalData::cpp_includes() const
163 {
164  return this->cpp_includes_;
165 }
166 
167 void BE_GlobalData::java_arg(const ACE_CString& str)
168 {
169  this->java_arg_ = str;
170 }
171 
172 ACE_CString BE_GlobalData::java_arg() const
173 {
174  return this->java_arg_;
175 }
176 
177 void BE_GlobalData::language_mapping(LanguageMapping lm)
178 {
179  this->language_mapping_ = lm;
180 }
181 
182 BE_GlobalData::LanguageMapping BE_GlobalData::language_mapping() const
183 {
184  return this->language_mapping_;
185 }
186 
187 void BE_GlobalData::sequence_suffix(const ACE_CString& str)
188 {
189  this->sequence_suffix_ = str;
190 }
191 
192 ACE_CString BE_GlobalData::sequence_suffix() const
193 {
194  return this->sequence_suffix_;
195 }
196 
197 void BE_GlobalData::java(bool b)
198 {
199  this->java_ = b;
200 }
201 
202 bool BE_GlobalData::java() const
203 {
204  return this->java_;
205 }
206 
207 void BE_GlobalData::no_default_gen(bool b)
208 {
209  this->no_default_gen_ = b;
210 }
211 
212 bool BE_GlobalData::no_default_gen() const
213 {
214  return this->no_default_gen_;
215 }
216 
217 void BE_GlobalData::filename_only_includes(bool b)
218 {
219  this->filename_only_includes_ = b;
220 }
221 
222 bool BE_GlobalData::filename_only_includes() const
223 {
224  return this->filename_only_includes_;
225 }
226 
227 
228 void BE_GlobalData::itl(bool b)
229 {
230  this->generate_itl_ = b;
231 }
232 
233 bool BE_GlobalData::itl() const
234 {
235  return this->generate_itl_;
236 }
237 
238 void BE_GlobalData::value_reader_writer(bool b)
239 {
240  this->generate_value_reader_writer_ = b;
241 }
242 
243 bool BE_GlobalData::value_reader_writer() const
244 {
245  return this->generate_value_reader_writer_;
246 }
247 
248 void BE_GlobalData::face_ts(bool b)
249 {
250  this->face_ts_ = b;
251 }
252 
253 bool BE_GlobalData::face_ts() const
254 {
255  return this->face_ts_;
256 }
257 
258 void BE_GlobalData::xtypes_complete(bool b)
259 {
260  this->generate_xtypes_complete_ = b;
261 }
262 
263 bool BE_GlobalData::xtypes_complete() const
264 {
265  return this->generate_xtypes_complete_;
266 }
267 
268 void
269 BE_GlobalData::open_streams(const char* filename)
270 {
271  size_t len = strlen(filename);
272  if ((len < 5 || 0 != ACE_OS::strcasecmp(filename + len - 4, ".idl"))
273  && (len < 6 || 0 != ACE_OS::strcasecmp(filename + len - 5, ".pidl"))) {
274  ACE_ERROR((LM_ERROR, "Error - Input filename must end in \".idl\" or \".pidl\".\n"));
275  BE_abort();
276  }
277 
278  string filebase(filename);
279  filebase.erase(filebase.rfind('.'));
280  size_t idx = filebase.find_last_of("/\\"); // allow either slash
281  if (idx != string::npos) {
282  filebase = filebase.substr(idx + 1);
283  }
284  header_name_ = (filebase + "TypeSupportImpl.h").c_str();
285  impl_name_ = (filebase + "TypeSupportImpl.cpp").c_str();
286  idl_name_ = (filebase + "TypeSupport.idl").c_str();
287  itl_name_ = (filebase + ".itl").c_str();
288  facets_header_name_ = (filebase + "_TS.hpp").c_str();
289  facets_impl_name_ = (filebase + "_TS.cpp").c_str();
290  lang_header_name_ = (filebase + "C.h").c_str();
291 }
292 
293 void
294 BE_GlobalData::multicast(const char* str)
295 {
296  header_ << str;
297  impl_ << str;
298  idl_ << str;
299  if (language_mapping_ != LANGMAP_NONE) lang_header_ << str;
300 }
301 
302 BE_Comment_Guard::BE_Comment_Guard(const char* type, const char* name)
303  : type_(type), name_(name)
304 {
305  if (idl_global->compile_flags() & IDL_CF_INFORMATIVE)
306  cout << type << ": " << name << endl;
307 
308  be_global->multicast("\n\n/* Begin ");
309  be_global->multicast(type);
310  be_global->multicast(": ");
311  be_global->multicast(name);
312  be_global->multicast(" */\n\n");
313 }
314 
316 {
317  be_global->multicast("\n/* End ");
318  be_global->multicast(type_);
319  be_global->multicast(": ");
320  be_global->multicast(name_);
321  be_global->multicast(" */\n");
322 }
323 
326 {
327  return idl_global->idl_flags();
328 }
329 
330 void invalid_option(char* option)
331 {
333  ACE_TEXT("opendds_idl: I don't understand the '%C' option\n"), option));
334  idl_global->parse_args_exit(1);
335 }
336 
337 void
338 BE_GlobalData::parse_args(long& i, char** av)
339 {
340  static const char EXPORT_FLAG[] = "--export=";
341  static const size_t EXPORT_FLAG_SIZE = sizeof(EXPORT_FLAG) - 1;
342 
343  static const char DEFAULT_NESTED_FLAG[] = "--default-nested";
344  static const size_t DEFAULT_NESTED_FLAG_SIZE = sizeof(DEFAULT_NESTED_FLAG) - 1;
345 
346  static const char NO_DEFAULT_NESTED_FLAG[] = "--no-default-nested";
347  static const size_t NO_DEFAULT_NESTED_FLAG_SIZE = sizeof(NO_DEFAULT_NESTED_FLAG) - 1;
348 
349  static const char NO_DCPS_DATA_TYPE_WARNINGS_FLAG[] = "--no-dcps-data-type-warnings";
350  static const size_t NO_DCPS_DATA_TYPE_WARNINGS_FLAG_SIZE = sizeof(NO_DCPS_DATA_TYPE_WARNINGS_FLAG) - 1;
351 
352  static const char FILENAME_ONLY_INCLUDES_FLAG[] = "--filename-only-includes";
353  static const size_t FILENAME_ONLY_INCLUDES_FLAG_SIZE = sizeof(FILENAME_ONLY_INCLUDES_FLAG) - 1;
354 
355  switch (av[i][1]) {
356  case 'o':
357  if (av[++i] == 0) {
358  ACE_ERROR((LM_ERROR, ACE_TEXT("No argument for -o\n")));
359  idl_global->parse_args_exit(1);
360  } else {
361  idl_global->append_idl_flag(av[i]);
362  if (ACE_OS::mkdir(av[i]) != 0 && errno != EEXIST) {
363  ACE_ERROR((LM_ERROR, ACE_TEXT("IDL: unable to create directory %C")
364  ACE_TEXT(" specified by -o option\n"), av[i]));
365  idl_global->parse_args_exit(1);
366  } else {
367  output_dir_ = av[i];
368  }
369  }
370  break;
371 
372  case 'G':
373  if (0 == ACE_OS::strcmp(av[i], "-Gitl")) {
374  itl(true);
375  } else if (0 == ACE_OS::strcasecmp(av[i], "-GfaceTS")) {
376  face_ts(true);
377  } else if (0 == ACE_OS::strcasecmp(av[i], "-Gxtypes-complete")) {
378  xtypes_complete(true);
379  } else {
380  invalid_option(av[i]);
381  }
382  break;
383 
384  case 'L':
385  if (0 == ACE_OS::strcasecmp(av[i], "-Lface"))
386  language_mapping(LANGMAP_FACE_CXX);
387  else if (0 == ACE_OS::strcasecmp(av[i], "-Lspcpp"))
388  language_mapping(LANGMAP_SP_CXX);
389  else if (0 == ACE_OS::strcasecmp(av[i], "-Lc++11")) {
390  language_mapping(LANGMAP_CXX11);
391  } else {
392  invalid_option(av[i]);
393  }
394  break;
395 
396  case 'S':
397  if (0 == ACE_OS::strcasecmp(av[i], "-Sdefault")) {
398  no_default_gen_ = true;
399  break;
400  }
401  if (av[i][2] && av[i][3]) {
402  invalid_option(av[i]);
403  break;
404  }
405  switch (av[i][2]) {
406  case 'I':
407  suppress_idl_ = true;
408  break;
409  case 't':
410  suppress_typecode_ = true;
411  break;
412  case 'v':
413  generate_value_reader_writer_ = false;
414  break;
415  case 'x':
416  suppress_xtypes_ = true;
417  break;
418  case 'a':
419  // ignore, accepted for tao_idl compatibility
420  break;
421  default:
422  invalid_option(av[i]);
423  }
424  break;
425 
426  case '-':
427  if (!ACE_OS::strncasecmp(av[i], EXPORT_FLAG, EXPORT_FLAG_SIZE)) {
428  this->export_macro(av[i] + EXPORT_FLAG_SIZE);
429  } else if (!ACE_OS::strncasecmp(av[i], DEFAULT_NESTED_FLAG, DEFAULT_NESTED_FLAG_SIZE)) {
430  root_default_nested_ = true;
431  } else if (!ACE_OS::strncasecmp(av[i], NO_DEFAULT_NESTED_FLAG, NO_DEFAULT_NESTED_FLAG_SIZE)) {
432  root_default_nested_ = false;
433  } else if (!ACE_OS::strncasecmp(av[i], NO_DCPS_DATA_TYPE_WARNINGS_FLAG, NO_DCPS_DATA_TYPE_WARNINGS_FLAG_SIZE)) {
434  warn_about_dcps_data_type_ = false;
435  } else if (!ACE_OS::strncasecmp(av[i], FILENAME_ONLY_INCLUDES_FLAG, FILENAME_ONLY_INCLUDES_FLAG_SIZE)) {
436  filename_only_includes_ = true;
437  } else if (!strcmp(av[i], "--default-extensibility")) {
438  if (av[++i] == 0) {
439  ACE_ERROR((LM_ERROR, ACE_TEXT("No argument for --default-extensibility\n")));
440  idl_global->parse_args_exit(1);
441  } else if (!strcmp(av[i], "final")) {
442  default_extensibility_ = extensibilitykind_final;
443  } else if (!strcmp(av[i], "appendable")) {
444  default_extensibility_ = extensibilitykind_appendable;
445  } else if (!strcmp(av[i], "mutable")) {
446  default_extensibility_ = extensibilitykind_mutable;
447  } else {
449  ACE_TEXT("Invalid argument to --default-extensibility: %C\n"), av[i]));
450  idl_global->parse_args_exit(1);
451  }
452  } else if (!strcmp(av[i], "--default-enum-extensibility-zero")) {
453  default_enum_extensibility_zero_ = true;
454  } else if (!strcmp(av[i], "--default-autoid")) {
455  if (av[++i] == 0) {
456  ACE_ERROR((LM_ERROR, ACE_TEXT("No argument for --default-autoid\n")));
457  idl_global->parse_args_exit(1);
458  } else if (!strcmp(av[i], "sequential")) {
459  root_default_autoid_ = autoidkind_sequential;
460  } else if (!strcmp(av[i], "hash")) {
461  root_default_autoid_ = autoidkind_hash;
462  } else {
464  ACE_TEXT("Invalid argument to --default-autoid: %C\n"), av[i]));
465  idl_global->parse_args_exit(1);
466  }
467  } else if (!strcmp(av[i], "--default-try-construct")) {
468  if (av[++i] == 0) {
469  ACE_ERROR((LM_ERROR, ACE_TEXT("No argument for --default-try-construct\n")));
470  idl_global->parse_args_exit(1);
471  } else if (!strcmp(av[i], "discard")) {
472  default_try_construct_ = tryconstructfailaction_discard;
473  } else if (!strcmp(av[i], "use-default")) {
474  default_try_construct_ = tryconstructfailaction_use_default;
475  } else if (!strcmp(av[i], "trim")) {
476  default_try_construct_ = tryconstructfailaction_trim;
477  } else {
479  ACE_TEXT("Invalid argument to --default-try-construct: %C\n"), av[i]));
480  idl_global->parse_args_exit(1);
481  }
482  } else if (!strcmp(av[i], "--old-typeobject-encoding")) {
483  old_typeobject_encoding_ = true;
484  } else if (!strcmp(av[i], "--old-typeobject-member-order")) {
485  old_typeobject_member_order_ = true;
486  } else {
487  invalid_option(av[i]);
488  }
489  break;
490 
491  default:
492  invalid_option(av[i]);
493  }
494 }
495 
496 
497 bool
498 BE_GlobalData::writeFile(const char* fileName, const string& content)
499 {
500  string file = (be_global->output_dir_ == "")
501  ? fileName : (string(be_global->output_dir_.c_str()) + '/' + fileName);
502  ofstream ofs(file.c_str());
503 
504  if (!ofs) {
505  cerr << "ERROR - couldn't open " << file << " for writing.\n";
506  return false;
507  }
508 
509  ofs << content;
510  return !!ofs;
511 }
512 
513 //include file management (assumes a singleton BE_GlobalData object)
514 
515 namespace {
516  typedef set<pair<string, string> > Includes;
517  Includes all_includes[BE_GlobalData::STREAM_COUNT];
518  set<string> referenced_idl, inc_path;
519  vector<string> inc_path_vector;
520 }
521 
522 void
523 BE_GlobalData::reset_includes()
524 {
525  inc_path_vector.clear();
526  for (int i = 0; i < BE_GlobalData::STREAM_COUNT; ++i) {
527  all_includes[i].clear();
528  }
529 }
530 
531 void
532 BE_GlobalData::add_inc_path(const char* path)
533 {
534  if (inc_path.insert(path).second) {
535  inc_path_vector.push_back(path);
536  }
537 }
538 
539 void
540 BE_GlobalData::set_inc_paths(const char* cmdline)
541 {
542  ACE_ARGV argv(ACE_TEXT_CHAR_TO_TCHAR(cmdline), false);
543  for (int i = 0; i < argv.argc(); ++i) {
544  string arg = ACE_TEXT_ALWAYS_CHAR(argv[i]);
545  if (arg == "-I" && i + 1 < argv.argc()) {
546  add_inc_path(ACE_TEXT_ALWAYS_CHAR(argv[++i]));
547  } else if (arg.substr(0, 2) == "-I") {
548  add_inc_path(arg.c_str() + 2);
549  }
550  }
551 }
552 
553 void
554 BE_GlobalData::add_include(const char* file, stream_enum_t which)
555 {
556  conditional_include(file, which, "");
557 }
558 
559 void
560 BE_GlobalData::conditional_include(const char* file,
561  stream_enum_t which,
562  const char* condition)
563 {
564  all_includes[which].insert(make_pair(file, condition));
565 }
566 
567 void
568 BE_GlobalData::add_referenced(const char* file)
569 {
570  referenced_idl.insert(file);
571 }
572 
573 namespace {
574  pair<string, string> transform_referenced(const string& idl, const char* suffix)
575  {
576  const size_t len = idl.size();
577  string base_name;
578  if (len >= 5 && 0 == ACE_OS::strcasecmp(idl.c_str() + len - 4, ".idl")) {
579  base_name.assign(idl.c_str(), len - 4);
580 
581  } else if (len >= 6 &&
582  0 == ACE_OS::strcasecmp(idl.c_str() + len - 5, ".pidl")) {
583  base_name.assign(idl.c_str(), len - 5);
584  const size_t slash = base_name.find_last_of("/\\");
585  if (slash != string::npos && slash >= 3 && base_name.size() > 3
586  && base_name.substr(slash - 3, 3) == "tao"
587  && base_name.substr(base_name.size() - 3) == "Seq") {
588  base_name = "dds/CorbaSeq/" + base_name.substr(slash + 1);
589  }
590  }
591 
592  return make_pair(base_name + suffix, "");
593  }
594 
595  string make_relative(const string& absolute, bool filename_only_includes)
596  {
597  for (vector<string>::reverse_iterator iter = inc_path_vector.rbegin(),
598  end = inc_path_vector.rend(); iter != end; ++iter) {
599  if (absolute.find(*iter) == 0) {
600  string rel = absolute.substr(iter->size());
601 
602  if (rel.size() && (rel[0] == '/' || rel[0] == '\\')) {
603  rel.erase(0, 1);
604  }
605 
606  if (filename_only_includes) {
607  size_t loc = rel.rfind('/', rel.length());
608  const size_t locw = rel.rfind('\\', rel.length());
609 
610  if (loc != string::npos && locw != string::npos) {
611  // path may contain both '/' and '\'. choose the last one.
612  loc = loc > locw ? loc : locw;
613  } else if (loc == string::npos) {
614  loc = locw;
615  }
616 
617  if (loc != string::npos) {
618  rel = rel.substr(loc + 1, rel.length() - loc);
619  }
620  }
621 
622  return rel;
623  }
624  }
625 
626  return absolute;
627  }
628 
629  struct InsertIncludes {
630  ostream& ret_;
631  explicit InsertIncludes(ostream& ret) : ret_(ret) {}
632 
633  void operator()(const pair<string, string>& inc) const
634  {
635  const string& str = inc.first;
636  const char* const quote = (!str.empty() && str[0] != '<') ? "\"" : "";
637  if (inc.second.size()) {
638  ret_ << inc.second << "\n ";
639  }
640  ret_ << "#include " << quote << str << quote << '\n';
641  if (inc.second.size()) {
642  ret_ << "#endif\n";
643  }
644  }
645  };
646 
647  struct InsertRefIncludes : InsertIncludes {
648  const char* const suffix_;
649  bool filename_only_includes_;
650 
651  InsertRefIncludes(ostream& ret, const char* suffix, const bool filename_only_includes)
652  : InsertIncludes(ret)
653  , suffix_(suffix)
654  , filename_only_includes_(filename_only_includes)
655  {}
656 
657  void operator()(const string& str) const
658  {
659  InsertIncludes::operator()(transform_referenced(make_relative(str, filename_only_includes_), suffix_));
660  }
661  };
662 }
663 
664 string
665 BE_GlobalData::get_include_block(BE_GlobalData::stream_enum_t which)
666 {
667  Includes& inc = all_includes[which];
668  ostringstream ret;
669 
670  for_each(inc.begin(), inc.end(), InsertIncludes(ret));
671 
672  switch (which) {
673  case STREAM_LANG_H:
674  for_each(referenced_idl.begin(), referenced_idl.end(),
675  InsertRefIncludes(ret, "C.h", filename_only_includes_));
676  // fall through
677  case STREAM_H:
678  if (!export_include().empty())
679  ret << "#include \"" << export_include() << "\"\n";
680  break;
681  case STREAM_CPP:
682  for_each(cpp_includes().begin(), cpp_includes().end(), InsertIncludes(ret));
683  for_each(referenced_idl.begin(), referenced_idl.end(),
684  InsertRefIncludes(ret, "TypeSupportImpl.h", filename_only_includes_));
685  break;
686  default:
687  break;
688  }
689 
690  return ret.str();
691 }
692 
693 bool BE_GlobalData::is_topic_type(AST_Decl* node)
694 {
695  return !is_nested(node);
696 }
697 
698 bool BE_GlobalData::is_nested(AST_Decl* node)
699 {
700  {
701  // @topic overrides @nested and @default_nested.
702  TopicAnnotation* topic = dynamic_cast<TopicAnnotation*>(builtin_annotations_["::@topic"]);
704  if (topic->node_value_exists(node, value)) {
705  if (platforms_.count(value.platform)) {
706  return false;
707  }
708  }
709  }
710 
711  NestedAnnotation* nested = dynamic_cast<NestedAnnotation*>(
712  builtin_annotations_["::@nested"]);
713  bool value;
714  if (nested->node_value_exists(node, value)) {
715  return value;
716  }
717 
718  return is_default_nested(node->defined_in());
719 }
720 
721 bool BE_GlobalData::is_default_nested(UTL_Scope* scope)
722 {
723  AST_Decl* module = dynamic_cast<AST_Decl*>(scope);
724  DefaultNestedAnnotation* default_nested = dynamic_cast<DefaultNestedAnnotation*>(
725  builtin_annotations_["::@default_nested"]);
726  if (module) {
727  bool value;
728  if (default_nested->node_value_exists(module, value)) {
729  return value;
730  }
731 
732  return is_default_nested(module->defined_in());
733  }
734 
735  return root_default_nested_;
736 }
737 
738 bool BE_GlobalData::check_key(AST_Decl* node, bool& value) const
739 {
740  KeyAnnotation* key = dynamic_cast<KeyAnnotation*>(builtin_annotations_["::@key"]);
741  value = key->absent_value;
742  return key->node_value_exists(node, value);
743 }
744 
745 bool BE_GlobalData::union_discriminator_is_key(AST_Union* node)
746 {
747  KeyAnnotation* key = dynamic_cast<KeyAnnotation*>(builtin_annotations_["::@key"]);
748  return key->union_value(node);
749 }
750 
751 void BE_GlobalData::warning(const char* msg, const char* filename, unsigned lineno)
752 {
753  if (idl_global->print_warnings()) {
754  if (filename) {
755  ACE_ERROR((LM_WARNING, ACE_TEXT("Warning - %C: \"%C\", line %u: %C\n"),
756  idl_global->prog_name(), filename, lineno, msg));
757  } else {
758  ACE_ERROR((LM_WARNING, ACE_TEXT("Warning - %C: %C\n"),
759  idl_global->prog_name(), msg));
760  }
761  }
762  idl_global->err()->last_warning = UTL_Error::EIDL_MISC;
763 }
764 
765 void BE_GlobalData::error(const char* msg, const char* filename, unsigned lineno)
766 {
767  if (filename) {
768  ACE_ERROR((LM_ERROR, ACE_TEXT("Error - %C: \"%C\", line %u: %C\n"),
769  idl_global->prog_name(), filename, lineno, msg));
770  } else {
771  ACE_ERROR((LM_ERROR, ACE_TEXT("Error - %C: %C\n"),
772  idl_global->prog_name(), msg));
773  }
774  idl_global->set_err_count(idl_global->err_count() + 1);
775  idl_global->err()->last_error = UTL_Error::EIDL_MISC;
776 }
777 
778 bool BE_GlobalData::warn_about_dcps_data_type()
779 {
780  if (!warn_about_dcps_data_type_) {
781  return false;
782  }
783  warn_about_dcps_data_type_ = false;
784  return idl_global->print_warnings();
785 }
786 
787 ExtensibilityKind BE_GlobalData::extensibility(AST_Decl* node, ExtensibilityKind default_extensibility, bool& has_annotation) const
788 {
789  has_annotation = true;
790 
791  if (builtin_annotations_["::@final"]->find_on(node)) {
793  }
794 
795  if (builtin_annotations_["::@appendable"]->find_on(node)) {
797  }
798 
799  if (builtin_annotations_["::@mutable"]->find_on(node)) {
801  }
802 
803  ExtensibilityAnnotation* extensibility_annotation =
804  dynamic_cast<ExtensibilityAnnotation*>(
805  builtin_annotations_["::@extensibility"]);
807  if (!extensibility_annotation->node_value_exists(node, value)) {
808  value = default_extensibility;
809  has_annotation = false;
810  }
811  return value;
812 }
813 
814 ExtensibilityKind BE_GlobalData::extensibility(AST_Decl* node, ExtensibilityKind default_extensibility) const
815 {
816  if (builtin_annotations_["::@final"]->find_on(node)) {
818  }
819 
820  if (builtin_annotations_["::@appendable"]->find_on(node)) {
822  }
823 
824  if (builtin_annotations_["::@mutable"]->find_on(node)) {
826  }
827 
828  ExtensibilityAnnotation* extensibility_annotation =
829  dynamic_cast<ExtensibilityAnnotation*>(
830  builtin_annotations_["::@extensibility"]);
832  if (!extensibility_annotation->node_value_exists(node, value)) {
833  value = default_extensibility;
834  }
835  return value;
836 }
837 
838 ExtensibilityKind BE_GlobalData::extensibility(AST_Decl* node) const
839 {
840  return extensibility(node, default_extensibility_);
841 }
842 
843 AutoidKind BE_GlobalData::autoid(AST_Decl* node) const
844 {
845  AutoidAnnotation* autoid_annotation = dynamic_cast<AutoidAnnotation*>(
846  builtin_annotations_["::@autoid"]);
848  if (autoid_annotation->node_value_exists(node, value)) {
849  return value;
850  }
851  return scoped_autoid(node->defined_in());
852 }
853 
854 AutoidKind BE_GlobalData::scoped_autoid(UTL_Scope* scope) const
855 {
856  AST_Decl* module = dynamic_cast<AST_Decl*>(scope);
857  AutoidAnnotation* autoid_annotation = dynamic_cast<AutoidAnnotation*>(
858  builtin_annotations_["::@autoid"]);
859  if (module) {
861  if (autoid_annotation->node_value_exists(module, value)) {
862  return value;
863  }
864  return scoped_autoid(module->defined_in());
865  }
866  return root_default_autoid_;
867 }
868 
869 bool BE_GlobalData::id(AST_Decl* node, ACE_CDR::ULong& value) const
870 {
871  IdAnnotation* id_annotation =
872  dynamic_cast<IdAnnotation*>(builtin_annotations_["::@id"]);
873  return id_annotation->node_value_exists(node, value);
874 }
875 
876 bool BE_GlobalData::hashid(AST_Decl* node, string& value) const
877 {
878  HashidAnnotation* hashid_annotation =
879  dynamic_cast<HashidAnnotation*>(builtin_annotations_["::@hashid"]);
880  return hashid_annotation->node_value_exists(node, value);
881 }
882 
883 bool BE_GlobalData::is_optional(AST_Decl* node) const
884 {
885  OptionalAnnotation* optional_annotation =
886  dynamic_cast<OptionalAnnotation*>(
887  builtin_annotations_["::@optional"]);
888  bool value = optional_annotation->absent_value;
889  optional_annotation->node_value_exists(node, value);
890  return value;
891 }
892 
893 bool BE_GlobalData::is_must_understand(AST_Decl* node) const
894 {
895  MustUnderstandAnnotation* must_understand_annotation =
896  dynamic_cast<MustUnderstandAnnotation*>(
897  builtin_annotations_["::@must_understand"]);
898  bool value = must_understand_annotation->absent_value;
899  must_understand_annotation->node_value_exists(node, value);
900  return value;
901 }
902 
903 bool BE_GlobalData::is_effectively_must_understand(AST_Decl* node) const
904 {
905  return is_must_understand(node) || is_key(node);
906 }
907 
908 bool BE_GlobalData::is_key(AST_Decl* node) const
909 {
910  bool value;
911  check_key(node, value);
912  return value;
913 }
914 
915 bool BE_GlobalData::is_external(AST_Decl* node) const
916 {
917  ExternalAnnotation* external_annotation =
918  dynamic_cast<ExternalAnnotation*>(
919  builtin_annotations_["::@external"]);
920  bool value = external_annotation->absent_value;
921  external_annotation->node_value_exists(node, value);
922  return value;
923 }
924 
925 bool BE_GlobalData::is_plain(AST_Decl* node) const
926 {
927  ExternalAnnotation* external_annotation =
928  dynamic_cast<ExternalAnnotation*>(
929  builtin_annotations_["::@external"]);
930  TryConstructAnnotation* try_construct_annotation =
931  dynamic_cast<TryConstructAnnotation*>(
932  builtin_annotations_["::@try_construct"]);
933 
934  for (AST_Annotation_Appls::iterator i = node->annotations().begin();
935  i != node->annotations().end(); ++i) {
936  AST_Annotation_Appl* appl = i->get();
937  if (appl &&
938  appl->annotation_decl() != external_annotation->declaration() &&
939  appl->annotation_decl() != try_construct_annotation->declaration()) {
940  return false;
941  }
942  }
943 
944  return true;
945 }
946 
947 TryConstructFailAction BE_GlobalData::try_construct(AST_Decl* node) const
948 {
949  TryConstructAnnotation* try_construct_annotation =
950  dynamic_cast<TryConstructAnnotation*>(
951  builtin_annotations_["::@try_construct"]);
953  if (!try_construct_annotation->node_value_exists(node, value)) {
954  value = default_try_construct_;
955  }
956  return value;
957 }
958 
959 TryConstructFailAction BE_GlobalData::sequence_element_try_construct(AST_Sequence* node)
960 {
961  TryConstructAnnotation* try_construct_annotation =
962  dynamic_cast<TryConstructAnnotation*>(builtin_annotations_["::@try_construct"]);
963  return try_construct_annotation->sequence_element_value(node);
964 }
965 
966 TryConstructFailAction BE_GlobalData::array_element_try_construct(AST_Array* node)
967 {
968  TryConstructAnnotation* try_construct_annotation =
969  dynamic_cast<TryConstructAnnotation*>(builtin_annotations_["::@try_construct"]);
970  return try_construct_annotation->array_element_value(node);
971 }
972 
973 TryConstructFailAction BE_GlobalData::union_discriminator_try_construct(AST_Union* node)
974 {
975  TryConstructAnnotation* try_construct_annotation =
976  dynamic_cast<TryConstructAnnotation*>(builtin_annotations_["::@try_construct"]);
977  return try_construct_annotation->union_value(node);
978 }
979 
980 OpenDDS::DataRepresentation BE_GlobalData::data_representations(
981  AST_Decl* node) const
982 {
983  using namespace OpenDDS;
984  DataRepresentationAnnotation* data_representation_annotation =
985  dynamic_cast<DataRepresentationAnnotation*>(
986  builtin_annotations_["::OpenDDS::@data_representation"]);
988  if (!data_representation_annotation->node_value_exists(node, value)) {
989  value = default_data_representation_;
990  }
991  return value;
992 }
993 
994 OpenDDS::XTypes::MemberId BE_GlobalData::compute_id(
995  AST_Structure* stru, AST_Field* field, AutoidKind auto_id, OpenDDS::XTypes::MemberId& member_id)
996 {
997  const MemberIdMap::const_iterator pos = member_id_map_.find(field);
998  if (pos != member_id_map_.end()) {
999  return pos->second;
1000  }
1001 
1004  const string field_name = canonical_name(field);
1005  string hash_id;
1006  MemberId mid;
1007  if (id(field, member_id)) {
1008  // @id
1009  mid = member_id++;
1010  } else if (hashid(field, hash_id)) {
1011  // @hashid
1012  mid = hash_member_name_to_id(hash_id.empty() ? field_name : hash_id);
1013  } else if (auto_id == autoidkind_hash) {
1014  mid = hash_member_name_to_id(field_name);
1015  } else {
1016  // auto_id == autoidkind_sequential
1017  mid = member_id++;
1018  }
1019 
1020  // Check for collision with ids in the same type
1021  GlobalMemberIdCollisionMap::iterator git = member_id_collision_map_.find(stru);
1022  if (git == member_id_collision_map_.end()) {
1023  git = member_id_collision_map_.insert(
1024  std::pair<AST_Structure*, MemberIdCollisionMap>(stru, MemberIdCollisionMap())).first;
1025  }
1026  MemberIdCollisionMap::iterator lit = git->second.find(mid);
1027  if (lit != git->second.end()) {
1028  std::ostringstream msg;
1029  msg << "Member id " << mid << " is the same as on field " << canonical_name(lit->second);
1030  be_util::misc_error_and_abort(msg.str(), field);
1031  }
1032  git->second.insert(std::pair<MemberId, AST_Field*>(mid, field));
1033 
1035  std::ostringstream msg;
1036  msg << "Member id " << mid << " exceeds the maximum allowed value (" <<
1038  be_util::misc_error_and_abort(msg.str(), field);
1039  }
1040  member_id_map_[field] = mid;
1041  return mid;
1042 }
1043 
1044 OpenDDS::XTypes::MemberId BE_GlobalData::get_id(AST_Field* field)
1045 {
1046  const MemberIdMap::const_iterator pos = member_id_map_.find(field);
1047  if (pos != member_id_map_.end()) {
1048  return pos->second;
1049  }
1050  be_util::misc_error_and_abort("Could not get member id for field");
1051  return -1;
1052 }
1053 
1054 bool BE_GlobalData::dynamic_data_adapter(AST_Decl* node) const
1055 {
1056  return !builtin_annotations_["::OpenDDS::internal::@no_dynamic_data_adapter"]->find_on(node);
1057 }
1058 
1059 bool BE_GlobalData::special_serialization(AST_Decl* node, std::string& template_name) const
1060 {
1062  const Anno* const anno =
1063  dynamic_cast<const Anno*>(builtin_annotations_["::OpenDDS::internal::@special_serialization"]);
1064  if (!anno->node_value_exists(node, template_name)) {
1065  return false;
1066  }
1067  if (template_name.empty()) {
1068  template_name = canonical_name(node->local_name());
1069  }
1070  return true;
1071 }
const char * filename(void) const
Definition: be_global.cpp:86
bool is_key(DDS::DynamicType_ptr type, const char *field)
#define ACE_ERROR(X)
const char * c_str(void) const
ACE_CDR::ULong MemberId
Definition: TypeObject.h:910
const LogLevel::Value value
Definition: debug.cpp:61
void parse_args(long &i, char **av)
Definition: be_global.cpp:338
TryConstructFailAction union_value(AST_Union *node) const
static const ACE_CDR::ULong MEMBER_ID_MAX
Maximum value for member id.
Definition: Serializer.h:387
TryConstructFailAction array_element_value(AST_Array *node) const
int strncasecmp(const char *s, const char *t, size_t len)
const char * name_
Definition: be_global.h:301
sequence< octet > key
BE_GlobalData * be_global
Definition: be_global.cpp:44
#define ACE_TEXT_ALWAYS_CHAR(STRING)
TryConstructFailAction
Definition: annotations.h:316
ACE_OutputCDR ostream
ExtensibilityKind
Definition: annotations.h:278
std::string platform
Definition: annotations.h:172
size_t strlen(const char *s)
char * filename_
AST_Annotation_Decl * declaration() const
Definition: annotations.cpp:75
std::string canonical_name(UTL_ScopedName *sn)
ACE_CDR::ULong hash_member_name_to_id(const OPENDDS_STRING &name)
Definition: TypeObject.cpp:389
int mkdir(const char *path, mode_t mode=ACE_DEFAULT_DIR_PERMS)
STL namespace.
int argc(void) const
TryConstructFailAction sequence_element_value(AST_Sequence *node) const
const T absent_value
Definition: annotations.h:104
virtual bool node_value_exists(AST_Decl *node, T &value) const
Definition: annotations.h:117
virtual ~BE_GlobalData(void)
Definition: be_global.cpp:76
LM_WARNING
#define ACE_TEXT_CHAR_TO_TCHAR(STRING)
ACE_UINT32 ULong
BE_Comment_Guard(const char *type, const char *name)
Definition: be_global.cpp:302
int strcmp(const char *s, const char *t)
const char *const name
Definition: debug.cpp:60
void destroy(void)
Definition: be_global.cpp:81
ACE_TEXT("TCP_Factory")
void invalid_option(char *option)
Definition: be_global.cpp:330
bool node_value_exists(AST_Decl *node, DataRepresentation &value) const
ACE_CString spawn_options(void)
Definition: be_global.cpp:325
int strcasecmp(const char *s, const char *t)
bool union_value(AST_Union *node) const
void misc_error_and_abort(const std::string &message, AST_Decl *node=0)
Report a miscellaneous error and abort.
void BE_abort()
Definition: be_produce.cpp:103
LM_ERROR
The Internal API and Implementation of OpenDDS.
Definition: AddressCache.h:28
const char * type_
Definition: be_global.h:301
AutoidKind
Definition: annotations.h:217
BE_GlobalData(void)
Definition: be_global.cpp:46
extensibility(MUTABLE) struct TypeLookup_getTypes_In
Definition: TypeLookup.idl:29