be_produce.cpp

Go to the documentation of this file.
00001 /*
00002 
00003 COPYRIGHT
00004 
00005 Copyright 1992, 1993, 1994 Sun Microsystems, Inc.  Printed in the United
00006 States of America.  All Rights Reserved.
00007 
00008 This product is protected by copyright and distributed under the following
00009 license restricting its use.
00010 
00011 The Interface Definition Language Compiler Front End (CFE) is made
00012 available for your use provided that you include this license and copyright
00013 notice on all media and documentation and the software program in which
00014 this product is incorporated in whole or part. You may copy and extend
00015 functionality (but may not remove functionality) of the Interface
00016 Definition Language CFE without charge, but you are not authorized to
00017 license or distribute it to anyone else except as part of a product or
00018 program developed by you or with the express written consent of Sun
00019 Microsystems, Inc. ("Sun").
00020 
00021 The names of Sun Microsystems, Inc. and any of its subsidiaries or
00022 affiliates may not be used in advertising or publicity pertaining to
00023 distribution of Interface Definition Language CFE as permitted herein.
00024 
00025 This license is effective until terminated by Sun for failure to comply
00026 with this license.  Upon termination, you shall destroy or return all code
00027 and documentation for the Interface Definition Language CFE.
00028 
00029 INTERFACE DEFINITION LANGUAGE CFE IS PROVIDED AS IS WITH NO WARRANTIES OF
00030 ANY KIND INCLUDING THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS
00031 FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR ARISING FROM A COURSE OF
00032 DEALING, USAGE OR TRADE PRACTICE.
00033 
00034 INTERFACE DEFINITION LANGUAGE CFE IS PROVIDED WITH NO SUPPORT AND WITHOUT
00035 ANY OBLIGATION ON THE PART OF Sun OR ANY OF ITS SUBSIDIARIES OR AFFILIATES
00036 TO ASSIST IN ITS USE, CORRECTION, MODIFICATION OR ENHANCEMENT.
00037 
00038 SUN OR ANY OF ITS SUBSIDIARIES OR AFFILIATES SHALL HAVE NO LIABILITY WITH
00039 RESPECT TO THE INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY
00040 INTERFACE DEFINITION LANGUAGE CFE OR ANY PART THEREOF.
00041 
00042 IN NO EVENT WILL SUN OR ANY OF ITS SUBSIDIARIES OR AFFILIATES BE LIABLE FOR
00043 ANY LOST REVENUE OR PROFITS OR OTHER SPECIAL, INDIRECT AND CONSEQUENTIAL
00044 DAMAGES, EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
00045 
00046 Use, duplication, or disclosure by the government is subject to
00047 restrictions as set forth in subparagraph (c)(1)(ii) of the Rights in
00048 Technical Data and Computer Software clause at DFARS 252.227-7013 and FAR
00049 52.227-19.
00050 
00051 Sun, Sun Microsystems and the Sun logo are trademarks or registered
00052 trademarks of Sun Microsystems, Inc.
00053 
00054 SunSoft, Inc.
00055 2550 Garcia Avenue
00056 Mountain View, California  94043
00057 
00058 NOTE:
00059 
00060 SunOS, SunSoft, Sun, Solaris, Sun Microsystems or the Sun logo are
00061 trademarks or registered trademarks of Sun Microsystems, Inc.
00062 
00063 */
00064 
00065 // be_produce.cpp - Produce the work of the BE
00066 
00067 #include "global_extern.h"
00068 
00069 #include "be_extern.h"
00070 #include "dds_visitor.h"
00071 
00072 #include "ast_root.h"
00073 #include "utl_string.h"
00074 
00075 #include "ace/OS_NS_strings.h"
00076 #include "ace/OS_NS_sys_time.h"
00077 #include "ace/OS_NS_unistd.h"
00078 
00079 #include "../Version.h"
00080 #include "ace/Version.h"
00081 
00082 #include <iostream>
00083 #include <fstream>
00084 #include <sstream>
00085 #include <string>
00086 #include <limits>
00087 #include <cassert>
00088 
00089 using namespace std;
00090 
00091 // Clean up before exit, whether successful or not.
00092 // Need not be exported since it is called only from this file.
00093 void
00094 BE_cleanup()
00095 {
00096   idl_global->destroy();
00097 }
00098 
00099 // Abort this run of the BE.
00100 void
00101 BE_abort()
00102 {
00103   ACE_ERROR((LM_ERROR, ACE_TEXT("Fatal Error - Aborting\n")));
00104   BE_cleanup();
00105   ACE_OS::exit(1);
00106 }
00107 
00108 namespace {
00109 
00110 /// generate a macro name for the #ifndef header-double-include protector
00111 string to_macro(const char* fn)
00112 {
00113   string ret = "OPENDDS_IDL_GENERATED_";
00114 
00115   for (size_t i = 0; i < strlen(fn); ++i) {
00116     if (isalnum(fn[i])) {
00117       ret += static_cast<char>(toupper(fn[i]));
00118     } else if (ret[ret.size() - 1] != '_') {
00119       ret += '_';
00120     }
00121   }
00122 
00123   // Add some random characters since two files of the same name (in different
00124   // directories) could be used in the same translation unit.  The algorithm
00125   // for randomness comes from TAO_IDL's implementation.
00126 
00127   const size_t NUM_CHARS = 6;
00128 
00129   const ACE_Time_Value now = ACE_OS::gettimeofday();
00130   ACE_UINT64 msec;
00131   now.msec(msec);
00132 
00133   msec += ACE_OS::getpid() + (size_t) ACE_OS::thr_self();
00134 
00135   unsigned int seed = static_cast<unsigned int>(msec);
00136 #ifdef max
00137 #undef max
00138 #endif
00139   const float MAX_VAL = static_cast<float>(numeric_limits<char>::max());
00140   const float coefficient = static_cast<float>(MAX_VAL / (RAND_MAX + 1.0f));
00141 
00142   if (ret[ret.size() - 1] != '_') ret += '_';
00143 
00144   for (unsigned int n = 0; n < NUM_CHARS; ++n) {
00145     char r;
00146     do {
00147       r = static_cast<char>(coefficient * ACE_OS::rand_r(&seed));
00148     } while (!isalnum(r));
00149 
00150     ret += static_cast<char>(toupper(r));
00151   }
00152 
00153   return ret;
00154 }
00155 
00156 /// change *.cpp to *.h
00157 string to_header(const char* cpp_name)
00158 {
00159   size_t len = strlen(cpp_name);
00160   assert(len >= 5 && 0 == ACE_OS::strcasecmp(cpp_name + len - 4, ".cpp"));
00161   string base_name(cpp_name, len - 4);
00162   return base_name + ".h";
00163 }
00164 
00165 void postprocess(const char* fn, ostringstream& content,
00166                  BE_GlobalData::stream_enum_t which)
00167 {
00168   ostringstream out;
00169 
00170   if (which == BE_GlobalData::STREAM_H ||
00171       which == BE_GlobalData::STREAM_LANG_H) {
00172     out << "/* -*- C++ -*- */\n";
00173   }
00174 
00175   if (which != BE_GlobalData::STREAM_WS)
00176     out << "/* ";
00177   else
00178     out << "# ";
00179   out << "Generated by " << idl_global->prog_name()
00180       << " version " DDS_VERSION " (ACE version " ACE_VERSION
00181       << ") running on input file "
00182       << idl_global->main_filename()->get_string();
00183   if (which != BE_GlobalData::STREAM_WS)
00184     out << " */";
00185   out << "\n";
00186 
00187   //  if .h add #ifndef...#define
00188   string macrofied;
00189 
00190   switch (which) {
00191   case BE_GlobalData::STREAM_H:
00192   case BE_GlobalData::STREAM_FACETS_H:
00193   case BE_GlobalData::STREAM_LANG_H: {
00194     macrofied = to_macro(fn);
00195     out << "#ifndef " << macrofied << "\n#define " << macrofied << '\n';
00196     if (which == BE_GlobalData::STREAM_LANG_H) {
00197       if (be_global->language_mapping() == BE_GlobalData::LANGMAP_FACE_CXX ||
00198           be_global->language_mapping() == BE_GlobalData::LANGMAP_SP_CXX) {
00199         out << "#include <tao/orbconf.h>\n"
00200                "#include <tao/Basic_Types.h>\n";
00201       }
00202     } else {
00203       string taoheader = be_global->header_name_.c_str();
00204       taoheader.replace(taoheader.find("TypeSupportImpl.h"), 17, "C.h");
00205       out << "#include \"" << be_global->tao_inc_pre_ << taoheader << "\"\n";
00206     }
00207     if (which == BE_GlobalData::STREAM_H) {
00208       out << "#include \"dds/DCPS/Definitions.h\"\n";
00209       out << "#include \"dds/DdsDcpsC.h\"\n";
00210     }
00211   }
00212   break;
00213   case BE_GlobalData::STREAM_CPP: {
00214     ACE_CString pch = be_global->pch_include();
00215     if (pch.length()) {
00216       out << "#include \"" << pch << "\"\n";
00217     }
00218     if (be_global->java_arg().length() == 0) {
00219       string header = to_header(fn);
00220       out << "#include \"" << header << "\"\n\n";
00221     } else {
00222       out << "#include \"" << be_global->header_name_.c_str() << "\"\n\n";
00223     }
00224   }
00225   break;
00226   case BE_GlobalData::STREAM_FACETS_CPP: {
00227     ACE_CString pch = be_global->pch_include();
00228     if (pch.length()) {
00229       out << "#include \"" << pch << "\"\n";
00230     }
00231     out << "#include \"" << be_global->facets_header_name_.c_str() << "\"\n"
00232       "#include \"" << be_global->header_name_.c_str() << "\"\n"
00233       "#include \"dds/FACE/FaceTSS.h\"\n\n"
00234       "namespace FACE { namespace TS {\n\n";
00235   }
00236   break;
00237   case BE_GlobalData::STREAM_IDL: {
00238     macrofied = to_macro(fn);
00239     out << "#ifndef " << macrofied << "\n#define " << macrofied << '\n';
00240 
00241 #ifdef ACE_HAS_CDR_FIXED
00242     out << "#define __OPENDDS_IDL_HAS_FIXED\n";
00243 #endif
00244 
00245     string filebase(be_global->filename());
00246     const size_t idx = filebase.find_last_of("/\\"); // allow either slash
00247     if (idx != string::npos) {
00248       filebase = filebase.substr(idx + 1);
00249     }
00250     out << "#include \"" << filebase << "\"\n\n";
00251   }
00252   break;
00253   default:
00254     ;
00255   }
00256 
00257   out << be_global->get_include_block(which);
00258 
00259   out << content.str();
00260 
00261   switch (which) {
00262   case BE_GlobalData::STREAM_H:
00263   case BE_GlobalData::STREAM_IDL:
00264   case BE_GlobalData::STREAM_FACETS_H:
00265   case BE_GlobalData::STREAM_LANG_H:
00266     out << "#endif /* " << macrofied << " */\n";
00267     break;
00268   case BE_GlobalData::STREAM_FACETS_CPP:
00269     out << "}}\n";
00270     break;
00271   default:
00272     ;
00273   }
00274 
00275   if (!BE_GlobalData::writeFile(fn, out.str())) {
00276     BE_abort();  //error message already printed
00277   }
00278 }
00279 
00280 } // namespace
00281 
00282 // Do the work of this BE. This is the starting point for code generation.
00283 void
00284 BE_produce()
00285 {
00286   //search for #includes in the IDL, add them as #includes in the stubs/skels
00287   const char* idl_fn = idl_global->main_filename()->get_string();
00288 
00289   const BE_GlobalData::stream_enum_t out_stream =
00290     be_global->language_mapping() == BE_GlobalData::LANGMAP_NONE
00291     ? BE_GlobalData::STREAM_H : BE_GlobalData::STREAM_LANG_H;
00292 
00293   ifstream idl(idl_fn);
00294   const size_t buffer_sz = 512;
00295   char buffer[buffer_sz];
00296 
00297   while (idl) {
00298     idl.getline(buffer, buffer_sz);
00299 
00300     if (0 == strncmp("#include", buffer, 8)) { //FUTURE: account for comments?
00301       string inc(buffer + 8);
00302       size_t delim1 = inc.find_first_of("<\"");
00303       size_t delim2 = inc.find_first_of(">\"", delim1 + 1);
00304       string included(inc, delim1 + 1, delim2 - delim1 - 1);
00305       size_t len = included.size();
00306       string base_name;
00307 
00308       if (len >= 5 &&
00309           0 == ACE_OS::strcasecmp(included.c_str() + len - 4, ".idl")) {
00310         base_name.assign(included.c_str(), len - 4);
00311 
00312       } else if (len >= 6 &&
00313                  0 == ACE_OS::strcasecmp(included.c_str() + len - 5, ".pidl")) {
00314         base_name.assign(included.c_str(), len - 5);
00315 
00316       } else {
00317         ACE_ERROR((LM_ERROR, ACE_TEXT("(%N:%l) BE_produce - included ")
00318                    ACE_TEXT("file must end in .idl or .pidl\n")));
00319         BE_abort();
00320       }
00321 
00322       string stb_inc = base_name + "C.h";
00323       if (stb_inc != "tao/orbC.h") {
00324         be_global->add_include(stb_inc.c_str(), out_stream);
00325         if (stb_inc == "orbC.h" ||
00326             (stb_inc.size() >= 7
00327             && stb_inc.substr(stb_inc.size() - 7) == "/orbC.h") ) {
00328           ACE_DEBUG((LM_WARNING,
00329                      ACE_TEXT("Warning: (%s) Potential inclusion of TAO orbC.H ")
00330                      ACE_TEXT(" Include TAO orb.idl with path of tao/orb.idl")
00331                      ACE_TEXT(" to prevent compilation errors\n"), idl_fn));
00332         }
00333       }
00334 
00335     }
00336   }
00337 
00338   idl.close();
00339 
00340   be_global->open_streams(idl_fn);
00341 
00342   AST_Decl* d = idl_global->root();
00343   AST_Root* root = AST_Root::narrow_from_decl(d);
00344 
00345   if (root == 0) {
00346     ACE_ERROR((LM_ERROR,
00347                ACE_TEXT("(%N:%l) BE_produce - ")
00348                ACE_TEXT("No Root\n")));
00349 
00350     BE_abort();
00351   }
00352 
00353   be_global->set_inc_paths(idl_global->idl_flags());
00354 
00355   const bool java_ts_only = be_global->java_arg().length() > 0;
00356 
00357   dds_visitor visitor(d, java_ts_only);
00358 
00359   if (root->ast_accept(&visitor) == -1) {
00360     ACE_ERROR((LM_ERROR,
00361                ACE_TEXT("(%N:%l) BE_produce -")
00362                ACE_TEXT(" failed to accept adding visitor\n")));
00363     BE_abort();
00364   }
00365 
00366   if (!java_ts_only) {
00367     postprocess(be_global->header_name_.c_str(),
00368                 be_global->header_, BE_GlobalData::STREAM_H);
00369     if (!be_global->suppress_idl()) {
00370       postprocess(be_global->idl_name_.c_str(),
00371                   be_global->idl_, BE_GlobalData::STREAM_IDL);
00372     }
00373   }
00374 
00375   postprocess(be_global->impl_name_.c_str(),
00376               be_global->impl_, BE_GlobalData::STREAM_CPP);
00377 
00378   if (be_global->generate_wireshark()) {
00379     postprocess(be_global->ws_config_name_.c_str(),
00380                 be_global->ws_config_, BE_GlobalData::STREAM_WS);
00381   }
00382 
00383   if (be_global->generate_itl()) {
00384     if (!BE_GlobalData::writeFile(be_global->itl_name_.c_str(), be_global->itl_.str())) {
00385       BE_abort();  //error message already printed
00386     }
00387   }
00388 
00389   if (be_global->face_ts()) {
00390     postprocess(be_global->facets_header_name_.c_str(), be_global->facets_header_,
00391                 BE_GlobalData::STREAM_FACETS_H);
00392     postprocess(be_global->facets_impl_name_.c_str(), be_global->facets_impl_,
00393                 BE_GlobalData::STREAM_FACETS_CPP);
00394   }
00395 
00396   if (be_global->language_mapping() == BE_GlobalData::LANGMAP_FACE_CXX ||
00397       be_global->language_mapping() == BE_GlobalData::LANGMAP_SP_CXX) {
00398     postprocess(be_global->lang_header_name_.c_str(), be_global->lang_header_,
00399                 BE_GlobalData::STREAM_LANG_H);
00400   }
00401 
00402   BE_cleanup();
00403 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 10 Aug 2018 for OpenDDS by  doxygen 1.6.1