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_DEBUG((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 if (idl_global->is_dcps_type(name) == 0) {
00070
00071 return true;
00072 }
00073
00074 const std::string cxxName = scoped(name);
00075 const std::string short_name = name->last_component()->get_string();
00076
00077 static const char* idl_includes[] = {
00078 "dds/DdsDcpsInfrastructure.idl", "dds/DdsDcpsTopic.idl",
00079 "dds/DdsDcpsPublication.idl", "dds/DdsDcpsSubscriptionExt.idl",
00080 "dds/DdsDcpsTypeSupportExt.idl"
00081 };
00082 add_includes(idl_includes, BE_GlobalData::STREAM_IDL);
00083
00084 std::string dc = be_global->header_name_.c_str();
00085 dc.replace(dc.end() - 6, dc.end() - 2, "C");
00086 be_global->add_include(dc.c_str());
00087
00088 static const char* h_includes[] = {
00089 "dds/DCPS/DataWriterImpl_T.h",
00090 "dds/DCPS/DataReaderImpl_T.h",
00091 "dds/DCPS/TypeSupportImpl_T.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"
00104 };
00105 add_includes(cpp_includes, BE_GlobalData::STREAM_CPP);
00106
00107 std::map<std::string, std::string> replacements;
00108 replacements["SCOPED"] = cxxName;
00109 replacements["TYPE"] = short_name;
00110 replacements["EXPORT"] = be_global->export_macro().c_str();
00111 replacements["SEQ"] = be_global->sequence_suffix().c_str();
00112
00113 ScopedNamespaceGuard idlGuard(name, be_global->idl_, "module");
00114 std::string idl = idl_template_;
00115 replaceAll(idl, replacements);
00116 be_global->idl_ << idl;
00117
00118 be_global->header_ <<
00119 "namespace OpenDDS { namespace DCPS {\n"
00120 "template <>\n"
00121 "struct DDSTraits<" << cxxName << "> {\n"
00122 " typedef " << cxxName << " MessageType;\n"
00123 " typedef " << cxxName << "Seq MessageSequenceType;\n"
00124 " typedef " << cxxName << "TypeSupport TypeSupportType;\n"
00125 " typedef " << cxxName << "DataWriter DataWriterType;\n"
00126 " typedef " << cxxName << "DataReader DataReaderType;\n"
00127 " typedef " << module_scope(name) << "OpenDDSGenerated::" << short_name << "_KeyLessThan LessThanType;\n"
00128 "\n"
00129 " inline static const char* type_name () { return \"" << cxxName << "\"; }\n"
00130 " inline static bool gen_has_key (const MessageType& x) { return ::OpenDDS::DCPS::gen_has_key(x); }\n"
00131 "\n"
00132 " inline static bool gen_is_bounded_size (const MessageType& x) { return ::OpenDDS::DCPS::gen_is_bounded_size(x); }\n"
00133 " inline static size_t gen_max_marshaled_size(const MessageType& x, bool align) { return ::OpenDDS::DCPS::gen_max_marshaled_size(x, align); }\n"
00134 " inline static void gen_find_size(const MessageType& arr, size_t& size, size_t& padding) { ::OpenDDS::DCPS::gen_find_size(arr, size, padding); }\n"
00135 "\n"
00136 " inline static bool gen_is_bounded_size (const OpenDDS::DCPS::KeyOnly<const MessageType>& x) { return ::OpenDDS::DCPS::gen_is_bounded_size(x); }\n"
00137 " inline 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"
00138 " inline 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"
00139 "};\n} }\n\n";
00140
00141 {
00142 ScopedNamespaceGuard hGuard(name, be_global->header_);
00143 be_global->header_ <<
00144 " typedef OpenDDS::DCPS::DataWriterImpl_T<" << cxxName << "> " << short_name << "DataWriterImpl;\n"
00145 " typedef OpenDDS::DCPS::DataReaderImpl_T<" << cxxName << "> " << short_name << "DataReaderImpl;\n"
00146 " typedef OpenDDS::DCPS::TypeSupportImpl_T<" << cxxName << "> " << short_name << "TypeSupportImpl;\n";
00147 }
00148
00149 ScopedNamespaceGuard cppGuard(name, be_global->impl_);
00150
00151 if (be_global->face_ts()) {
00152 face_ts_generator::generate(name);
00153 }
00154
00155 return true;
00156 }
00157
00158 bool ts_generator::gen_union(AST_Union*, UTL_ScopedName* name,
00159 const std::vector<AST_UnionBranch*>&, AST_Type*, const char*)
00160 {
00161 if (idl_global->is_dcps_type(name)) {
00162 std::cerr << "ERROR: union " << scoped(name) << " can not be used as a "
00163 "DCPS_DATA_TYPE (only structs can be Topic types)" << std::endl;
00164 return false;
00165 }
00166 return true;
00167 }
00168
00169 namespace java_ts_generator {
00170
00171
00172 void generate(UTL_ScopedName* name) {
00173 if (idl_global->is_dcps_type(name) == 0) {
00174
00175 return;
00176 }
00177
00178 ACE_CString output_file = be_global->java_arg();
00179 if (output_file.length()) {
00180 be_global->impl_name_ = output_file;
00181 }
00182 be_global->add_include("idl2jni_jni.h", BE_GlobalData::STREAM_CPP);
00183
00184 std::string type = scoped(name);
00185
00186 std::string file, jniclass, jpackage;
00187 for (UTL_ScopedName* sn = name; sn;
00188 sn = static_cast<UTL_ScopedName*>(sn->tail())) {
00189 std::string tmp = sn->head()->get_string();
00190 if (tmp != "" && sn->tail()) {
00191 jpackage += tmp;
00192 file += tmp;
00193 ACE_OS::mkdir(file.c_str());
00194 }
00195 for (size_t i = tmp.find('_'); i < tmp.length();
00196 i = tmp.find('_', i + 1)) {
00197 tmp.insert(++i, 1, '1');
00198 }
00199 jniclass += tmp;
00200 if (jniclass != "" && sn->tail()) {
00201 jniclass += '_';
00202 jpackage += '.';
00203 file += '/';
00204 }
00205 }
00206
00207 if (jpackage[jpackage.size() - 1] == '.') {
00208 jpackage.resize(jpackage.size() - 1);
00209 }
00210
00211 std::string clazz = name->last_component()->get_string();
00212 file += clazz + "TypeSupportImpl.java";
00213
00214 std::ofstream java(file.c_str());
00215 java << (jpackage.size() ? "package " : "") << jpackage
00216 << (jpackage.size() ? ";\n" :"") <<
00217 "public class " << clazz << "TypeSupportImpl extends _" << clazz
00218 << "TypeSupportTAOPeer {\n"
00219 " public " << clazz << "TypeSupportImpl() {\n"
00220 " super(_jni_init());\n"
00221 " }\n"
00222 " private static native long _jni_init();\n"
00223 "}\n";
00224 be_global->impl_ <<
00225 "extern \"C\" JNIEXPORT jlong JNICALL\n"
00226 "Java_" << jniclass << "TypeSupportImpl__1jni_1init(JNIEnv*, jclass) {\n"
00227 " return reinterpret_cast<jlong>(static_cast<CORBA::Object_ptr>(new "
00228 << type << "TypeSupportImpl));\n"
00229 "}\n\n";
00230 }
00231
00232 }
00233
00234 namespace face_ts_generator {
00235
00236 void generate(UTL_ScopedName* name) {
00237 const std::string name_cxx = scoped(name),
00238 name_underscores = dds_generator::scoped_helper(name, "_"),
00239 exportMacro = be_global->export_macro().c_str(),
00240 exporter = exportMacro.empty() ? "" : (" " + exportMacro + '\n');
00241 be_global->add_include("FACE/TS.hpp", BE_GlobalData::STREAM_FACETS_H);
00242 be_global->facets_header_ <<
00243 "namespace FACE\n"
00244 "{\n"
00245 " namespace Read_Callback\n"
00246 " {\n"
00247 " typedef void (*send_event_" << name_underscores << "_Ptr) (\n"
00248 " /* in */ TRANSACTION_ID_TYPE transaction_id,\n"
00249 " /* inout */ " << name_cxx << "& message,\n"
00250 " /* in */ MESSAGE_TYPE_GUID message_type_id,\n"
00251 " /* in */ MESSAGE_SIZE_TYPE message_size,\n"
00252 " /* in */ const WAITSET_TYPE waitset,\n"
00253 " /* out */ RETURN_CODE_TYPE& return_code);\n"
00254 " }\n\n"
00255 " namespace TS\n"
00256 " {\n" << exporter <<
00257 " void Receive_Message(\n"
00258 " /* in */ CONNECTION_ID_TYPE connection_id,\n"
00259 " /* in */ TIMEOUT_TYPE timeout,\n"
00260 " /* inout */ TRANSACTION_ID_TYPE& transaction_id,\n"
00261 " /* out */ " << name_cxx << "& message,\n"
00262 " /* in */ MESSAGE_SIZE_TYPE message_size,\n"
00263 " /* out */ RETURN_CODE_TYPE& return_code);\n\n" << exporter <<
00264 " void Send_Message(\n"
00265 " /* in */ CONNECTION_ID_TYPE connection_id,\n"
00266 " /* in */ TIMEOUT_TYPE timeout,\n"
00267 " /* inout */ TRANSACTION_ID_TYPE& transaction_id,\n"
00268 " /* inout */ " << name_cxx << "& message,\n"
00269 " /* inout */ MESSAGE_SIZE_TYPE& message_size,\n"
00270 " /* out */ RETURN_CODE_TYPE& return_code);\n\n" << exporter <<
00271 " void Register_Callback(\n"
00272 " /* in */ CONNECTION_ID_TYPE connection_id,\n"
00273 " /* in */ const WAITSET_TYPE waitset,\n"
00274 " /* in */ Read_Callback::send_event_" << name_underscores
00275 << "_Ptr data_callback,\n"
00276 " /* in */ MESSAGE_SIZE_TYPE max_message_size,\n"
00277 " /* out */ RETURN_CODE_TYPE& return_code);\n\n"
00278 " }\n"
00279 "}\n\n";
00280 be_global->facets_impl_ <<
00281 "void Receive_Message(CONNECTION_ID_TYPE connection_id,\n"
00282 " TIMEOUT_TYPE timeout,\n"
00283 " TRANSACTION_ID_TYPE& transaction_id,\n"
00284 " " << name_cxx << "& message,\n"
00285 " MESSAGE_SIZE_TYPE message_size,\n"
00286 " RETURN_CODE_TYPE& return_code) {\n"
00287 " OpenDDS::FaceTSS::receive_message(connection_id, timeout,\n"
00288 " transaction_id, message,\n"
00289 " message_size, return_code);\n"
00290 "}\n\n"
00291 "void Send_Message(CONNECTION_ID_TYPE connection_id,\n"
00292 " TIMEOUT_TYPE timeout,\n"
00293 " TRANSACTION_ID_TYPE& transaction_id,\n"
00294 " " << name_cxx << "& message,\n"
00295 " MESSAGE_SIZE_TYPE& message_size,\n"
00296 " RETURN_CODE_TYPE& return_code) {\n"
00297 " OpenDDS::FaceTSS::send_message(connection_id, timeout,\n"
00298 " transaction_id, message,\n"
00299 " message_size, return_code);\n"
00300 "}\n\n"
00301 "void Register_Callback(CONNECTION_ID_TYPE connection_id,\n"
00302 " const WAITSET_TYPE waitset,\n"
00303 " Read_Callback::send_event_" << name_underscores
00304 << "_Ptr data_callback,\n"
00305 " MESSAGE_SIZE_TYPE max_message_size,\n"
00306 " RETURN_CODE_TYPE& return_code) {\n"
00307 " OpenDDS::FaceTSS::register_callback(connection_id, waitset,\n"
00308 " data_callback,\n"
00309 " max_message_size, return_code);\n"
00310 "}\n\n"
00311 "struct " << name_underscores << "_Initializer {\n"
00312 " " << name_underscores << "_Initializer()\n"
00313 " {\n"
00314 " " << name_cxx << "TypeSupport_var ts = new " << name_cxx
00315 << "TypeSupportImpl;\n"
00316 " ts->register_type(0, \"\");\n"
00317 " }\n"
00318 "} init_" << name_underscores << ";\n\n";
00319 }
00320 }