be_global.cpp

Go to the documentation of this file.
00001 /*
00002  *
00003  *
00004  * Distributed under the OpenDDS License.
00005  * See: http://www.opendds.org/license.html
00006  */
00007 
00008 #include "be_global.h"
00009 #include "be_util.h"
00010 #include "ast_generator.h"
00011 #include "global_extern.h"
00012 #include "idl_defines.h"
00013 #include "utl_err.h"
00014 #include "utl_string.h"
00015 
00016 #include "ace/OS_NS_strings.h"
00017 #include "ace/OS_NS_sys_stat.h"
00018 #include "ace/ARGV.h"
00019 
00020 #include <algorithm>
00021 #include <iostream>
00022 #include <fstream>
00023 #include <sstream>
00024 #include <string>
00025 #include <vector>
00026 #include <set>
00027 
00028 using namespace std;
00029 
00030 BE_GlobalData* be_global = 0;
00031 
00032 BE_GlobalData::BE_GlobalData()
00033   : filename_(0)
00034   , java_(false)
00035   , suppress_idl_(false)
00036   , suppress_typecode_(false)
00037   , generate_wireshark_(false)
00038   , generate_itl_(false)
00039   , v8_(false)
00040   , face_ts_(false)
00041   , seq_("Seq")
00042   , language_mapping_(LANGMAP_NONE)
00043 {
00044 }
00045 
00046 BE_GlobalData::~BE_GlobalData()
00047 {
00048 }
00049 
00050 void
00051 BE_GlobalData::destroy()
00052 {
00053 }
00054 
00055 const char*
00056 BE_GlobalData::filename() const
00057 {
00058   return this->filename_;
00059 }
00060 
00061 void
00062 BE_GlobalData::filename(const char* fname)
00063 {
00064   this->filename_ = fname;
00065 }
00066 
00067 ACE_CString BE_GlobalData::export_macro() const
00068 {
00069   return this->export_macro_;
00070 }
00071 
00072 void BE_GlobalData::export_macro(const ACE_CString& str)
00073 {
00074   this->export_macro_ = str;
00075 }
00076 
00077 ACE_CString BE_GlobalData::export_include() const
00078 {
00079   return this->export_include_;
00080 }
00081 
00082 void BE_GlobalData::export_include(const ACE_CString& str)
00083 {
00084   this->export_include_ = str;
00085 }
00086 
00087 ACE_CString BE_GlobalData::versioning_name() const
00088 {
00089   return this->versioning_name_;
00090 }
00091 
00092 void BE_GlobalData::versioning_name(const ACE_CString& str)
00093 {
00094   this->versioning_name_ = str;
00095 }
00096 
00097 ACE_CString BE_GlobalData::versioning_begin() const
00098 {
00099   return this->versioning_begin_;
00100 }
00101 
00102 void BE_GlobalData::versioning_begin(const ACE_CString& str)
00103 {
00104   this->versioning_begin_ = str;
00105 }
00106 
00107 ACE_CString BE_GlobalData::versioning_end() const
00108 {
00109   return this->versioning_end_;
00110 }
00111 
00112 void BE_GlobalData::versioning_end(const ACE_CString& str)
00113 {
00114   this->versioning_end_ = str;
00115 }
00116 
00117 void BE_GlobalData::pch_include(const ACE_CString& str)
00118 {
00119   this->pch_include_ = str;
00120 }
00121 
00122 ACE_CString BE_GlobalData::pch_include() const
00123 {
00124   return this->pch_include_;
00125 }
00126 
00127 void BE_GlobalData::java_arg(const ACE_CString& str)
00128 {
00129   this->java_arg_ = str;
00130 }
00131 
00132 ACE_CString BE_GlobalData::java_arg() const
00133 {
00134   return this->java_arg_;
00135 }
00136 
00137 void BE_GlobalData::language_mapping(LanguageMapping lm)
00138 {
00139   this->language_mapping_ = lm;
00140 }
00141 
00142 BE_GlobalData::LanguageMapping BE_GlobalData::language_mapping() const
00143 {
00144   return this->language_mapping_;
00145 }
00146 
00147 void BE_GlobalData::sequence_suffix(const ACE_CString& str)
00148 {
00149   this->seq_ = str;
00150 }
00151 
00152 ACE_CString BE_GlobalData::sequence_suffix() const
00153 {
00154   return this->seq_;
00155 }
00156 
00157 void BE_GlobalData::java(bool b)
00158 {
00159   this->java_ = b;
00160 }
00161 
00162 bool BE_GlobalData::java() const
00163 {
00164   return this->java_;
00165 }
00166 
00167 void BE_GlobalData::v8(bool b)
00168 {
00169   this->v8_ = b;
00170 }
00171 
00172 bool BE_GlobalData::v8() const
00173 {
00174   return this->v8_;
00175 }
00176 
00177 void BE_GlobalData::face_ts(bool b)
00178 {
00179   this->face_ts_ = b;
00180 }
00181 
00182 bool BE_GlobalData::face_ts() const
00183 {
00184   return this->face_ts_;
00185 }
00186 
00187 // bool
00188 // BE_GlobalData::do_included_files() const
00189 // {
00190 //   return false; //we never process included files
00191 // }
00192 
00193 void
00194 BE_GlobalData::open_streams(const char* filename)
00195 {
00196   this->filename(filename);
00197   size_t len = strlen(filename);
00198 
00199   if ((len < 5 || 0 != ACE_OS::strcasecmp(filename + len - 4, ".idl"))
00200       && (len < 6 || 0 != ACE_OS::strcasecmp(filename + len - 5, ".pidl"))) {
00201     UTL_Error u;
00202     UTL_String str("Input filename must end in \".idl\" or \".pidl\".");
00203     u.back_end(0, &str);
00204     exit(-1);
00205     return;
00206   }
00207 
00208   string filebase(filename);
00209   filebase.erase(filebase.rfind('.'));
00210   size_t idx = filebase.find_last_of("/\\"); // allow either slash
00211 
00212   if (idx != string::npos) {
00213     filebase = filebase.substr(idx + 1);
00214   }
00215 
00216   header_name_ = (filebase + "TypeSupportImpl.h").c_str();
00217   impl_name_ = (filebase + "TypeSupportImpl.cpp").c_str();
00218   idl_name_ = (filebase + "TypeSupport.idl").c_str();
00219   ws_config_name_ = (filebase + "_ws.ini").c_str();
00220   itl_name_ = (filebase + ".itl").c_str();
00221   facets_header_name_ = (filebase + "_TS.hpp").c_str();
00222   facets_impl_name_ = (filebase + "_TS.cpp").c_str();
00223   lang_header_name_ = (filebase + "C.h").c_str();
00224 }
00225 
00226 void
00227 BE_GlobalData::multicast(const char* str)
00228 {
00229   header_ << str;
00230   impl_ << str;
00231   idl_ << str;
00232   if (language_mapping_ != LANGMAP_NONE) lang_header_ << str;
00233 }
00234 
00235 BE_Comment_Guard::BE_Comment_Guard(const char* type, const char* name)
00236   : type_(type), name_(name)
00237 {
00238   if (idl_global->compile_flags() & IDL_CF_INFORMATIVE)
00239     std::cout << type << ": " << name << std::endl;
00240 
00241   be_global->multicast("\n\n/* Begin ");
00242   be_global->multicast(type);
00243   be_global->multicast(": ");
00244   be_global->multicast(name);
00245   be_global->multicast(" */\n\n");
00246 }
00247 
00248 BE_Comment_Guard::~BE_Comment_Guard()
00249 {
00250   be_global->multicast("\n/* End ");
00251   be_global->multicast(type_);
00252   be_global->multicast(": ");
00253   be_global->multicast(name_);
00254   be_global->multicast(" */\n");
00255 }
00256 
00257 ACE_CString
00258 BE_GlobalData::spawn_options()
00259 {
00260   return idl_global->idl_flags();
00261 }
00262 
00263 void
00264 BE_GlobalData::parse_args(long& i, char** av)
00265 {
00266   static const char WB_EXPORT_MACRO[] = "--export=";
00267   static const size_t SZ_WB_EXPORT_MACRO = sizeof(WB_EXPORT_MACRO) - 1;
00268 
00269   switch (av[i][1]) {
00270   case 'o':
00271     idl_global->append_idl_flag(av[i + 1]);
00272     if (ACE_OS::mkdir(av[i + 1]) != 0 && errno != EEXIST) {
00273       ACE_ERROR((LM_ERROR,
00274         ACE_TEXT("IDL: unable to create directory %C")
00275         ACE_TEXT(" specified by -o option\n"), av[i + 1]));
00276     } else {
00277       output_dir_ = av[++i];
00278     }
00279     break;
00280   case 'G':
00281     if (0 == ACE_OS::strcmp(av[i], "-Gws"))
00282       generate_wireshark_ = true;
00283     else if (0 == ACE_OS::strcmp(av[i], "-Gitl"))
00284       generate_itl_ = true;
00285     else if (0 == ACE_OS::strcasecmp(av[i], "-GfaceTS"))
00286       face_ts(true);
00287     else
00288       {
00289         ACE_ERROR((LM_ERROR, ACE_TEXT("IDL: I don't understand the '%C'")
00290                    ACE_TEXT(" option\n"), av[i]));
00291         idl_global->set_compile_flags(idl_global->compile_flags()
00292                                       | IDL_CF_ONLY_USAGE);
00293       }
00294     break;
00295   case 'L':
00296     if (0 == ACE_OS::strcasecmp(av[i], "-Lface"))
00297       language_mapping(LANGMAP_FACE_CXX);
00298     else if (0 == ACE_OS::strcasecmp(av[i], "-Lspcpp"))
00299       language_mapping(LANGMAP_SP_CXX);
00300     else {
00301       ACE_ERROR((LM_ERROR, ACE_TEXT("IDL: I don't understand the '%C'")
00302                   ACE_TEXT(" option\n"), av[i]));
00303       idl_global->set_compile_flags(idl_global->compile_flags()
00304                                     | IDL_CF_ONLY_USAGE);
00305     }
00306     break;
00307   case 'S':
00308     switch (av[i][2]) {
00309     case 'I':
00310       suppress_idl_ = true;
00311       break;
00312     case 't':
00313       suppress_typecode_ = true;
00314       break;
00315     case 'a':
00316       // ignore, accepted for tao_idl compatibility
00317       break;
00318     default:
00319       ACE_ERROR((LM_ERROR, ACE_TEXT("IDL: I don't understand the '%C'")
00320         ACE_TEXT(" option\n"), av[i]));
00321       idl_global->set_compile_flags(idl_global->compile_flags()
00322                                     | IDL_CF_ONLY_USAGE);
00323     }
00324     break;
00325   case 'Z':
00326     switch (av[i][2]) {
00327     case 'C':
00328       add_include (av[++i], STREAM_CPP);
00329       break;
00330     default:
00331       ACE_ERROR((LM_ERROR, ACE_TEXT("IDL: I don't understand the '%C'")
00332                  ACE_TEXT(" option\n"), av[i]));
00333       idl_global->set_compile_flags(idl_global->compile_flags()
00334                                     | IDL_CF_ONLY_USAGE);
00335     }
00336     break;
00337   case '-':
00338     if (0 == ACE_OS::strncasecmp(av[i], WB_EXPORT_MACRO, SZ_WB_EXPORT_MACRO)) {
00339       this->export_macro(av[i] + SZ_WB_EXPORT_MACRO);
00340     }
00341     break;
00342   default:
00343     ACE_ERROR((LM_ERROR, ACE_TEXT("IDL: I don't understand the '%C' option\n"),
00344                av[i]));
00345     idl_global->set_compile_flags(idl_global->compile_flags()
00346                                   | IDL_CF_ONLY_USAGE);
00347   }
00348 }
00349 
00350 
00351 bool
00352 BE_GlobalData::writeFile(const char* fileName, const string& content)
00353 {
00354   string file = (be_global->output_dir_ == "")
00355     ? fileName : (string(be_global->output_dir_.c_str()) + '/' + fileName);
00356   ofstream ofs(file.c_str());
00357 
00358   if (!ofs) {
00359     cerr << "ERROR - couldn't open " << file << " for writing.\n";
00360     return false;
00361   }
00362 
00363   ofs << content;
00364   return !!ofs;
00365 }
00366 
00367 //include file management (assumes a singleton BE_GlobalData object)
00368 
00369 namespace {
00370   typedef set<string> Includes_t;
00371   Includes_t inc_h_, inc_c_, inc_idl_, referenced_idl_, inc_path_, inc_facets_h_,
00372     inc_lang_h_;
00373 }
00374 
00375 void
00376 BE_GlobalData::reset_includes()
00377 {
00378   inc_h_.clear();
00379   inc_c_.clear();
00380   inc_idl_.clear();
00381   inc_facets_h_.clear();
00382   inc_lang_h_.clear();
00383   referenced_idl_.clear();
00384 }
00385 
00386 void
00387 BE_GlobalData::add_inc_path(const char* path)
00388 {
00389   inc_path_.insert(path);
00390 }
00391 
00392 void
00393 BE_GlobalData::set_inc_paths(const char* cmdline)
00394 {
00395   ACE_ARGV argv(ACE_TEXT_CHAR_TO_TCHAR(cmdline), false);
00396   for (int i = 0; i < argv.argc(); ++i) {
00397     std::string arg = ACE_TEXT_ALWAYS_CHAR(argv[i]);
00398     if (arg == "-I" && i + 1 < argv.argc()) {
00399       inc_path_.insert(ACE_TEXT_ALWAYS_CHAR(argv[++i]));
00400     } else if (arg.substr(0, 2) == "-I") {
00401       inc_path_.insert(arg.c_str() + 2);
00402     }
00403   }
00404 }
00405 
00406 void
00407 BE_GlobalData::add_include(const char* file,
00408                            BE_GlobalData::stream_enum_t which)
00409 {
00410   Includes_t* inc = 0;
00411 
00412   switch (which) {
00413   case STREAM_H:
00414     inc = &inc_h_;
00415     break;
00416   case STREAM_CPP:
00417     inc = &inc_c_;
00418     break;
00419   case STREAM_IDL:
00420     inc = &inc_idl_;
00421     break;
00422   case STREAM_FACETS_H:
00423     inc = &inc_facets_h_;
00424     break;
00425   case STREAM_LANG_H:
00426     inc = &inc_lang_h_;
00427     break;
00428   default:
00429     return;
00430   }
00431 
00432   inc->insert(file);
00433 }
00434 
00435 void
00436 BE_GlobalData::add_referenced(const char* file)
00437 {
00438   referenced_idl_.insert(file);
00439 }
00440 
00441 namespace {
00442   std::string transform_referenced(const std::string& idl, const char* suffix)
00443   {
00444     const size_t len = idl.size();
00445     string base_name;
00446     if (len >= 5 && 0 == ACE_OS::strcasecmp(idl.c_str() + len - 4, ".idl")) {
00447       base_name.assign(idl.c_str(), len - 4);
00448 
00449     } else if (len >= 6 &&
00450         0 == ACE_OS::strcasecmp(idl.c_str() + len - 5, ".pidl")) {
00451       base_name.assign(idl.c_str(), len - 5);
00452       size_t slash = base_name.find_last_of("/\\");
00453       if (slash != std::string::npos && slash > 3 && base_name.size() > 3
00454           && base_name.substr(slash - 3, 3) == "tao"
00455           && base_name.substr(base_name.size() - 3) == "Seq") {
00456         base_name = "dds/CorbaSeq/" + base_name.substr(slash + 1);
00457       }
00458     }
00459 
00460     return base_name + suffix;
00461   }
00462 
00463   std::string make_relative(const std::string& absolute)
00464   {
00465     for (Includes_t::const_iterator iter = inc_path_.begin(),
00466         end = inc_path_.upper_bound(absolute); iter != end; ++iter) {
00467       if (absolute.find(*iter) == 0) {
00468         string rel = absolute.substr(iter->size());
00469         if (rel.size() && (rel[0] == '/' || rel[0] == '\\')) {
00470           rel.erase(0, 1);
00471         }
00472         return rel;
00473       }
00474     }
00475     return absolute;
00476   }
00477 
00478   struct InsertIncludes {
00479     std::ostream& ret_;
00480     explicit InsertIncludes(std::ostream& ret) : ret_(ret) {}
00481 
00482     void operator()(const std::string& str) const
00483     {
00484        const char* const quote = (!str.empty() && str[0] != '<') ? "\"" : "";
00485        ret_ << "#include " << quote << str << quote << '\n';
00486     }
00487   };
00488 
00489   struct InsertRefIncludes : InsertIncludes {
00490     const char* const suffix_;
00491 
00492     InsertRefIncludes(std::ostream& ret, const char* suffix)
00493       : InsertIncludes(ret)
00494       , suffix_(suffix)
00495     {}
00496 
00497     void operator()(const std::string& str) const
00498     {
00499       InsertIncludes::operator()(transform_referenced(make_relative(str), suffix_));
00500     }
00501   };
00502 }
00503 
00504 std::string
00505 BE_GlobalData::get_include_block(BE_GlobalData::stream_enum_t which)
00506 {
00507   const Includes_t* inc = 0;
00508 
00509   switch (which) {
00510   case STREAM_H:
00511     inc = &inc_h_;
00512     break;
00513   case STREAM_CPP:
00514     inc = &inc_c_;
00515     break;
00516   case STREAM_IDL:
00517     inc = &inc_idl_;
00518     break;
00519   case STREAM_FACETS_H:
00520     inc = &inc_facets_h_;
00521     break;
00522   case STREAM_LANG_H:
00523     inc = &inc_lang_h_;
00524     break;
00525   default:
00526     return "";
00527   }
00528 
00529   std::ostringstream ret;
00530 
00531   std::for_each(inc->begin(), inc->end(), InsertIncludes(ret));
00532 
00533   switch (which) {
00534   case STREAM_LANG_H:
00535     std::for_each(referenced_idl_.begin(), referenced_idl_.end(),
00536                   InsertRefIncludes(ret, "C.h"));
00537     // fall through
00538   case STREAM_H:
00539     if (!export_include().empty())
00540       ret << "#include \"" << export_include() << "\"\n";
00541     break;
00542 
00543   case STREAM_CPP:
00544     std::for_each(referenced_idl_.begin(), referenced_idl_.end(),
00545                   InsertRefIncludes(ret, "TypeSupportImpl.h"));
00546     break;
00547   default:
00548     break;
00549   }
00550 
00551   return ret.str();
00552 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 10 Aug 2018 for OpenDDS by  doxygen 1.6.1