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 void BE_GlobalData::pch_include(const ACE_CString& str)
00088 {
00089 this->pch_include_ = str;
00090 }
00091
00092 ACE_CString BE_GlobalData::pch_include() const
00093 {
00094 return this->pch_include_;
00095 }
00096
00097 void BE_GlobalData::java_arg(const ACE_CString& str)
00098 {
00099 this->java_arg_ = str;
00100 }
00101
00102 ACE_CString BE_GlobalData::java_arg() const
00103 {
00104 return this->java_arg_;
00105 }
00106
00107 void BE_GlobalData::language_mapping(LanguageMapping lm)
00108 {
00109 this->language_mapping_ = lm;
00110 }
00111
00112 BE_GlobalData::LanguageMapping BE_GlobalData::language_mapping() const
00113 {
00114 return this->language_mapping_;
00115 }
00116
00117 void BE_GlobalData::sequence_suffix(const ACE_CString& str)
00118 {
00119 this->seq_ = str;
00120 }
00121
00122 ACE_CString BE_GlobalData::sequence_suffix() const
00123 {
00124 return this->seq_;
00125 }
00126
00127 void BE_GlobalData::java(bool b)
00128 {
00129 this->java_ = b;
00130 }
00131
00132 bool BE_GlobalData::java() const
00133 {
00134 return this->java_;
00135 }
00136
00137 void BE_GlobalData::v8(bool b)
00138 {
00139 this->v8_ = b;
00140 }
00141
00142 bool BE_GlobalData::v8() const
00143 {
00144 return this->v8_;
00145 }
00146
00147 void BE_GlobalData::face_ts(bool b)
00148 {
00149 this->face_ts_ = b;
00150 }
00151
00152 bool BE_GlobalData::face_ts() const
00153 {
00154 return this->face_ts_;
00155 }
00156
00157
00158
00159
00160
00161
00162
00163 void
00164 BE_GlobalData::open_streams(const char* filename)
00165 {
00166 this->filename(filename);
00167 size_t len = strlen(filename);
00168
00169 if ((len < 5 || 0 != ACE_OS::strcasecmp(filename + len - 4, ".idl"))
00170 && (len < 6 || 0 != ACE_OS::strcasecmp(filename + len - 5, ".pidl"))) {
00171 UTL_Error u;
00172 UTL_String str("Input filename must end in \".idl\" or \".pidl\".");
00173 u.back_end(0, &str);
00174 exit(-1);
00175 return;
00176 }
00177
00178 string filebase(filename);
00179 filebase.erase(filebase.rfind('.'));
00180 size_t idx = filebase.find_last_of("/\\");
00181
00182 if (idx != string::npos) {
00183 filebase = filebase.substr(idx + 1);
00184 }
00185
00186 header_name_ = (filebase + "TypeSupportImpl.h").c_str();
00187 impl_name_ = (filebase + "TypeSupportImpl.cpp").c_str();
00188 idl_name_ = (filebase + "TypeSupport.idl").c_str();
00189 ws_config_name_ = (filebase + "_ws.ini").c_str();
00190 itl_name_ = (filebase + ".itl").c_str();
00191 facets_header_name_ = (filebase + "_TS.hpp").c_str();
00192 facets_impl_name_ = (filebase + "_TS.cpp").c_str();
00193 lang_header_name_ = (filebase + "C.h").c_str();
00194 }
00195
00196 void
00197 BE_GlobalData::multicast(const char* str)
00198 {
00199 header_ << str;
00200 impl_ << str;
00201 idl_ << str;
00202 if (language_mapping_ != LANGMAP_NONE) lang_header_ << str;
00203 }
00204
00205 BE_Comment_Guard::BE_Comment_Guard(const char* type, const char* name)
00206 : type_(type), name_(name)
00207 {
00208 if (idl_global->compile_flags() & IDL_CF_INFORMATIVE)
00209 std::cout << type << ": " << name << std::endl;
00210
00211 be_global->multicast("\n\n/* Begin ");
00212 be_global->multicast(type);
00213 be_global->multicast(": ");
00214 be_global->multicast(name);
00215 be_global->multicast(" */\n\n");
00216 }
00217
00218 BE_Comment_Guard::~BE_Comment_Guard()
00219 {
00220 be_global->multicast("\n/* End ");
00221 be_global->multicast(type_);
00222 be_global->multicast(": ");
00223 be_global->multicast(name_);
00224 be_global->multicast(" */\n");
00225 }
00226
00227 ACE_CString
00228 BE_GlobalData::spawn_options()
00229 {
00230 return idl_global->idl_flags();
00231 }
00232
00233 void
00234 BE_GlobalData::parse_args(long& i, char** av)
00235 {
00236 static const char WB_EXPORT_MACRO[] = "--export=";
00237 static const size_t SZ_WB_EXPORT_MACRO = sizeof(WB_EXPORT_MACRO) - 1;
00238
00239 switch (av[i][1]) {
00240 case 'o':
00241 idl_global->append_idl_flag(av[i + 1]);
00242 if (ACE_OS::mkdir(av[i + 1]) != 0 && errno != EEXIST) {
00243 ACE_ERROR((LM_ERROR,
00244 ACE_TEXT("IDL: unable to create directory %C")
00245 ACE_TEXT(" specified by -o option\n"), av[i + 1]));
00246 } else {
00247 output_dir_ = av[++i];
00248 }
00249 break;
00250 case 'G':
00251 if (0 == ACE_OS::strcmp(av[i], "-Gws"))
00252 generate_wireshark_ = true;
00253 else if (0 == ACE_OS::strcmp(av[i], "-Gitl"))
00254 generate_itl_ = true;
00255 else if (0 == ACE_OS::strcasecmp(av[i], "-GfaceTS"))
00256 face_ts(true);
00257 else
00258 {
00259 ACE_ERROR((LM_ERROR, ACE_TEXT("IDL: I don't understand the '%C'")
00260 ACE_TEXT(" option\n"), av[i]));
00261 idl_global->set_compile_flags(idl_global->compile_flags()
00262 | IDL_CF_ONLY_USAGE);
00263 }
00264 break;
00265 case 'L':
00266 if (0 == ACE_OS::strcasecmp(av[i], "-Lface"))
00267 language_mapping(LANGMAP_FACE_CXX);
00268 else if (0 == ACE_OS::strcasecmp(av[i], "-Lspcpp"))
00269 language_mapping(LANGMAP_SP_CXX);
00270 else {
00271 ACE_ERROR((LM_ERROR, ACE_TEXT("IDL: I don't understand the '%C'")
00272 ACE_TEXT(" option\n"), av[i]));
00273 idl_global->set_compile_flags(idl_global->compile_flags()
00274 | IDL_CF_ONLY_USAGE);
00275 }
00276 break;
00277 case 'S':
00278 switch (av[i][2]) {
00279 case 'I':
00280 suppress_idl_ = true;
00281 break;
00282 case 't':
00283 suppress_typecode_ = true;
00284 break;
00285 case 'a':
00286
00287 break;
00288 default:
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 'Z':
00296 switch (av[i][2]) {
00297 case 'C':
00298 add_include (av[++i], STREAM_CPP);
00299 break;
00300 default:
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 '-':
00308 if (0 == ACE_OS::strncasecmp(av[i], WB_EXPORT_MACRO, SZ_WB_EXPORT_MACRO)) {
00309 this->export_macro(av[i] + SZ_WB_EXPORT_MACRO);
00310 }
00311 break;
00312 default:
00313 ACE_ERROR((LM_ERROR, ACE_TEXT("IDL: I don't understand the '%C' option\n"),
00314 av[i]));
00315 idl_global->set_compile_flags(idl_global->compile_flags()
00316 | IDL_CF_ONLY_USAGE);
00317 }
00318 }
00319
00320
00321 bool
00322 BE_GlobalData::writeFile(const char* fileName, const string& content)
00323 {
00324 string file = (be_global->output_dir_ == "")
00325 ? fileName : (string(be_global->output_dir_.c_str()) + '/' + fileName);
00326 ofstream ofs(file.c_str());
00327
00328 if (!ofs) {
00329 cerr << "ERROR - couldn't open " << file << " for writing.\n";
00330 return false;
00331 }
00332
00333 ofs << content;
00334 return !!ofs;
00335 }
00336
00337
00338
00339 namespace {
00340 typedef set<string> Includes_t;
00341 Includes_t inc_h_, inc_c_, inc_idl_, referenced_idl_, inc_path_, inc_facets_h_,
00342 inc_lang_h_;
00343 }
00344
00345 void
00346 BE_GlobalData::reset_includes()
00347 {
00348 inc_h_.clear();
00349 inc_c_.clear();
00350 inc_idl_.clear();
00351 inc_facets_h_.clear();
00352 inc_lang_h_.clear();
00353 referenced_idl_.clear();
00354 }
00355
00356 void
00357 BE_GlobalData::add_inc_path(const char* path)
00358 {
00359 inc_path_.insert(path);
00360 }
00361
00362 void
00363 BE_GlobalData::set_inc_paths(const char* cmdline)
00364 {
00365 ACE_ARGV argv(ACE_TEXT_CHAR_TO_TCHAR(cmdline), false);
00366 for (int i = 0; i < argv.argc(); ++i) {
00367 std::string arg = ACE_TEXT_ALWAYS_CHAR(argv[i]);
00368 if (arg == "-I" && i + 1 < argv.argc()) {
00369 inc_path_.insert(ACE_TEXT_ALWAYS_CHAR(argv[++i]));
00370 } else if (arg.substr(0, 2) == "-I") {
00371 inc_path_.insert(arg.c_str() + 2);
00372 }
00373 }
00374 }
00375
00376 void
00377 BE_GlobalData::add_include(const char* file,
00378 BE_GlobalData::stream_enum_t which)
00379 {
00380 Includes_t* inc = 0;
00381
00382 switch (which) {
00383 case STREAM_H:
00384 inc = &inc_h_;
00385 break;
00386 case STREAM_CPP:
00387 inc = &inc_c_;
00388 break;
00389 case STREAM_IDL:
00390 inc = &inc_idl_;
00391 break;
00392 case STREAM_FACETS_H:
00393 inc = &inc_facets_h_;
00394 break;
00395 case STREAM_LANG_H:
00396 inc = &inc_lang_h_;
00397 break;
00398 default:
00399 return;
00400 }
00401
00402 inc->insert(file);
00403 }
00404
00405 void
00406 BE_GlobalData::add_referenced(const char* file)
00407 {
00408 referenced_idl_.insert(file);
00409 }
00410
00411 namespace {
00412 std::string transform_referenced(const std::string& idl, const char* suffix)
00413 {
00414 const size_t len = idl.size();
00415 string base_name;
00416 if (len >= 5 && 0 == ACE_OS::strcasecmp(idl.c_str() + len - 4, ".idl")) {
00417 base_name.assign(idl.c_str(), len - 4);
00418
00419 } else if (len >= 6 &&
00420 0 == ACE_OS::strcasecmp(idl.c_str() + len - 5, ".pidl")) {
00421 base_name.assign(idl.c_str(), len - 5);
00422 size_t slash = base_name.find_last_of("/\\");
00423 if (slash != std::string::npos && slash > 3 && base_name.size() > 3
00424 && base_name.substr(slash - 3, 3) == "tao"
00425 && base_name.substr(base_name.size() - 3) == "Seq") {
00426 base_name = "dds/CorbaSeq/" + base_name.substr(slash + 1);
00427 }
00428 }
00429
00430 return base_name + suffix;
00431 }
00432
00433 std::string make_relative(const std::string& absolute)
00434 {
00435 for (Includes_t::const_iterator iter = inc_path_.begin(),
00436 end = inc_path_.upper_bound(absolute); iter != end; ++iter) {
00437 if (absolute.find(*iter) == 0) {
00438 string rel = absolute.substr(iter->size());
00439 if (rel.size() && (rel[0] == '/' || rel[0] == '\\')) {
00440 rel.erase(0, 1);
00441 }
00442 return rel;
00443 }
00444 }
00445 return absolute;
00446 }
00447
00448 struct InsertIncludes {
00449 std::ostream& ret_;
00450 explicit InsertIncludes(std::ostream& ret) : ret_(ret) {}
00451
00452 void operator()(const std::string& str) const
00453 {
00454 const char* const quote = (!str.empty() && str[0] != '<') ? "\"" : "";
00455 ret_ << "#include " << quote << str << quote << '\n';
00456 }
00457 };
00458
00459 struct InsertRefIncludes : InsertIncludes {
00460 const char* const suffix_;
00461
00462 InsertRefIncludes(std::ostream& ret, const char* suffix)
00463 : InsertIncludes(ret)
00464 , suffix_(suffix)
00465 {}
00466
00467 void operator()(const std::string& str) const
00468 {
00469 InsertIncludes::operator()(transform_referenced(make_relative(str), suffix_));
00470 }
00471 };
00472 }
00473
00474 std::string
00475 BE_GlobalData::get_include_block(BE_GlobalData::stream_enum_t which)
00476 {
00477 const Includes_t* inc = 0;
00478
00479 switch (which) {
00480 case STREAM_H:
00481 inc = &inc_h_;
00482 break;
00483 case STREAM_CPP:
00484 inc = &inc_c_;
00485 break;
00486 case STREAM_IDL:
00487 inc = &inc_idl_;
00488 break;
00489 case STREAM_FACETS_H:
00490 inc = &inc_facets_h_;
00491 break;
00492 case STREAM_LANG_H:
00493 inc = &inc_lang_h_;
00494 break;
00495 default:
00496 return "";
00497 }
00498
00499 std::ostringstream ret;
00500
00501 std::for_each(inc->begin(), inc->end(), InsertIncludes(ret));
00502
00503 switch (which) {
00504 case STREAM_LANG_H:
00505 std::for_each(referenced_idl_.begin(), referenced_idl_.end(),
00506 InsertRefIncludes(ret, "C.h"));
00507
00508 case STREAM_H:
00509 if (!export_include().empty())
00510 ret << "#include \"" << export_include() << "\"\n";
00511 break;
00512
00513 case STREAM_CPP:
00514 std::for_each(referenced_idl_.begin(), referenced_idl_.end(),
00515 InsertRefIncludes(ret, "TypeSupportImpl.h"));
00516 break;
00517 default:
00518 break;
00519 }
00520
00521 return ret.str();
00522 }