00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "tolua_generator.h"
00024 #include "exceptions.h"
00025
00026 #include <utils/misc/string_conversions.h>
00027
00028 #include <algorithm>
00029 #include <iostream>
00030 #include <vector>
00031 #include <time.h>
00032 #include <fstream>
00033
00034 using namespace std;
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 ToLuaInterfaceGenerator::ToLuaInterfaceGenerator(std::string directory, std::string interface_name,
00060 std::string config_basename, std::string author,
00061 std::string year, std::string creation_date,
00062 std::string data_comment,
00063 const unsigned char *hash, size_t hash_size,
00064 const std::vector<InterfaceConstant> &constants,
00065 const std::vector<InterfaceEnumConstant> &enum_constants,
00066 const std::vector<InterfaceField> &data_fields,
00067 const std::vector<InterfacePseudoMap> &pseudo_maps,
00068 const std::vector<InterfaceMessage> &messages
00069 )
00070 {
00071 this->dir = directory;
00072 if ( dir.find_last_of("/") != (dir.length() - 1) ) {
00073 dir += "/";
00074 }
00075 this->author = author;
00076 this->year = year;
00077 this->creation_date = creation_date;
00078 this->data_comment = data_comment;
00079 this->hash = hash;
00080 this->hash_size = hash_size;
00081 this->constants = constants;
00082 this->enum_constants = enum_constants;
00083 this->data_fields = data_fields;
00084 this->pseudo_maps = pseudo_maps;
00085 this->messages = messages;
00086
00087 filename_tolua = config_basename + ".tolua";
00088 filename_h = config_basename + ".h";
00089
00090 if ( interface_name.find("Interface", 0) == string::npos ) {
00091
00092 class_name = interface_name + "Interface";
00093 } else {
00094 class_name = interface_name;
00095 }
00096 }
00097
00098
00099
00100 ToLuaInterfaceGenerator::~ToLuaInterfaceGenerator()
00101 {
00102 }
00103
00104
00105
00106
00107
00108
00109
00110
00111 const char *
00112 ToLuaInterfaceGenerator::convert_type(std::string c_type)
00113 {
00114 if (c_type == "uint8_t") {
00115 return "unsigned char";
00116 } else if (c_type == "uint16_t") {
00117 return "unsigned short";
00118 } else if (c_type == "uint32_t") {
00119 return "unsigned int";
00120 } else if (c_type == "uint64_t") {
00121 #if __WORDSIZE == 64
00122 return "unsigned long";
00123 #else
00124 return "unsigned long long";
00125 #endif
00126 } else if (c_type == "int8_t") {
00127 return "char";
00128 } else if (c_type == "int16_t") {
00129 return "short";
00130 } else if (c_type == "int32_t") {
00131 return "int";
00132 } else if (c_type == "int64_t") {
00133 #if __WORDSIZE == 64
00134 return "long";
00135 #else
00136 return "long long";
00137 #endif
00138 } else if (c_type == "uint8_t *") {
00139 return "unsigned char *";
00140 } else if (c_type == "uint16_t *") {
00141 return "unsigned short *";
00142 } else if (c_type == "uint32_t *") {
00143 return "unsigned int *";
00144 } else if (c_type == "uint64_t *") {
00145 #if __WORDSIZE == 64
00146 return "unsigned long *";
00147 #else
00148 return "unsigned long long *";
00149 #endif
00150 } else if (c_type == "int8_t *") {
00151 return "char *";
00152 } else if (c_type == "int16_t *") {
00153 return "short *";
00154 } else if (c_type == "int32_t *") {
00155 return "int *";
00156 } else if (c_type == "int64_t *") {
00157 #if __WORDSIZE == 64
00158 return "long *";
00159 #else
00160 return "long long *";
00161 #endif
00162 } else {
00163 return c_type.c_str();
00164 }
00165 }
00166
00167
00168
00169
00170
00171
00172
00173 void
00174 ToLuaInterfaceGenerator::write_header(FILE *f, std::string filename)
00175 {
00176 fprintf(f, "\n/***************************************************************************\n");
00177 fprintf(f, " * %s - Fawkes BlackBoard Interface - %s - tolua++ wrapper\n", filename.c_str(), class_name.c_str());
00178 fprintf(f, " *\n");
00179 if ( creation_date.length() > 0 ) {
00180 fprintf(f, " * Interface created: %s\n", creation_date.c_str());
00181 }
00182 fprintf(f, " * Templated created: Thu Oct 12 10:49:19 2006\n");
00183 fprintf(f, " * Copyright %s %s\n", year.c_str(),
00184 ((author.length() > 0) ? author.c_str() : "AllemaniACs RoboCup Team") );
00185 fprintf(f, " *\n");
00186 fprintf(f, " ****************************************************************************/\n\n");
00187 fprintf(f, "/*\n");
00188 fprintf(f, " * This program is free software; you can redistribute it and/or modify\n");
00189 fprintf(f, " * it under the terms of the GNU General Public License as published by\n");
00190 fprintf(f, " * the Free Software Foundation; either version 2 of the License, or\n");
00191 fprintf(f, " * (at your option) any later version.\n");
00192 fprintf(f, " *\n");
00193 fprintf(f, " * This program is distributed in the hope that it will be useful,\n");
00194 fprintf(f, " * but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
00195 fprintf(f, " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");
00196 fprintf(f, " * GNU Library General Public License for more details.\n");
00197 fprintf(f, " *\n");
00198 fprintf(f, " * You should have received a copy of the GNU General Public License\n");
00199 fprintf(f, " * along with this program; if not, write to the Free Software Foundation,\n");
00200 fprintf(f, " * Inc., 51 Franklin Street, Fifth floor, Boston, MA 02111-1307, USA.\n");
00201 fprintf(f, " */\n\n");
00202 }
00203
00204
00205
00206
00207
00208 void
00209 ToLuaInterfaceGenerator::write_constants_h(FILE *f)
00210 {
00211 for ( vector<InterfaceConstant>::iterator i = constants.begin(); i != constants.end(); ++i) {
00212 fprintf(f, " static const %s %s;\n", convert_type(i->getType()),
00213 i->getName().c_str());
00214 }
00215 fprintf(f, "\n");
00216
00217 for ( vector<InterfaceEnumConstant>::iterator i = enum_constants.begin(); i != enum_constants.end(); ++i) {
00218 fprintf(f, " typedef enum {\n");
00219 vector< pair<string,string> > items = (*i).getItems();
00220 vector< pair<string,string> >::iterator j = items.begin();
00221 while (j != items.end()) {
00222 fprintf(f, " %s", (*j).first.c_str());
00223 ++j;
00224 if ( j != items.end() ) {
00225 fprintf(f, ",\n");
00226 } else {
00227 fprintf(f, "\n");
00228 }
00229 }
00230 fprintf(f, " } %s;\n\n", (*i).getName().c_str());
00231 }
00232 }
00233
00234
00235
00236
00237
00238 void
00239 ToLuaInterfaceGenerator::write_messages_h(FILE *f)
00240 {
00241 for (vector<InterfaceMessage>::iterator i = messages.begin(); i != messages.end(); ++i) {
00242 fprintf(f, " class %s : public Message\n"
00243 " {\n", (*i).getName().c_str());
00244 write_message_ctor_dtor_h(f, " ", (*i).getName(), (*i).getFields());
00245 write_methods_h(f, " ", (*i).getFields());
00246
00247 fprintf(f, " };\n\n");
00248 }
00249
00250 }
00251
00252
00253
00254
00255
00256
00257
00258 void
00259 ToLuaInterfaceGenerator::write_ctor_dtor_h(FILE *f, std::string is,
00260 std::string classname)
00261 {
00262 fprintf(f,
00263 "%s%s();\n"
00264 "%s~%s();\n\n",
00265 is.c_str(), classname.c_str(),
00266 is.c_str(), classname.c_str());
00267 }
00268
00269
00270
00271
00272
00273
00274
00275
00276 void
00277 ToLuaInterfaceGenerator::write_message_ctor_dtor_h(FILE *f, std::string is,
00278 std::string classname,
00279 std::vector<InterfaceField> fields)
00280 {
00281 vector<InterfaceField>::iterator i;
00282
00283 if ( fields.size() > 0 ) {
00284
00285 fprintf(f, "%s%s(", is.c_str(), classname.c_str());
00286
00287 i = fields.begin();
00288 while (i != fields.end()) {
00289 fprintf(f, "%s ini_%s",
00290 convert_type(i->getAccessType()), i->getName().c_str());
00291 ++i;
00292 if ( i != fields.end() ) {
00293 fprintf(f, ", ");
00294 }
00295 }
00296
00297 fprintf(f, ");\n");
00298 }
00299
00300
00301 write_ctor_dtor_h(f, is, classname);
00302 }
00303
00304
00305
00306
00307 void
00308 ToLuaInterfaceGenerator::write_superclass_h(FILE *f)
00309 {
00310 fprintf(f,
00311 " bool oftype(const char *interface_type) const;\n"
00312 " const void * datachunk() const;\n"
00313 " unsigned int datasize() const;\n"
00314 " const char * type() const;\n"
00315 " const char * id() const;\n"
00316 " const char * uid() const;\n"
00317 " unsigned int serial() const;\n"
00318 " unsigned int mem_serial() const;\n"
00319 " bool operator== (Interface &comp) const;\n"
00320 " const unsigned char * hash() const;\n"
00321 " int hash_size() const;\n"
00322 " const char * hash_printable() const;\n"
00323 " bool is_writer() const;\n"
00324
00325 " void set_from_chunk(void *chunk);\n"
00326
00327 " virtual Message * create_message(const char *type) const = 0;\n"
00328
00329 " void read();\n"
00330 " void write();\n"
00331
00332 " bool has_writer() const;\n"
00333 " unsigned int num_readers() const;\n"
00334
00335
00336 " unsigned int msgq_enqueue_copy(Message *message);\n"
00337 " void msgq_remove(Message *message);\n"
00338 " void msgq_remove(unsigned int message_id);\n"
00339 " unsigned int msgq_size();\n"
00340 " void msgq_flush();\n"
00341 " void msgq_lock();\n"
00342 " bool msgq_try_lock();\n"
00343 " void msgq_unlock();\n"
00344 " void msgq_pop();\n"
00345 " Message * msgq_first();\n"
00346 " bool msgq_empty();\n"
00347 "\n");
00348 }
00349
00350
00351
00352
00353
00354
00355 void
00356 ToLuaInterfaceGenerator::write_methods_h(FILE *f, std::string is,
00357 std::vector<InterfaceField> fields)
00358 {
00359 for (vector<InterfaceField>::iterator i = fields.begin(); i != fields.end(); ++i) {
00360
00361 if ( (i->getLengthValue() > 0) && (i->getType() != "string" ) ) {
00362 fprintf(f,
00363 "%s%s %s%s(int index);\n",
00364 is.c_str(),
00365 (i->getType() == "byte") ? "unsigned int" : convert_type(i->getPlainAccessType()),
00366 ( ((*i).getType() == "bool" ) ? "is_" : ""),
00367 (*i).getName().c_str());
00368
00369 fprintf(f,
00370 "%svoid set_%s(unsigned int index, const %s new_%s);\n",
00371 is.c_str(), (*i).getName().c_str(),
00372 convert_type(i->getPlainAccessType()), i->getName().c_str());
00373 } else {
00374 fprintf(f,
00375 "%s%s %s%s();\n",
00376 is.c_str(), convert_type(i->getAccessType()),
00377 ( ((*i).getType() == "bool" ) ? "is_" : ""),
00378 (*i).getName().c_str());
00379
00380 fprintf(f,
00381 "%svoid set_%s(const %s new_%s);\n",
00382 is.c_str(), (*i).getName().c_str(),
00383 convert_type(i->getAccessType()), i->getName().c_str());
00384 }
00385 fprintf(f,
00386 "%sint maxlenof_%s() const;\n",
00387 is.c_str(), (*i).getName().c_str()
00388 );
00389 }
00390 }
00391
00392
00393
00394
00395
00396
00397
00398
00399 void
00400 ToLuaInterfaceGenerator::write_methods_h(FILE *f, std::string is,
00401 std::vector<InterfaceField> fields,
00402 std::vector<InterfacePseudoMap> pseudo_maps)
00403 {
00404 write_methods_h(f, is, fields);
00405
00406 for (vector<InterfacePseudoMap>::iterator i = pseudo_maps.begin(); i != pseudo_maps.end(); ++i) {
00407 fprintf(f,
00408 "%s%s %s(%s key) const;\n"
00409 "%svoid set_%s(const %s key, const %s new_value);\n",
00410 is.c_str(), convert_type(i->getType()),
00411 (*i).getName().c_str(), convert_type(i->getKeyType()),
00412 is.c_str(), (*i).getName().c_str(),
00413 convert_type(i->getKeyType()), convert_type(i->getType()));
00414 }
00415 }
00416
00417
00418
00419
00420
00421 void
00422 ToLuaInterfaceGenerator::write_toluaf(FILE *f)
00423 {
00424 fprintf(f,
00425 "$#include <interfaces/%s>\n"
00426 "$using namespace fawkes;\n"
00427 "namespace fawkes {\n"
00428 "class %s : public Interface\n"
00429 "{\n",
00430 filename_h.c_str(),
00431 class_name.c_str());
00432
00433 write_constants_h(f);
00434 write_messages_h(f);
00435
00436 write_methods_h(f, " ", data_fields, pseudo_maps);
00437 write_superclass_h(f);
00438 fprintf(f, "\n};\n\n}\n");
00439 }
00440
00441
00442
00443
00444 void
00445 ToLuaInterfaceGenerator::generate()
00446 {
00447 char timestring[26];
00448 struct tm timestruct;
00449 time_t t = time(NULL);
00450 localtime_r(&t, ×truct);
00451 asctime_r(×truct, timestring);
00452 gendate = timestring;
00453
00454 FILE *toluaf;
00455
00456 toluaf = fopen(string(dir + filename_tolua).c_str(), "w");
00457
00458 if ( toluaf == NULL ) {
00459 printf("Cannot open tolua file %s%s\n", dir.c_str(), filename_tolua.c_str());
00460 }
00461
00462 write_toluaf(toluaf);
00463
00464 fclose(toluaf);
00465 }