00001
00002
00003
00004
00005
00006
00007
00008 #include "ts_generator.h"
00009 #include "be_extern.h"
00010
00011 #include "utl_identifier.h"
00012
00013 #include "ace/OS_NS_sys_stat.h"
00014
00015 #include <cstring>
00016 #include <fstream>
00017 #include <sstream>
00018 #include <map>
00019 #include <iostream>
00020
00021 namespace {
00022 std::string read_template(const char* prefix)
00023 {
00024 const char* dds_root = ACE_OS::getenv("DDS_ROOT");
00025 if (!dds_root) {
00026 ACE_ERROR((LM_ERROR, "The environment variable DDS_ROOT must be set.\n"));
00027 BE_abort();
00028 }
00029 std::string path = dds_root;
00030 path.append("/dds/idl/");
00031 path.append(prefix);
00032 path.append("Template.txt");
00033 std::ifstream ifs(path.c_str());
00034 std::ostringstream oss;
00035 oss << ifs.rdbuf();
00036 return oss.str();
00037 }
00038
00039 void replaceAll(std::string& s,
00040 const std::map<std::string, std::string>& rep) {
00041 typedef std::map<std::string, std::string>::const_iterator mapiter_t;
00042 for (size_t i = s.find("<%"); i < s.length(); i = s.find("<%", i + 1)) {
00043 size_t n = s.find("%>", i) - i + 2;
00044 mapiter_t iter = rep.find(s.substr(i + 2, n - 4));
00045 if (iter != rep.end()) {
00046 s.replace(i, n, iter->second);
00047 }
00048 }
00049 }
00050
00051 template<size_t N>
00052 void add_includes(const char* (&includes)[N],
00053 BE_GlobalData::stream_enum_t whichStream) {
00054 for (size_t i = 0; i < N; ++i) {
00055 be_global->add_include(includes[i], whichStream);
00056 }
00057 }
00058
00059 }
00060
00061 ts_generator::ts_generator()
00062 : idl_template_(read_template("IDL"))
00063 {
00064 }
00065
00066 bool ts_generator::gen_struct(AST_Structure*, UTL_ScopedName* name,
00067 const std::vector<AST_Field*>&, AST_Type::SIZE_TYPE, const char*)
00068 {
00069 IDL_GlobalData::DCPS_Data_Type_Info* info = idl_global->is_dcps_type(name);
00070
00071 if (!info) {
00072
00073 return true;
00074 }
00075
00076 const std::string cxxName = scoped(name);
00077 const std::string short_name = name->last_component()->get_string();
00078
00079 static const char* idl_includes[] = {
00080 "dds/DdsDcpsInfrastructure.idl", "dds/DdsDcpsTopic.idl",
00081 "dds/DdsDcpsPublication.idl", "dds/DdsDcpsSubscriptionExt.idl",
00082 "dds/DdsDcpsTypeSupportExt.idl"
00083 };
00084 add_includes(idl_includes, BE_GlobalData::STREAM_IDL);
00085
00086 std::string dc = be_global->header_name_.c_str();
00087 dc.replace(dc.end() - 6, dc.end() - 2, "C");
00088 be_global->add_include(dc.c_str());
00089
00090 static const char* h_includes[] = {
00091 "dds/DCPS/TypeSupportImpl.h"
00092 };
00093 add_includes(h_includes, BE_GlobalData::STREAM_H);
00094
00095 static const char* cpp_includes[] = {
00096 "dds/DCPS/debug.h", "dds/DCPS/Registered_Data_Types.h",
00097 "dds/DdsDcpsDomainC.h", "dds/DCPS/Service_Participant.h",
00098 "dds/DCPS/Qos_Helper.h", "dds/DCPS/PublicationInstance.h",
00099 "dds/DCPS/PublisherImpl.h", "dds/DCPS/SubscriberImpl.h",
00100 "dds/DCPS/ReceivedDataElementList.h", "dds/DCPS/RakeResults_T.h",
00101 "dds/DCPS/BuiltInTopicUtils.h", "dds/DCPS/Util.h",
00102 "dds/DCPS/ContentFilteredTopicImpl.h", "dds/DCPS/RakeData.h",
00103 "dds/DCPS/MultiTopicDataReader_T.h", "dds/DCPS/DataWriterImpl_T.h",
00104 "dds/DCPS/DataReaderImpl_T.h"
00105 };
00106 add_includes(cpp_includes, BE_GlobalData::STREAM_CPP);
00107
00108 std::map<std::string, std::string> replacements;
00109 replacements["SCOPED"] = cxxName;
00110 replacements["TYPE"] = short_name;
00111 replacements["EXPORT"] = be_global->export_macro().c_str();
00112 replacements["SEQ"] = be_global->sequence_suffix().c_str();
00113
00114 ScopedNamespaceGuard idlGuard(name, be_global->idl_, "module");
00115 std::string idl = idl_template_;
00116 replaceAll(idl, replacements);
00117 be_global->idl_ << idl;
00118
00119 be_global->header_ << be_global->versioning_begin() << "\n";
00120 {
00121 ScopedNamespaceGuard hGuard(name, be_global->header_);
00122
00123 be_global->header_ <<
00124 "class " << short_name << "TypeSupportImpl;\n";
00125 }
00126 be_global->header_ << be_global->versioning_end() << "\n";
00127
00128 const bool has_keys = info->key_list_.is_empty();
00129
00130 be_global->header_ <<
00131 "OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL\n"
00132 "namespace OpenDDS { namespace DCPS {\n"
00133 "template <>\n"
00134 "struct DDSTraits<" << cxxName << "> {\n"
00135 " typedef " << cxxName << " MessageType;\n"
00136 " typedef " << cxxName << "Seq MessageSequenceType;\n"
00137 " typedef " << cxxName << "TypeSupport TypeSupportType;\n"
00138 " typedef " << cxxName << "TypeSupportImpl TypeSupportTypeImpl;\n"
00139 " typedef " << cxxName << "DataWriter DataWriterType;\n"
00140 " typedef " << cxxName << "DataReader DataReaderType;\n"
00141 " typedef " << cxxName << "_OpenDDS_KeyLessThan LessThanType;\n"
00142 "\n"
00143 " static const char* type_name () { return \"" << cxxName << "\"; }\n"
00144 " static bool gen_has_key () { return " << (has_keys ? "false" : "true") << "; }\n"
00145 "\n"
00146 " static size_t gen_max_marshaled_size(const MessageType& x, bool align) { return ::OpenDDS::DCPS::gen_max_marshaled_size(x, align); }\n"
00147 " static void gen_find_size(const MessageType& arr, size_t& size, size_t& padding) { ::OpenDDS::DCPS::gen_find_size(arr, size, padding); }\n"
00148 "\n"
00149 " static size_t gen_max_marshaled_size(const OpenDDS::DCPS::KeyOnly<const MessageType>& x, bool align) { return ::OpenDDS::DCPS::gen_max_marshaled_size(x, align); }\n"
00150 " static void gen_find_size(const OpenDDS::DCPS::KeyOnly<const MessageType>& arr, size_t& size, size_t& padding) { ::OpenDDS::DCPS::gen_find_size(arr, size, padding); }\n"
00151 "};\n} }\nOPENDDS_END_VERSIONED_NAMESPACE_DECL\n\n";
00152
00153 be_global->header_ << be_global->versioning_begin() << "\n";
00154 {
00155 ScopedNamespaceGuard hGuard(name, be_global->header_);
00156
00157 be_global->header_ <<
00158 "class " << be_global->export_macro() << " " << short_name << "TypeSupportImpl\n"
00159 " : public virtual OpenDDS::DCPS::LocalObject<" << short_name << "TypeSupport>\n"
00160 " , public virtual OpenDDS::DCPS::TypeSupportImpl\n"
00161 "{\n"
00162 "public:\n"
00163 " typedef OpenDDS::DCPS::DDSTraits<" << short_name << "> TraitsType;\n"
00164 " typedef " << short_name << "TypeSupport TypeSupportType;\n"
00165 " typedef " << short_name << "TypeSupport::_var_type _var_type;\n"
00166 " typedef " << short_name << "TypeSupport::_ptr_type _ptr_type;\n"
00167 "\n"
00168 " " << short_name << "TypeSupportImpl() {}\n"
00169 " virtual ~" << short_name << "TypeSupportImpl() {}\n"
00170 "\n"
00171 " virtual " << be_global->versioning_name() << "::DDS::DataWriter_ptr create_datawriter();\n"
00172 " virtual " << be_global->versioning_name() << "::DDS::DataReader_ptr create_datareader();\n"
00173 "#ifndef OPENDDS_NO_MULTI_TOPIC\n"
00174 " virtual " << be_global->versioning_name() << "::DDS::DataReader_ptr create_multitopic_datareader();\n"
00175 "#endif /* !OPENDDS_NO_MULTI_TOPIC */\n"
00176 "#ifndef OPENDDS_NO_CONTENT_SUBSCRIPTION_PROFILE\n"
00177 " virtual const OpenDDS::DCPS::MetaStruct& getMetaStructForType();\n"
00178 "#endif /* !OPENDDS_NO_CONTENT_SUBSCRIPTION_PROFILE */\n"
00179 " virtual bool has_dcps_key();\n"
00180 " const char* default_type_name() const;\n"
00181 " static " << short_name << "TypeSupport::_ptr_type _narrow(CORBA::Object_ptr obj);\n"
00182 "};\n";
00183 }
00184 be_global->header_ << be_global->versioning_end() << "\n";
00185
00186 be_global->impl_ << be_global->versioning_begin() << "\n";
00187 {
00188 ScopedNamespaceGuard cppGuard(name, be_global->impl_);
00189 be_global->impl_ <<
00190 "::DDS::DataWriter_ptr " << short_name << "TypeSupportImpl::create_datawriter()\n"
00191 "{\n"
00192 " typedef OpenDDS::DCPS::DataWriterImpl_T<" << short_name << "> DataWriterImplType;\n"
00193 " ::DDS::DataWriter_ptr writer_impl = ::DDS::DataWriter::_nil();\n"
00194 " ACE_NEW_NORETURN(writer_impl,\n"
00195 " DataWriterImplType());\n"
00196 " return writer_impl;\n"
00197 "}\n\n"
00198 "::DDS::DataReader_ptr " << short_name << "TypeSupportImpl::create_datareader()\n"
00199 "{\n"
00200 " typedef OpenDDS::DCPS::DataReaderImpl_T<" << short_name << "> DataReaderImplType;\n"
00201 " ::DDS::DataReader_ptr reader_impl = ::DDS::DataReader::_nil();\n"
00202 " ACE_NEW_NORETURN(reader_impl,\n"
00203 " DataReaderImplType());\n"
00204 " return reader_impl;\n"
00205 "}\n\n"
00206 "#ifndef OPENDDS_NO_MULTI_TOPIC\n"
00207 "::DDS::DataReader_ptr " << short_name << "TypeSupportImpl::create_multitopic_datareader()\n"
00208 "{\n"
00209 " typedef OpenDDS::DCPS::DataReaderImpl_T<" << short_name << "> DataReaderImplType;\n"
00210 " typedef OpenDDS::DCPS::MultiTopicDataReader_T<" << short_name << ", DataReaderImplType> MultiTopicDataReaderImplType;\n"
00211 " ::DDS::DataReader_ptr multitopic_reader_impl = ::DDS::DataReader::_nil();\n"
00212 " ACE_NEW_NORETURN(multitopic_reader_impl,\n"
00213 " MultiTopicDataReaderImplType());\n"
00214 " return multitopic_reader_impl;\n"
00215 "}\n"
00216 "#endif /* !OPENDDS_NO_MULTI_TOPIC */\n\n"
00217 "#ifndef OPENDDS_NO_CONTENT_SUBSCRIPTION_PROFILE\n"
00218 "const OpenDDS::DCPS::MetaStruct& " << short_name << "TypeSupportImpl::getMetaStructForType()\n"
00219 "{\n"
00220 " return OpenDDS::DCPS::getMetaStruct<" << short_name << ">();\n"
00221 "}\n"
00222 "#endif /* !OPENDDS_NO_CONTENT_SUBSCRIPTION_PROFILE */\n\n"
00223 "bool " << short_name << "TypeSupportImpl::has_dcps_key()\n"
00224 "{\n"
00225 " return TraitsType::gen_has_key ();\n"
00226 "}\n\n"
00227 "const char* " << short_name << "TypeSupportImpl::default_type_name() const\n"
00228 "{\n"
00229 " return TraitsType::type_name();\n"
00230 "}\n\n"
00231 << short_name << "TypeSupport::_ptr_type " << short_name << "TypeSupportImpl::_narrow(CORBA::Object_ptr obj)\n"
00232 "{\n"
00233 " return TypeSupportType::_narrow(obj);\n"
00234 "}\n";
00235 }
00236 be_global->impl_ << be_global->versioning_end() << "\n";
00237
00238 if (be_global->face_ts()) {
00239 face_ts_generator::generate(name);
00240 }
00241
00242 return true;
00243 }
00244
00245 bool ts_generator::gen_union(AST_Union*, UTL_ScopedName* name,
00246 const std::vector<AST_UnionBranch*>&, AST_Type*, const char*)
00247 {
00248 if (idl_global->is_dcps_type(name)) {
00249 std::cerr << "ERROR: union " << scoped(name) << " can not be used as a "
00250 "DCPS_DATA_TYPE (only structs can be Topic types)" << std::endl;
00251 return false;
00252 }
00253 return true;
00254 }
00255
00256 namespace java_ts_generator {
00257
00258
00259 void generate(UTL_ScopedName* name) {
00260 if (idl_global->is_dcps_type(name) == 0) {
00261
00262 return;
00263 }
00264
00265 ACE_CString output_file = be_global->java_arg();
00266 if (output_file.length()) {
00267 be_global->impl_name_ = output_file;
00268 }
00269 be_global->add_include("idl2jni_jni.h", BE_GlobalData::STREAM_CPP);
00270
00271 std::string type = scoped(name);
00272
00273 std::string file, jniclass, jpackage;
00274 for (UTL_ScopedName* sn = name; sn;
00275 sn = static_cast<UTL_ScopedName*>(sn->tail())) {
00276 std::string tmp = sn->head()->get_string();
00277 if (tmp != "" && sn->tail()) {
00278 jpackage += tmp;
00279 file += tmp;
00280 if (ACE_OS::mkdir(file.c_str()) != 0 && errno != EEXIST) {
00281 ACE_ERROR((LM_ERROR, ACE_TEXT("ERROR: java_ts_generator::generate - ")
00282 ACE_TEXT("unable to create specified directory: %C"), file.c_str()));
00283 }
00284 }
00285 for (size_t i = tmp.find('_'); i < tmp.length();
00286 i = tmp.find('_', i + 1)) {
00287 tmp.insert(++i, 1, '1');
00288 }
00289 jniclass += tmp;
00290 if (jniclass != "" && sn->tail()) {
00291 jniclass += '_';
00292 jpackage += '.';
00293 file += '/';
00294 }
00295 }
00296
00297 if (jpackage.size() && jpackage[jpackage.size() - 1] == '.') {
00298 jpackage.resize(jpackage.size() - 1);
00299 }
00300
00301 std::string clazz = name->last_component()->get_string();
00302 file += clazz + "TypeSupportImpl.java";
00303
00304 std::ofstream java(file.c_str());
00305 java << (jpackage.size() ? "package " : "") << jpackage
00306 << (jpackage.size() ? ";\n" :"") <<
00307 "public class " << clazz << "TypeSupportImpl extends _" << clazz
00308 << "TypeSupportTAOPeer {\n"
00309 " public " << clazz << "TypeSupportImpl() {\n"
00310 " super(_jni_init());\n"
00311 " }\n"
00312 " private static native long _jni_init();\n"
00313 "}\n";
00314 be_global->impl_ <<
00315 "extern \"C\" JNIEXPORT jlong JNICALL\n"
00316 "Java_" << jniclass << "TypeSupportImpl__1jni_1init(JNIEnv*, jclass) {\n"
00317 " return reinterpret_cast<jlong>(static_cast<CORBA::Object_ptr>(new "
00318 << type << "TypeSupportImpl));\n"
00319 "}\n\n";
00320 }
00321
00322 }
00323
00324 namespace face_ts_generator {
00325
00326 void generate(UTL_ScopedName* name) {
00327 const std::string name_cxx = scoped(name),
00328 name_underscores = dds_generator::scoped_helper(name, "_"),
00329 exportMacro = be_global->export_macro().c_str(),
00330 exporter = exportMacro.empty() ? "" : (" " + exportMacro + '\n');
00331 be_global->add_include("FACE/TS.hpp", BE_GlobalData::STREAM_FACETS_H);
00332 be_global->facets_header_ <<
00333 "namespace FACE\n"
00334 "{\n"
00335 " namespace Read_Callback\n"
00336 " {\n"
00337 " typedef void (*send_event_" << name_underscores << "_Ptr) (\n"
00338 " /* in */ TRANSACTION_ID_TYPE transaction_id,\n"
00339 " /* inout */ " << name_cxx << "& message,\n"
00340 " /* in */ MESSAGE_TYPE_GUID message_type_id,\n"
00341 " /* in */ MESSAGE_SIZE_TYPE message_size,\n"
00342 " /* in */ const WAITSET_TYPE waitset,\n"
00343 " /* out */ RETURN_CODE_TYPE& return_code);\n"
00344 " }\n\n"
00345 " namespace TS\n"
00346 " {\n" << exporter <<
00347 " void Receive_Message(\n"
00348 " /* in */ CONNECTION_ID_TYPE connection_id,\n"
00349 " /* in */ TIMEOUT_TYPE timeout,\n"
00350 " /* inout */ TRANSACTION_ID_TYPE& transaction_id,\n"
00351 " /* out */ " << name_cxx << "& message,\n"
00352 " /* in */ MESSAGE_SIZE_TYPE message_size,\n"
00353 " /* out */ RETURN_CODE_TYPE& return_code);\n\n" << exporter <<
00354 " void Send_Message(\n"
00355 " /* in */ CONNECTION_ID_TYPE connection_id,\n"
00356 " /* in */ TIMEOUT_TYPE timeout,\n"
00357 " /* inout */ TRANSACTION_ID_TYPE& transaction_id,\n"
00358 " /* inout */ " << name_cxx << "& message,\n"
00359 " /* inout */ MESSAGE_SIZE_TYPE& message_size,\n"
00360 " /* out */ RETURN_CODE_TYPE& return_code);\n\n" << exporter <<
00361 " void Register_Callback(\n"
00362 " /* in */ CONNECTION_ID_TYPE connection_id,\n"
00363 " /* in */ const WAITSET_TYPE waitset,\n"
00364 " /* in */ Read_Callback::send_event_" << name_underscores
00365 << "_Ptr data_callback,\n"
00366 " /* in */ MESSAGE_SIZE_TYPE max_message_size,\n"
00367 " /* out */ RETURN_CODE_TYPE& return_code);\n\n"
00368 " }\n"
00369 "}\n\n";
00370 be_global->facets_impl_ <<
00371 "void Receive_Message(CONNECTION_ID_TYPE connection_id,\n"
00372 " TIMEOUT_TYPE timeout,\n"
00373 " TRANSACTION_ID_TYPE& transaction_id,\n"
00374 " " << name_cxx << "& message,\n"
00375 " MESSAGE_SIZE_TYPE message_size,\n"
00376 " RETURN_CODE_TYPE& return_code) {\n"
00377 " OpenDDS::FaceTSS::receive_message(connection_id, timeout,\n"
00378 " transaction_id, message,\n"
00379 " message_size, return_code);\n"
00380 "}\n\n"
00381 "void Send_Message(CONNECTION_ID_TYPE connection_id,\n"
00382 " TIMEOUT_TYPE timeout,\n"
00383 " TRANSACTION_ID_TYPE& transaction_id,\n"
00384 " " << name_cxx << "& message,\n"
00385 " MESSAGE_SIZE_TYPE& message_size,\n"
00386 " RETURN_CODE_TYPE& return_code) {\n"
00387 " OpenDDS::FaceTSS::send_message(connection_id, timeout,\n"
00388 " transaction_id, message,\n"
00389 " message_size, return_code);\n"
00390 "}\n\n"
00391 "void Register_Callback(CONNECTION_ID_TYPE connection_id,\n"
00392 " const WAITSET_TYPE waitset,\n"
00393 " Read_Callback::send_event_" << name_underscores
00394 << "_Ptr data_callback,\n"
00395 " MESSAGE_SIZE_TYPE max_message_size,\n"
00396 " RETURN_CODE_TYPE& return_code) {\n"
00397 " OpenDDS::FaceTSS::register_callback(connection_id, waitset,\n"
00398 " data_callback,\n"
00399 " max_message_size, return_code);\n"
00400 "}\n\n"
00401 "struct " << name_underscores << "_Initializer {\n"
00402 " " << name_underscores << "_Initializer()\n"
00403 " {\n"
00404 " " << name_cxx << "TypeSupport_var ts = new " << name_cxx
00405 << "TypeSupportImpl;\n"
00406 " ts->register_type(0, \"\");\n"
00407 " }\n"
00408 "} init_" << name_underscores << ";\n\n";
00409 }
00410 }