OpenDDS  Snapshot(2023/04/28-20:55)
be_produce.cpp
Go to the documentation of this file.
1 /*
2 
3 COPYRIGHT
4 
5 Copyright 1992, 1993, 1994 Sun Microsystems, Inc. Printed in the United
6 States of America. All Rights Reserved.
7 
8 This product is protected by copyright and distributed under the following
9 license restricting its use.
10 
11 The Interface Definition Language Compiler Front End (CFE) is made
12 available for your use provided that you include this license and copyright
13 notice on all media and documentation and the software program in which
14 this product is incorporated in whole or part. You may copy and extend
15 functionality (but may not remove functionality) of the Interface
16 Definition Language CFE without charge, but you are not authorized to
17 license or distribute it to anyone else except as part of a product or
18 program developed by you or with the express written consent of Sun
19 Microsystems, Inc. ("Sun").
20 
21 The names of Sun Microsystems, Inc. and any of its subsidiaries or
22 affiliates may not be used in advertising or publicity pertaining to
23 distribution of Interface Definition Language CFE as permitted herein.
24 
25 This license is effective until terminated by Sun for failure to comply
26 with this license. Upon termination, you shall destroy or return all code
27 and documentation for the Interface Definition Language CFE.
28 
29 INTERFACE DEFINITION LANGUAGE CFE IS PROVIDED AS IS WITH NO WARRANTIES OF
30 ANY KIND INCLUDING THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS
31 FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR ARISING FROM A COURSE OF
32 DEALING, USAGE OR TRADE PRACTICE.
33 
34 INTERFACE DEFINITION LANGUAGE CFE IS PROVIDED WITH NO SUPPORT AND WITHOUT
35 ANY OBLIGATION ON THE PART OF Sun OR ANY OF ITS SUBSIDIARIES OR AFFILIATES
36 TO ASSIST IN ITS USE, CORRECTION, MODIFICATION OR ENHANCEMENT.
37 
38 SUN OR ANY OF ITS SUBSIDIARIES OR AFFILIATES SHALL HAVE NO LIABILITY WITH
39 RESPECT TO THE INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY
40 INTERFACE DEFINITION LANGUAGE CFE OR ANY PART THEREOF.
41 
42 IN NO EVENT WILL SUN OR ANY OF ITS SUBSIDIARIES OR AFFILIATES BE LIABLE FOR
43 ANY LOST REVENUE OR PROFITS OR OTHER SPECIAL, INDIRECT AND CONSEQUENTIAL
44 DAMAGES, EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
45 
46 Use, duplication, or disclosure by the government is subject to
47 restrictions as set forth in subparagraph (c)(1)(ii) of the Rights in
48 Technical Data and Computer Software clause at DFARS 252.227-7013 and FAR
49 52.227-19.
50 
51 Sun, Sun Microsystems and the Sun logo are trademarks or registered
52 trademarks of Sun Microsystems, Inc.
53 
54 SunSoft, Inc.
55 2550 Garcia Avenue
56 Mountain View, California 94043
57 
58 NOTE:
59 
60 SunOS, SunSoft, Sun, Solaris, Sun Microsystems or the Sun logo are
61 trademarks or registered trademarks of Sun Microsystems, Inc.
62 
63 */
64 
65 // be_produce.cpp - Produce the work of the BE
66 
67 #include "global_extern.h"
68 
69 #include "be_extern.h"
70 #include "dds_visitor.h"
71 
72 #include "ast_root.h"
73 #include "utl_string.h"
74 
75 #include "ace/OS_NS_strings.h"
76 #include "ace/OS_NS_sys_time.h"
77 #include "ace/OS_NS_unistd.h"
78 
79 #include "../Version.h"
80 #include "ace/Version.h"
81 
82 #include <iostream>
83 #include <fstream>
84 #include <sstream>
85 #include <string>
86 #include <limits>
87 #include <cassert>
88 
89 using namespace std;
90 
91 // Clean up before exit, whether successful or not.
92 // Need not be exported since it is called only from this file.
93 void
95 {
96  if (idl_global) {
97  idl_global->destroy();
98  }
99 }
100 
101 // Abort this run of the BE.
102 void
104 {
105  ACE_ERROR((LM_ERROR, ACE_TEXT("Fatal Error - Aborting\n")));
106  BE_cleanup();
107  ACE_OS::exit(1);
108 }
109 
110 namespace {
111 
112 /// generate a macro name for the #ifndef header-double-include protector
113 string to_macro(const char* fn)
114 {
115  string ret = "OPENDDS_IDL_GENERATED_";
116 
117  for (size_t i = 0; i < strlen(fn); ++i) {
118  if (isalnum(fn[i])) {
119  ret += static_cast<char>(toupper(fn[i]));
120  } else if (ret[ret.size() - 1] != '_') {
121  ret += '_';
122  }
123  }
124 
125  // Add some random characters since two files of the same name (in different
126  // directories) could be used in the same translation unit. The algorithm
127  // for randomness comes from TAO_IDL's implementation.
128 
129  const size_t NUM_CHARS = 6;
130 
131  const ACE_Time_Value now = ACE_OS::gettimeofday();
132  ACE_UINT64 msec;
133  now.msec(msec);
134 
135  msec += ACE_OS::getpid() + (size_t) ACE_OS::thr_self();
136 
137  unsigned int seed = static_cast<unsigned int>(msec);
138 
139  if (ret[ret.size() - 1] != '_') ret += '_';
140  static const char alphanum[] =
141  "0123456789"
142  "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
143 
144  for (unsigned int n = 0; n < NUM_CHARS; ++n) {
145  ret += alphanum[ACE_OS::rand_r(&seed) % (sizeof(alphanum) - 1)];
146  }
147 
148  return ret;
149 }
150 
151 /// change *.cpp to *.h
152 string to_header(const char* cpp_name)
153 {
154  size_t len = strlen(cpp_name);
155  assert(len >= 5 && 0 == ACE_OS::strcasecmp(cpp_name + len - 4, ".cpp"));
156  string base_name(cpp_name, len - 4);
157  return base_name + ".h";
158 }
159 
160 void postprocess(const char* fn, ostringstream& content,
161  BE_GlobalData::stream_enum_t which)
162 {
163  ostringstream out;
164 
165  if (which == BE_GlobalData::STREAM_H ||
166  which == BE_GlobalData::STREAM_LANG_H) {
167  out << "/* -*- C++ -*- */\n";
168  }
169 
170  out << "/* Generated by " << idl_global->prog_name()
171  << " version " OPENDDS_VERSION " (ACE version " ACE_VERSION
172  << ") running on input file "
173  << idl_global->main_filename()->get_string()
174  << " */\n";
175 
176  // if .h add #ifndef...#define
177  string macrofied;
178 
179  switch (which) {
180  case BE_GlobalData::STREAM_H:
181  case BE_GlobalData::STREAM_FACETS_H:
182  case BE_GlobalData::STREAM_LANG_H: {
183  macrofied = to_macro(fn);
184  out << "#ifndef " << macrofied << "\n#define " << macrofied << '\n';
185  if (which == BE_GlobalData::STREAM_H) {
186  out <<
187  "\n"
188  "#include <dds/Version.h>\n"
189  "#if !OPENDDS_VERSION_EXACTLY(" << OPENDDS_MAJOR_VERSION
190  << ", " << OPENDDS_MINOR_VERSION
191  << ", " << OPENDDS_MICRO_VERSION << ")\n"
192  "# error \"This file should be regenerated with opendds_idl\"\n"
193  "#endif\n"
194  "#include <dds/DCPS/Definitions.h>\n"
195  "\n"
196  "#include <dds/DdsDcpsC.h>\n"
197  "\n";
198  }
199  if (which == BE_GlobalData::STREAM_LANG_H) {
200  if (be_global->language_mapping() == BE_GlobalData::LANGMAP_FACE_CXX ||
201  be_global->language_mapping() == BE_GlobalData::LANGMAP_SP_CXX) {
202  out <<
203  "#include <tao/orbconf.h>\n"
204  "#include <tao/Basic_Types_IDLv4.h>\n"
205  "TAO_BEGIN_VERSIONED_NAMESPACE_DECL\n"
206  "namespace CORBA {\n"
207  " using namespace IDLv4;\n"
208  "}\n"
209  "TAO_END_VERSIONED_NAMESPACE_DECL\n";
210  }
211  } else {
212  string taoheader = be_global->header_name_.c_str();
213  taoheader.replace(taoheader.find("TypeSupportImpl.h"), 17, "C.h");
214  const bool explicit_ints = be_global->tao_inc_pre_.length()
215  && (taoheader == "Int8SeqC.h" || taoheader == "UInt8SeqC.h");
216  std::string indent;
217  if (explicit_ints) {
218  out << "#if OPENDDS_HAS_EXPLICIT_INTS\n";
219  indent = " ";
220  }
221  out << "#" << indent << "include \"" << be_global->tao_inc_pre_ << taoheader << "\"\n";
222  if (explicit_ints) {
223  out << "#endif\n";
224  }
225  }
226  }
227  break;
228  case BE_GlobalData::STREAM_CPP: {
229  ACE_CString pch = be_global->pch_include();
230  if (pch.length()) {
231  out << "#include \"" << pch << "\"\n";
232  }
233  if (be_global->java_arg().length() == 0) {
234  string header = to_header(fn);
235  out << "#include \"" << header << "\"\n\n";
236  } else {
237  out << "#include \"" << be_global->header_name_.c_str() << "\"\n\n";
238  }
239  }
240  break;
241  case BE_GlobalData::STREAM_FACETS_CPP: {
242  ACE_CString pch = be_global->pch_include();
243  if (pch.length()) {
244  out << "#include \"" << pch << "\"\n";
245  }
246  out << "#include \"" << be_global->facets_header_name_.c_str() << "\"\n"
247  "#include \"" << be_global->header_name_.c_str() << "\"\n"
248  "#include \"dds/FACE/FaceTSS.h\"\n\n"
249  "namespace FACE { namespace TS {\n\n";
250  }
251  break;
252  case BE_GlobalData::STREAM_IDL: {
253  macrofied = to_macro(fn);
254  out << "#ifndef " << macrofied << "\n#define " << macrofied << '\n';
255 
256 #ifdef ACE_HAS_CDR_FIXED
257  out << "#define __OPENDDS_IDL_HAS_FIXED\n";
258 #endif
259 
260  string filebase(be_global->filename());
261  const size_t idx = filebase.find_last_of("/\\"); // allow either slash
262  if (idx != string::npos) {
263  filebase = filebase.substr(idx + 1);
264  }
265  out << "#include \"" << filebase << "\"\n\n";
266  }
267  break;
268  default:
269  ;
270  }
271 
272  out << be_global->get_include_block(which);
273 
274  out << content.str();
275 
276  switch (which) {
277  case BE_GlobalData::STREAM_H:
278  case BE_GlobalData::STREAM_IDL:
279  case BE_GlobalData::STREAM_FACETS_H:
280  case BE_GlobalData::STREAM_LANG_H:
281  out << "#endif /* " << macrofied << " */\n";
282  break;
283  case BE_GlobalData::STREAM_FACETS_CPP:
284  out << "}}\n";
285  break;
286  default:
287  ;
288  }
289 
290  if (!BE_GlobalData::writeFile(fn, out.str())) {
291  BE_abort(); //error message already printed
292  }
293 }
294 
295 } // namespace
296 
297 // Do the work of this BE. This is the starting point for code generation.
298 void
300 {
301  const char* idl_fn = idl_global->main_filename()->get_string();
302  be_global->filename(idl_fn);
303 
304  const BE_GlobalData::stream_enum_t out_stream =
305  be_global->language_mapping() == BE_GlobalData::LANGMAP_NONE
306  ? BE_GlobalData::STREAM_H : BE_GlobalData::STREAM_LANG_H;
307 
308  ifstream idl(idl_fn);
309  const size_t buffer_sz = 512;
310  char buffer[buffer_sz];
311  unsigned lineno = 0;
312 
313  while (idl) {
314  idl.getline(buffer, buffer_sz);
315  ++lineno;
316 
317  // search for #includes in the IDL, add them as #includes in the stubs/skels
318  if (0 == strncmp("#include", buffer, 8)) { //FUTURE: account for comments?
319  string inc(buffer + 8);
320  size_t delim1 = inc.find_first_of("<\"");
321  size_t delim2 = inc.find_first_of(">\"", delim1 + 1);
322  string included(inc, delim1 + 1, delim2 - delim1 - 1);
323  size_t len = included.size();
324  string base_name;
325 
326  if (len >= 5 &&
327  0 == ACE_OS::strcasecmp(included.c_str() + len - 4, ".idl")) {
328  base_name.assign(included.c_str(), len - 4);
329 
330  } else if (len >= 6 &&
331  0 == ACE_OS::strcasecmp(included.c_str() + len - 5, ".pidl")) {
332  base_name.assign(included.c_str(), len - 5);
333 
334  } else {
335  continue;
336  }
337 
338  if (be_global->language_mapping() == BE_GlobalData::LANGMAP_SP_CXX &&
339  base_name.substr(0, 4) == "tao/" &&
340  base_name.substr(base_name.size() - 3) == "Seq") {
341  continue; // with Safety Profile C++, skip include of tao/*SeqC.h
342  }
343 
344  string stb_inc = base_name + "C.h";
345  if (stb_inc != "tao/orbC.h") {
346  be_global->add_include(stb_inc.c_str(), out_stream);
347  if (stb_inc == "orbC.h" ||
348  (stb_inc.size() >= 7
349  && stb_inc.substr(stb_inc.size() - 7) == "/orbC.h") ) {
350  be_global->warning(
351  "Potential inclusion of TAO orbC.h\n"
352  " Include TAO orb.idl with path of tao/orb.idl"
353  " to prevent compilation errors",
354  idl_fn, lineno);
355  }
356  }
357 
358  }
359  }
360 
361  idl.close();
362 
363  be_global->open_streams(idl_fn);
364 
365  AST_Decl* d = idl_global->root();
366  AST_Root* root = dynamic_cast<AST_Root*>(d);
367 
368  if (root == 0) {
370  ACE_TEXT("(%N:%l) BE_produce - ")
371  ACE_TEXT("No Root\n")));
372 
373  BE_abort();
374  }
375 
376  be_global->set_inc_paths(idl_global->idl_flags());
377 
378  const bool java_ts_only = be_global->java_arg().length() > 0;
379 
380  dds_visitor visitor(d, java_ts_only);
381 
382  if (root->ast_accept(&visitor) == -1) {
384  ACE_TEXT("(%N:%l) BE_produce -")
385  ACE_TEXT(" failed to accept adding visitor\n")));
386  BE_abort();
387  }
388 
389  if (!java_ts_only) {
390  postprocess(be_global->header_name_.c_str(),
391  be_global->header_, BE_GlobalData::STREAM_H);
392  if (!be_global->suppress_idl()) {
393  postprocess(be_global->idl_name_.c_str(),
394  be_global->idl_, BE_GlobalData::STREAM_IDL);
395  }
396  }
397 
398  postprocess(be_global->impl_name_.c_str(),
399  be_global->impl_, BE_GlobalData::STREAM_CPP);
400 
401  if (be_global->itl()) {
402  if (!BE_GlobalData::writeFile(be_global->itl_name_.c_str(), be_global->itl_.str())) {
403  BE_abort(); //error message already printed
404  }
405  }
406 
407  if (be_global->face_ts()) {
408  postprocess(be_global->facets_header_name_.c_str(), be_global->facets_header_,
409  BE_GlobalData::STREAM_FACETS_H);
410  postprocess(be_global->facets_impl_name_.c_str(), be_global->facets_impl_,
411  BE_GlobalData::STREAM_FACETS_CPP);
412  }
413 
414  if (be_global->language_mapping() != BE_GlobalData::LANGMAP_NONE) {
415  postprocess(be_global->lang_header_name_.c_str(), be_global->lang_header_,
416  BE_GlobalData::STREAM_LANG_H);
417  }
418 
419  BE_cleanup();
420 }
const char * filename(void) const
Definition: be_global.cpp:86
void BE_produce()
Definition: be_produce.cpp:299
#define OPENDDS_VERSION
Definition: Version.h:16
#define OPENDDS_MICRO_VERSION
Definition: Version.h:13
#define ACE_ERROR(X)
const char * c_str(void) const
int strncmp(const char *s, const char *t, size_t len)
void exit(int status=0) ACE_GCC_NO_RETURN
ACE_thread_t thr_self(void)
size_t strlen(const char *s)
void BE_abort()
Definition: be_produce.cpp:103
#define ACE_VERSION
Christopher Diggins *renamed files *fixing compilation errors *adding Visual C project file *removed make Max Lybbert *removed references to missing and unused header
Definition: CHANGELOG.txt:8
#define OPENDDS_MINOR_VERSION
Definition: Version.h:12
STL namespace.
void BE_cleanup()
Definition: be_produce.cpp:94
#define OPENDDS_MAJOR_VERSION
Definition: Version.h:11
ACE_TEXT("TCP_Factory")
unsigned long long ACE_UINT64
unsigned long msec(void) const
int strcasecmp(const char *s, const char *t)
BE_GlobalData * be_global
Definition: be_global.cpp:44
ACE_Time_Value gettimeofday(void)
size_type length(void) const
LM_ERROR
pid_t getpid(void)
int rand_r(unsigned int *seed)