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     }
00210   }
00211   break;
00212   case BE_GlobalData::STREAM_CPP: {
00213     ACE_CString pch = be_global->pch_include();
00214     if (pch.length()) {
00215       out << "#include \"" << pch << "\"\n";
00216     }
00217     if (be_global->java_arg().length() == 0) {
00218       string header = to_header(fn);
00219       out << "#include \"" << header << "\"\n\n";
00220     } else {
00221       out << "#include \"" << be_global->header_name_.c_str() << "\"\n\n";
00222     }
00223   }
00224   break;
00225   case BE_GlobalData::STREAM_FACETS_CPP: {
00226     ACE_CString pch = be_global->pch_include();
00227     if (pch.length()) {
00228       out << "#include \"" << pch << "\"\n";
00229     }
00230     out << "#include \"" << be_global->facets_header_name_.c_str() << "\"\n"
00231       "#include \"" << be_global->header_name_.c_str() << "\"\n"
00232       "#include \"dds/FACE/FaceTSS.h\"\n\n"
00233       "namespace FACE { namespace TS {\n\n";
00234   }
00235   break;
00236   case BE_GlobalData::STREAM_IDL: {
00237     macrofied = to_macro(fn);
00238     out << "#ifndef " << macrofied << "\n#define " << macrofied << '\n';
00239 
00240 #ifdef ACE_HAS_CDR_FIXED
00241     out << "#define __OPENDDS_IDL_HAS_FIXED\n";
00242 #endif
00243 
00244     string filebase(be_global->filename());
00245     const size_t idx = filebase.find_last_of("/\\"); // allow either slash
00246     if (idx != string::npos) {
00247       filebase = filebase.substr(idx + 1);
00248     }
00249     out << "#include \"" << filebase << "\"\n\n";
00250   }
00251   break;
00252   default:
00253     ;
00254   }
00255 
00256   out << be_global->get_include_block(which);
00257 
00258   out << content.str();
00259 
00260   switch (which) {
00261   case BE_GlobalData::STREAM_H:
00262   case BE_GlobalData::STREAM_IDL:
00263   case BE_GlobalData::STREAM_FACETS_H:
00264   case BE_GlobalData::STREAM_LANG_H:
00265     out << "#endif /* " << macrofied << " */\n";
00266     break;
00267   case BE_GlobalData::STREAM_FACETS_CPP:
00268     out << "}}\n";
00269     break;
00270   default:
00271     ;
00272   }
00273 
00274   if (!BE_GlobalData::writeFile(fn, out.str())) {
00275     BE_abort();  //error message already printed
00276   }
00277 }
00278 
00279 } // namespace
00280 
00281 // Do the work of this BE. This is the starting point for code generation.
00282 void
00283 BE_produce()
00284 {
00285   //search for #includes in the IDL, add them as #includes in the stubs/skels
00286   const char* idl_fn = idl_global->main_filename()->get_string();
00287 
00288   ifstream idl(idl_fn);
00289   const size_t buffer_sz = 512;
00290   char buffer[buffer_sz];
00291 
00292   while (idl) {
00293     idl.getline(buffer, buffer_sz);
00294 
00295     if (0 == strncmp("#include", buffer, 8)) { //FUTURE: account for comments?
00296       string inc(buffer + 8);
00297       size_t delim1 = inc.find_first_of("<\"");
00298       size_t delim2 = inc.find_first_of(">\"", delim1 + 1);
00299       string included(inc, delim1 + 1, delim2 - delim1 - 1);
00300       size_t len = included.size();
00301       string base_name;
00302 
00303       if (len >= 5 &&
00304           0 == ACE_OS::strcasecmp(included.c_str() + len - 4, ".idl")) {
00305         base_name.assign(included.c_str(), len - 4);
00306 
00307       } else if (len >= 6 &&
00308                  0 == ACE_OS::strcasecmp(included.c_str() + len - 5, ".pidl")) {
00309         base_name.assign(included.c_str(), len - 5);
00310 
00311       } else {
00312         ACE_ERROR((LM_ERROR, ACE_TEXT("(%N:%l) BE_produce - included ")
00313                    ACE_TEXT("file must end in .idl or .pidl\n")));
00314         BE_abort();
00315       }
00316 
00317       string stb_inc = base_name + "C.h";
00318       if (stb_inc != "tao/orbC.h") {
00319         be_global->add_include(stb_inc.c_str());
00320         if (stb_inc == "orbC.h" ||
00321             (stb_inc.size() >= 7
00322             && stb_inc.substr(stb_inc.size() - 7) == "/orbC.h") ) {
00323           ACE_DEBUG((LM_WARNING,
00324                      ACE_TEXT("Warning: (%s) Potential inclusion of TAO orbC.H ")
00325                      ACE_TEXT(" Include TAO orb.idl with path of tao/orb.idl")
00326                      ACE_TEXT(" to prevent compilation errors\n"), idl_fn));
00327         }
00328       }
00329 
00330     }
00331   }
00332 
00333   idl.close();
00334 
00335   be_global->open_streams(idl_fn);
00336 
00337   AST_Decl* d = idl_global->root();
00338   AST_Root* root = AST_Root::narrow_from_decl(d);
00339 
00340   if (root == 0) {
00341     ACE_ERROR((LM_ERROR,
00342                ACE_TEXT("(%N:%l) BE_produce - ")
00343                ACE_TEXT("No Root\n")));
00344 
00345     BE_abort();
00346   }
00347 
00348   be_global->set_inc_paths(idl_global->idl_flags());
00349 
00350   const bool java_ts_only = be_global->java_arg().length() > 0;
00351 
00352   dds_visitor visitor(d, java_ts_only);
00353 
00354   if (root->ast_accept(&visitor) == -1) {
00355     ACE_ERROR((LM_ERROR,
00356                ACE_TEXT("(%N:%l) BE_produce -")
00357                ACE_TEXT(" failed to accept adding visitor\n")));
00358     BE_abort();
00359   }
00360 
00361   if (!java_ts_only) {
00362     postprocess(be_global->header_name_.c_str(),
00363                 be_global->header_, BE_GlobalData::STREAM_H);
00364     if (!be_global->suppress_idl()) {
00365       postprocess(be_global->idl_name_.c_str(),
00366                   be_global->idl_, BE_GlobalData::STREAM_IDL);
00367     }
00368   }
00369 
00370   postprocess(be_global->impl_name_.c_str(),
00371               be_global->impl_, BE_GlobalData::STREAM_CPP);
00372 
00373   if (be_global->generate_wireshark()) {
00374     postprocess(be_global->ws_config_name_.c_str(),
00375                 be_global->ws_config_, BE_GlobalData::STREAM_WS);
00376   }
00377 
00378   if (be_global->generate_itl()) {
00379     if (!BE_GlobalData::writeFile(be_global->itl_name_.c_str(), be_global->itl_.str())) {
00380       BE_abort();  //error message already printed
00381     }
00382   }
00383 
00384   if (be_global->face_ts()) {
00385     postprocess(be_global->facets_header_name_.c_str(), be_global->facets_header_,
00386                 BE_GlobalData::STREAM_FACETS_H);
00387     postprocess(be_global->facets_impl_name_.c_str(), be_global->facets_impl_,
00388                 BE_GlobalData::STREAM_FACETS_CPP);
00389   }
00390 
00391   if (be_global->language_mapping() == BE_GlobalData::LANGMAP_FACE_CXX ||
00392       be_global->language_mapping() == BE_GlobalData::LANGMAP_SP_CXX) {
00393     postprocess(be_global->lang_header_name_.c_str(), be_global->lang_header_,
00394                 BE_GlobalData::STREAM_LANG_H);
00395   }
00396 
00397   BE_cleanup();
00398 }

Generated on Fri Feb 12 20:05:19 2016 for OpenDDS by  doxygen 1.4.7