00001
00002
00003
00004
00005
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
00188
00189
00190
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("/\\");
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
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
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
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 }