Generator.cpp 73 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965
  1. #include "Generator.h"
  2. Generator* Generator::__instance = NULL;
  3. // Warning flags.
  4. static bool __printTemplateWarning = false;
  5. static bool __printVarargWarning = false;
  6. static bool __printOperatorWarning = false;
  7. // Utility functions (local to this file).
  8. static string trim(const string& str);
  9. static string stripTypeQualifiers(const string& typeStr, FunctionBinding::Param::Kind& kind);
  10. static inline bool isWantedFileNormal(const string& s);
  11. static inline bool isNamespaceFile(const string& s);
  12. static inline bool isGeneratedBindingFile(const string& s);
  13. static bool getFileList(string directory, vector<string>& files, bool (*isWantedFile)(const string& s));
  14. static bool isReservedKeyword(string name);
  15. Generator* Generator::getInstance()
  16. {
  17. if (!__instance)
  18. __instance = new Generator();
  19. return __instance;
  20. }
  21. void Generator::releaseInstance()
  22. {
  23. SAFE_DELETE(__instance);
  24. }
  25. string Generator::getUniqueName(string name)
  26. {
  27. // Calculate the unique name for the given identifier (class, struct, enum, etc).
  28. string uniquename = name;
  29. size_t i = uniquename.find("::");
  30. while (i != uniquename.npos)
  31. {
  32. uniquename.replace(i, 2, SCOPE_REPLACEMENT);
  33. i = uniquename.find("::");
  34. }
  35. return uniquename;
  36. }
  37. string Generator::getUniqueNameFromRef(string refId)
  38. {
  39. return getUniqueName(getIdentifier(refId));
  40. }
  41. vector<string> Generator::getScopePath(string classname, string ns)
  42. {
  43. size_t i = classname.find("::");
  44. vector<string> scopePath;
  45. while (i != classname.npos)
  46. {
  47. string scope = classname.substr(0, i);
  48. if (scope != ns)
  49. scopePath.push_back(scope);
  50. classname = classname.substr(i + 2);
  51. i = classname.find("::");
  52. }
  53. return scopePath;
  54. }
  55. string Generator::getIdentifier(string refId)
  56. {
  57. if (_refIds.find(refId) != _refIds.end())
  58. return _refIds[refId];
  59. return refId;
  60. }
  61. string Generator::getClassNameAndNamespace(string classname, string* ns)
  62. {
  63. size_t index = classname.find("::");
  64. if (index != classname.npos)
  65. {
  66. string classNS = classname.substr(0, index);
  67. if (_namespaces.find(classNS) != _namespaces.end())
  68. {
  69. if (ns)
  70. *ns = classNS;
  71. string tmp = classname.substr(index + 2);
  72. if (_namespaces[classNS].find(tmp) != _namespaces[classNS].end())
  73. return classname.substr(index + 2);
  74. else
  75. {
  76. size_t tmpIndex = tmp.find("::");
  77. if (tmpIndex != tmp.npos)
  78. {
  79. tmp = tmp.substr(0, tmpIndex);
  80. if (_namespaces[classNS].find(tmp) != _namespaces[classNS].end())
  81. {
  82. _namespaces[classNS].insert(classname.substr(index + 2));
  83. return classname.substr(index + 2);
  84. }
  85. }
  86. }
  87. }
  88. }
  89. return classname;
  90. }
  91. void Generator::setIdentifier(string refId, string id)
  92. {
  93. _refIds[refId] = id;
  94. }
  95. bool Generator::isDerived(const ClassBinding& c, string classname)
  96. {
  97. for (unsigned int i = 0; i < c.derived.size(); i++)
  98. {
  99. // If the derived class is not in the ref ID table, then it
  100. // is a hidden (protected, private, etc.) class, so don't consider it.
  101. if (_refIds.find(c.derived[i]) != _refIds.end())
  102. {
  103. const string& derivedClassName = getIdentifier(c.derived[i]);
  104. if (derivedClassName == classname ||
  105. (_classes.find(derivedClassName) != _classes.end() &&
  106. isDerived(_classes[derivedClassName], classname)))
  107. {
  108. return true;
  109. }
  110. }
  111. }
  112. return false;
  113. }
  114. bool Generator::isRef(string classname)
  115. {
  116. // Check if the class is derived from Ref.
  117. for (unsigned int i = 0; i < _topLevelBaseClasses.size(); i++)
  118. {
  119. if (_topLevelBaseClasses[i] == REF_CLASS_NAME)
  120. {
  121. return isDerived(_classes[_topLevelBaseClasses[i]], classname);
  122. }
  123. }
  124. return classname == REF_CLASS_NAME;
  125. }
  126. string Generator::getCompoundName(XMLElement* node)
  127. {
  128. // Get the name of the namespace, class, struct, or file that we are processing.
  129. XMLElement* nameElement = node->FirstChildElement("compoundname");
  130. if (!nameElement)
  131. {
  132. GP_ERROR("Missing 'compoundname' child node of 'compounddef' node for XML document '%s'.", _file);
  133. return "";
  134. }
  135. const char* text = nameElement->GetText();
  136. if (!text)
  137. {
  138. GP_ERROR("The 'compoundname' node is empty for XML document '%s'.", _file);
  139. return "";
  140. }
  141. return string(text);
  142. }
  143. void Generator::run(string inDir, string outDir, string* bindingNS)
  144. {
  145. // Set the output directory.
  146. _outDir = outDir;
  147. // Get a list of all .cpp and .h files in the output directory so
  148. // we can delete them before generating new bindings.
  149. vector<string> oldBindingsFiles;
  150. getFileList(outDir, oldBindingsFiles, isGeneratedBindingFile);
  151. // Delete the old bindings.
  152. for (unsigned int i = 0; i < oldBindingsFiles.size(); i++)
  153. {
  154. remove(oldBindingsFiles[i].c_str());
  155. }
  156. // Get a list of the Doxygen XML files that specify a namespace.
  157. // Note: we must do this before adding the normal files so that
  158. // when we process the files sequentially, we process the namespaces
  159. // before the normal files (so that namespaces can be removed
  160. // properly from class/struct names, etc.)
  161. vector<string> files;
  162. getFileList(inDir, files, isNamespaceFile);
  163. // Add all of the normal Doxygen XML files we want to use to generate Lua bindings.
  164. if (!getFileList(inDir, files, isWantedFileNormal) || files.empty())
  165. {
  166. GP_ERROR("Failed to get a valid list of files to generate bindings from using directory '%s'.", inDir.c_str());
  167. return;
  168. }
  169. // Go through each file and build the data needed to generate the bindings.
  170. for (vector<string>::iterator iter = files.begin(); iter != files.end(); iter++)
  171. {
  172. tinyxml2::XMLDocument doc;
  173. _file = iter->c_str();
  174. doc.LoadFile(iter->c_str());
  175. int ret = doc.ErrorID();
  176. if (ret != 0)
  177. {
  178. GP_ERROR("Failed to load XML document '%s' properly with error ID %d.", iter->c_str(), ret);
  179. continue;
  180. }
  181. XMLElement* rootNode = doc.FirstChildElement("doxygen");
  182. if (!rootNode)
  183. {
  184. GP_ERROR("Missing root 'doxygen' node for XML document '%s'.", iter->c_str());
  185. continue;
  186. }
  187. XMLElement* node = rootNode->FirstChildElement("compounddef");
  188. if (!node)
  189. {
  190. GP_ERROR("Missing 'compounddef' node for XML document '%s'.", iter->c_str());
  191. continue;
  192. }
  193. const char* kind = node->Attribute("kind");
  194. if (kind && strcmp(kind, "namespace") == 0)
  195. {
  196. string name = getCompoundName(node);
  197. cout << "Parsing namespace " << name << "...\n";
  198. getNamespace(node, name);
  199. }
  200. else if ( (kind && (strcmp(kind, "class") == 0 || strcmp(kind, "struct") == 0) ) && strcmp(node->Attribute("prot"), "public") == 0)
  201. {
  202. string name = getCompoundName(node);
  203. cout << "Parsing class/struct " << name << "...\n";
  204. getClass(node, name);
  205. }
  206. else if (kind && strcmp(kind, "file") == 0)
  207. {
  208. string name = getCompoundName(node);
  209. cout << "Parsing file " << name << "...\n";
  210. if (name.find(".h") != name.npos)
  211. {
  212. getFunctions(node);
  213. getEnums(node, name);
  214. }
  215. else if (name.find(".cpp") != name.npos)
  216. {
  217. getIncludes(node, name);
  218. }
  219. }
  220. }
  221. // Resolve all inheritance.
  222. resolveInheritance();
  223. // Resolve all unrecognized parameter and return value types.
  224. resolveTypes();
  225. // Resolve all inherited include files.
  226. resolveInheritedIncludes();
  227. // Generate the script bindings.
  228. generateBindings(bindingNS);
  229. // Print out all warnings (unsupported types, function name-Lua keyword clashes, etc.)
  230. if (__warnings.size() > 0)
  231. {
  232. cout << "\nWarnings:\n";
  233. for (set<string>::iterator iter = __warnings.begin(); iter!= __warnings.end(); iter++)
  234. {
  235. GP_WARN("%s", iter->c_str());
  236. }
  237. }
  238. // Print warnings for the use of unsupported C++ features.
  239. if (__printTemplateWarning)
  240. GP_WARN("Detected the use of template parameters; this feature of C++ is not supported.");
  241. if (__printVarargWarning)
  242. GP_WARN("Detected the use of variable argument lists; this feature of C++ is not supported.");
  243. if (__printOperatorWarning)
  244. GP_WARN("Detected the use of operator overloading; this feature of C++ is not supported.");
  245. }
  246. Generator::Generator()
  247. {
  248. }
  249. Generator::~Generator()
  250. {
  251. }
  252. void Generator::getFunctions(XMLElement* fileNode, string ns)
  253. {
  254. // Process all public, non-static functions and variables that are defined in this file.
  255. XMLElement* node = NULL;
  256. const char* kind = NULL;
  257. const char* isStatic = NULL;
  258. for (node = fileNode->FirstChildElement("sectiondef"); node != NULL; node = node->NextSiblingElement("sectiondef"))
  259. {
  260. kind = node->Attribute("kind");
  261. if (kind && strcmp(kind, "func") == 0)
  262. {
  263. XMLElement* e = node->FirstChildElement("memberdef");
  264. while (e)
  265. {
  266. isStatic = e->Attribute("static");
  267. if (e->FirstChildElement("templateparamlist"))
  268. {
  269. __printTemplateWarning = true;
  270. }
  271. else if (getScriptFlag(e) != "ignore" &&
  272. (!isStatic || strcmp(isStatic, "yes") != 0))
  273. {
  274. FunctionBinding b;
  275. b.type = FunctionBinding::GLOBAL_FUNCTION;
  276. b.name = getName(e);
  277. if (!isReservedKeyword(b.name))
  278. {
  279. // Ignore operators.
  280. if (b.name.find("operator") != 0)
  281. {
  282. b.returnParam = getParam(e);
  283. getParams(e, b);
  284. getCreateFlag(e, b);
  285. _functions[b.getFunctionName()].push_back(b);
  286. // Add the function to the set of namespace members if it is part of a namespace.
  287. if (ns.size() > 0)
  288. _namespaces[ns].insert(b.name);
  289. }
  290. else
  291. {
  292. __printOperatorWarning = true;
  293. }
  294. }
  295. else
  296. {
  297. __warnings.insert(string("Function name '") + b.name + string("' is a reserved Lua keyword; binding '") + b.getFunctionName() + string("' was not generated."));
  298. }
  299. }
  300. e = e->NextSiblingElement("memberdef");
  301. }
  302. }
  303. else if (kind && strcmp(kind, "var") == 0)
  304. {
  305. XMLElement* e = node->FirstChildElement("memberdef");
  306. while (e)
  307. {
  308. isStatic = e->Attribute("static");
  309. if (getScriptFlag(e) != "ignore" &&
  310. (!isStatic || strcmp(isStatic, "yes") != 0))
  311. {
  312. FunctionBinding b;
  313. if (getIsConstType(e))
  314. b.type = FunctionBinding::GLOBAL_CONSTANT;
  315. else
  316. b.type = FunctionBinding::GLOBAL_VARIABLE;
  317. b.name = getName(e);
  318. if (!isReservedKeyword(b.name))
  319. {
  320. b.returnParam = getParam(e, true);
  321. _functions[b.getFunctionName()].push_back(b);
  322. // Add the variable to the set of namespace members if it is part of a namespace.
  323. if (ns.size() > 0)
  324. _namespaces[ns].insert(b.name);
  325. }
  326. else
  327. {
  328. __warnings.insert(string("Function name '") + b.name + string("' is a reserved Lua keyword; binding '") + b.getFunctionName() + string("' was not generated."));
  329. }
  330. }
  331. e = e->NextSiblingElement("memberdef");
  332. }
  333. }
  334. }
  335. }
  336. void Generator::getNamespace(XMLElement* nsNode, const string& name)
  337. {
  338. // Skip the 'std' namespace.
  339. if (name == "std")
  340. return;
  341. // Create the set of all classes that are a part of this namespace.
  342. XMLElement* e = nsNode->FirstChildElement("innerclass");
  343. while (e)
  344. {
  345. string classname = e->GetText();
  346. size_t i = classname.find("::");
  347. if (i != classname.npos)
  348. classname = classname.substr(i + 2);
  349. _namespaces[name].insert(classname);
  350. e = e->NextSiblingElement("innerclass");
  351. }
  352. // Parse all functions that are directly in this namespace.
  353. getFunctions(nsNode, name);
  354. // Parse all enums that are directly in this namespace.
  355. getEnums(nsNode, name);
  356. // Parse all typedefs.
  357. getTypedefs(nsNode, name);
  358. }
  359. void Generator::getClass(XMLElement* classNode, const string& name)
  360. {
  361. // Get the ref id for the class.
  362. string refId = classNode->Attribute("id");
  363. // Create the class binding object that we will store the function bindings in (name -> binding).
  364. ClassBinding classBinding(name, refId);
  365. // Store the mapping between the ref id and the class's fully qualified name.
  366. Generator::getInstance()->setIdentifier(refId, classBinding.classname);
  367. // Check if we should ignore this class.
  368. if (getScriptFlag(classNode) == "ignore")
  369. return;
  370. // Get the include header for the original class declaration.
  371. XMLElement* includeElement = classNode->FirstChildElement("includes");
  372. if (includeElement)
  373. {
  374. const char* text = includeElement->GetText();
  375. if (!text)
  376. {
  377. GP_ERROR("The 'includes' node is empty (a class must have an include file) for XML document '%s'.", _file);
  378. return;
  379. }
  380. classBinding.include = text;
  381. }
  382. else
  383. {
  384. // See if we are an inner class. If so, attempt to get the include from the root parent class.
  385. size_t index = classBinding.classname.find("::");
  386. if (index != classBinding.classname.npos)
  387. {
  388. string parentClassName = classBinding.classname.substr(0, index);
  389. if (_classes.find(parentClassName) != _classes.end())
  390. classBinding.include = _classes[parentClassName].include;
  391. }
  392. }
  393. // Track whether the class has any pure virtual functions.
  394. bool hasPureVirtual = false;
  395. // Process all public members that are defined in this class.
  396. XMLElement* node = NULL;
  397. const char* kind = NULL;
  398. for (node = classNode->FirstChildElement("sectiondef"); node != NULL; node = node->NextSiblingElement("sectiondef"))
  399. {
  400. kind = node->Attribute("kind");
  401. if (!kind)
  402. {
  403. GP_ERROR("Section definition is missing required 'kind' attribute in XML document '%s'.", _file);
  404. return;
  405. }
  406. // Process public static functions.
  407. if (strcmp(kind, "public-static-func") == 0)
  408. {
  409. XMLElement* e = node->FirstChildElement("memberdef");
  410. while (e)
  411. {
  412. if (e->FirstChildElement("templateparamlist"))
  413. {
  414. __printTemplateWarning = true;
  415. }
  416. else if (getScriptFlag(e) != "ignore")
  417. {
  418. FunctionBinding b(classBinding.classname, classBinding.uniquename);
  419. b.type = FunctionBinding::STATIC_FUNCTION;
  420. b.name = getName(e);
  421. if (!isReservedKeyword(b.name))
  422. {
  423. b.returnParam = getParam(e, false, b.classname);
  424. getParams(e, b);
  425. getCreateFlag(e, b);
  426. classBinding.bindings[b.getFunctionName()].push_back(b);
  427. }
  428. else
  429. {
  430. __warnings.insert(string("Function name '") + b.name + string("' is a reserved Lua keyword; binding '") + b.getFunctionName() + string("' was not generated."));
  431. }
  432. }
  433. e = e->NextSiblingElement("memberdef");
  434. }
  435. }
  436. // Process public member functions.
  437. else if (strcmp(kind, "public-func") == 0)
  438. {
  439. XMLElement* e = node->FirstChildElement("memberdef");
  440. while (e)
  441. {
  442. if (e->FirstChildElement("templateparamlist"))
  443. {
  444. __printTemplateWarning = true;
  445. }
  446. else if (getScriptFlag(e) != "ignore")
  447. {
  448. if (strcmp(e->Attribute("virt"), "pure-virtual") == 0)
  449. hasPureVirtual = true;
  450. FunctionBinding b(classBinding.classname, classBinding.uniquename);
  451. b.type = FunctionBinding::MEMBER_FUNCTION;
  452. b.name = getName(e);
  453. if (!isReservedKeyword(b.name))
  454. {
  455. // Ignore operators.
  456. if (b.name.find("operator") != 0)
  457. {
  458. b.returnParam = getParam(e, false, b.classname);
  459. if (b.returnParam.type == FunctionBinding::Param::TYPE_CONSTRUCTOR)
  460. {
  461. b.returnParam.info = refId;
  462. b.own = true;
  463. }
  464. getParams(e, b);
  465. getCreateFlag(e, b);
  466. classBinding.bindings[b.getFunctionName()].push_back(b);
  467. }
  468. else
  469. {
  470. __printOperatorWarning = true;
  471. }
  472. }
  473. else
  474. {
  475. __warnings.insert(string("Function name '") + b.name + string("' is a reserved Lua keyword; binding '") + b.getFunctionName() + string("' was not generated."));
  476. }
  477. }
  478. e = e->NextSiblingElement("memberdef");
  479. }
  480. }
  481. // Process public static variables.
  482. else if (strcmp(kind, "public-static-attrib") == 0)
  483. {
  484. XMLElement* e = node->FirstChildElement("memberdef");
  485. while (e)
  486. {
  487. if (getScriptFlag(e) != "ignore")
  488. {
  489. FunctionBinding b(classBinding.classname, classBinding.uniquename);
  490. if (getIsConstType(e))
  491. b.type = FunctionBinding::STATIC_CONSTANT;
  492. else
  493. b.type = FunctionBinding::STATIC_VARIABLE;
  494. b.name = getName(e);
  495. if (!isReservedKeyword(b.name))
  496. {
  497. b.returnParam = getParam(e, true, b.classname);
  498. classBinding.bindings[b.getFunctionName()].push_back(b);
  499. }
  500. else
  501. {
  502. __warnings.insert(string("Function name '") + b.name + string("' is a reserved Lua keyword; binding '") + b.getFunctionName() + string("' was not generated."));
  503. }
  504. }
  505. e = e->NextSiblingElement("memberdef");
  506. }
  507. }
  508. // Process public member variables.
  509. else if (strcmp(kind, "public-attrib") == 0)
  510. {
  511. XMLElement* e = node->FirstChildElement("memberdef");
  512. while (e)
  513. {
  514. if (e->FirstChildElement("templateparamlist"))
  515. {
  516. __printTemplateWarning = true;
  517. }
  518. else if (getScriptFlag(e) != "ignore")
  519. {
  520. FunctionBinding b(classBinding.classname, classBinding.uniquename);
  521. if (getIsConstType(e))
  522. b.type = FunctionBinding::MEMBER_CONSTANT;
  523. else
  524. b.type = FunctionBinding::MEMBER_VARIABLE;
  525. b.name = getName(e);
  526. if (!isReservedKeyword(b.name))
  527. {
  528. b.returnParam = getParam(e, true, b.classname);
  529. classBinding.bindings[b.getFunctionName()].push_back(b);
  530. }
  531. else
  532. {
  533. __warnings.insert(string("Function name '") + b.name + string("' is a reserved Lua keyword; binding '") + b.getFunctionName() + string("' was not generated."));
  534. }
  535. }
  536. e = e->NextSiblingElement("memberdef");
  537. }
  538. }
  539. else if (strcmp(kind, "protected-func") == 0 ||
  540. strcmp(kind, "private-func") == 0)
  541. {
  542. // Check for inaccessible constructor/destructor
  543. // and create a list of all other inaccessible functions
  544. // (we do this so that classes that override a public function
  545. // and change its scope to protected or private work properly
  546. // from Lua-i.e. no binding is generated for such functions).
  547. XMLElement* e = node->FirstChildElement("memberdef");
  548. while (e)
  549. {
  550. if (strcmp(e->Attribute("virt"), "pure-virtual") == 0)
  551. hasPureVirtual = true;
  552. FunctionBinding::Param t = getParam(e);
  553. if (t.type == FunctionBinding::Param::TYPE_CONSTRUCTOR)
  554. {
  555. classBinding.inaccessibleConstructor = true;
  556. }
  557. else if (t.type == FunctionBinding::Param::TYPE_DESTRUCTOR)
  558. {
  559. classBinding.inaccessibleDestructor = true;
  560. }
  561. else
  562. {
  563. FunctionBinding b(classBinding.classname, classBinding.uniquename);
  564. b.type = FunctionBinding::MEMBER_FUNCTION;
  565. b.name = getName(e);
  566. if (!isReservedKeyword(b.name))
  567. {
  568. // Ignore operators.
  569. if (b.name.find("operator") != 0)
  570. {
  571. b.returnParam = getParam(e, false, b.classname);
  572. if (b.returnParam.type == FunctionBinding::Param::TYPE_CONSTRUCTOR)
  573. {
  574. b.returnParam.info = refId;
  575. b.own = true;
  576. }
  577. getParams(e, b);
  578. getCreateFlag(e, b);
  579. classBinding.hidden[b.getFunctionName()].push_back(b);
  580. }
  581. else
  582. {
  583. __printOperatorWarning = true;
  584. }
  585. }
  586. }
  587. e = e->NextSiblingElement("memberdef");
  588. }
  589. }
  590. else if (strcmp(kind, "protected-static-func") == 0 ||
  591. strcmp(kind, "private-static-func") == 0)
  592. {
  593. // Create a list of all other inaccessible functions
  594. // (we do this so that classes that override a public function
  595. // and change its scope to protected or private work properly
  596. // from Lua-i.e. no binding is generated for such functions).
  597. XMLElement* e = node->FirstChildElement("memberdef");
  598. while (e)
  599. {
  600. if (e->FirstChildElement("templateparamlist"))
  601. {
  602. __printTemplateWarning = true;
  603. }
  604. else if (getScriptFlag(e) != "ignore")
  605. {
  606. FunctionBinding b(classBinding.classname, classBinding.uniquename);
  607. b.type = FunctionBinding::STATIC_FUNCTION;
  608. b.name = getName(e);
  609. if (!isReservedKeyword(b.name))
  610. {
  611. b.returnParam = getParam(e, false, b.classname);
  612. getParams(e, b);
  613. getCreateFlag(e, b);
  614. classBinding.hidden[b.getFunctionName()].push_back(b);
  615. }
  616. }
  617. e = e->NextSiblingElement("memberdef");
  618. }
  619. }
  620. // Process public enums and typedefs.
  621. else if (strcmp(kind, "public-type") == 0)
  622. {
  623. XMLElement* e = node->FirstChildElement("memberdef");
  624. while (e)
  625. {
  626. if (getScriptFlag(e) != "ignore")
  627. {
  628. if (strcmp(e->Attribute("kind"), "enum") == 0)
  629. {
  630. getEnum(e, classBinding.classname, classBinding.ns, classBinding.include);
  631. }
  632. else if (strcmp(e->Attribute("kind"), "typedef") == 0)
  633. {
  634. getTypedef(e, classBinding.classname, classBinding.ns);
  635. }
  636. }
  637. e = e->NextSiblingElement("memberdef");
  638. }
  639. }
  640. else
  641. {
  642. // Ignore other section definitions.
  643. }
  644. }
  645. // If the class has a pure-virtual method, we mark the constructor as inaccessible
  646. // and remove any constructor bindings that are in the list.
  647. if (hasPureVirtual)
  648. {
  649. classBinding.inaccessibleConstructor = true;
  650. map<string, vector<FunctionBinding> >::iterator iter = classBinding.bindings.begin();
  651. for (; iter != classBinding.bindings.end(); iter++)
  652. {
  653. if (iter->second[0].returnParam.type == FunctionBinding::Param::TYPE_CONSTRUCTOR)
  654. {
  655. classBinding.bindings.erase(iter);
  656. break;
  657. }
  658. }
  659. }
  660. // Store the class's derived class(es)' ref id(s) if it has any.
  661. node = classNode->FirstChildElement("derivedcompoundref");
  662. while (node)
  663. {
  664. classBinding.derived.push_back(node->Attribute("refid"));
  665. node = node->NextSiblingElement("derivedcompoundref");
  666. }
  667. // If the class has no base classes and it has derived classes, add it to the list of top-level classes.
  668. if (!classNode->FirstChildElement("basecompoundref") && classBinding.derived.size() > 0)
  669. _topLevelBaseClasses.push_back(classBinding.classname);
  670. // Insert the class binding into the global table.
  671. _classes[classBinding.classname] = classBinding;
  672. }
  673. void Generator::getEnums(XMLElement* fileNode, string ns)
  674. {
  675. XMLElement* node = NULL;
  676. const char* kind = NULL;
  677. for (node = fileNode->FirstChildElement("sectiondef"); node != NULL; node = node->NextSiblingElement("sectiondef"))
  678. {
  679. kind = node->Attribute("kind");
  680. if (!kind)
  681. {
  682. GP_ERROR("Section definition is missing required 'kind' attribute in XML document '%s'.", _file);
  683. return;
  684. }
  685. // Process the enums.
  686. if (strcmp(kind, "enum") == 0)
  687. {
  688. XMLElement* e = node->FirstChildElement("memberdef");
  689. while (e)
  690. {
  691. if (getScriptFlag(e) != "ignore" && strcmp(e->Attribute("kind"), "enum") == 0)
  692. {
  693. getEnum(e, "", ns);
  694. }
  695. e = e->NextSiblingElement("memberdef");
  696. }
  697. }
  698. }
  699. }
  700. void Generator::getEnum(XMLElement* e, string classname, string ns, string include)
  701. {
  702. // Get the enumeration's name.
  703. string enumname = classname;
  704. if (enumname.size() > 0)
  705. enumname += string("::");
  706. enumname += getName(e);
  707. // Get the ref id for the enum.
  708. string refId = e->Attribute("id");
  709. // Store the ref id to name mapping.
  710. Generator::getInstance()->setIdentifier(refId, enumname);
  711. // Add the enum to the enum list if it's not there
  712. // (we implicitly create it when we set its scope path).
  713. if (_enums.find(enumname) == _enums.end())
  714. _enums[enumname].scopePath = Generator::getScopePath(enumname, ns);
  715. // Set the include file for the enum.
  716. if (include.size() > 0)
  717. _enums[enumname].include = include;
  718. else
  719. {
  720. XMLElement* location = e->FirstChildElement("location");
  721. if (location)
  722. _enums[enumname].include = location->Attribute("file");
  723. }
  724. for (e = e->FirstChildElement("enumvalue"); e; e = e->NextSiblingElement("enumvalue"))
  725. {
  726. _enums[enumname].values.push_back(getName(e));
  727. }
  728. // Add the enum to the set of namespace members if it is part of a namespace.
  729. if (ns.size() > 0)
  730. _namespaces[ns].insert(enumname);
  731. }
  732. void Generator::getTypedefs(XMLElement* fileNode, string ns)
  733. {
  734. XMLElement* node = NULL;
  735. const char* kind = NULL;
  736. for (node = fileNode->FirstChildElement("sectiondef"); node != NULL; node = node->NextSiblingElement("sectiondef"))
  737. {
  738. kind = node->Attribute("kind");
  739. if (!kind)
  740. {
  741. GP_ERROR("Section definition is missing required 'kind' attribute in XML document '%s'.", _file);
  742. return;
  743. }
  744. // Process the enums.
  745. if (strcmp(kind, "typedef") == 0)
  746. {
  747. XMLElement* e = node->FirstChildElement("memberdef");
  748. while (e)
  749. {
  750. if (getScriptFlag(e) != "ignore" && strcmp(e->Attribute("kind"), "typedef") == 0)
  751. {
  752. getTypedef(e, "", ns);
  753. }
  754. e = e->NextSiblingElement("memberdef");
  755. }
  756. }
  757. }
  758. }
  759. void Generator::getTypedef(XMLElement* e, string classname, string ns)
  760. {
  761. TypedefBinding t;
  762. // Get the typedef's name.
  763. string tname = classname;
  764. if (tname.size() > 0)
  765. tname += string("::");
  766. tname += getName(e);
  767. // Get the typedef's id and store the mapping from ref id to name.
  768. string refId = e->Attribute("id");
  769. setIdentifier(refId, tname);
  770. FunctionBinding::Param p = getParam(e);
  771. if (p.info.size() > 0)
  772. t.refId = p.info;
  773. _typedefs[tname] = t;
  774. // Add the typedef to the set of namespace members if it is part of a namespace.
  775. if (ns.size() > 0)
  776. _namespaces[ns].insert(tname);
  777. }
  778. static inline bool getScriptFlagHelper(XMLElement* e, string& flag)
  779. {
  780. XMLElement* x = e->FirstChildElement("xmlonly");
  781. if (x)
  782. {
  783. flag = x->GetText();
  784. return true;
  785. }
  786. x = e->FirstChild() ? e->FirstChild()->ToElement() : NULL;
  787. while (x)
  788. {
  789. if (getScriptFlagHelper(x, flag))
  790. return true;
  791. x = x->NextSibling() ? x->NextSibling()->ToElement() : NULL;
  792. }
  793. return false;
  794. }
  795. string Generator::getScriptFlag(XMLElement* e)
  796. {
  797. string flag;
  798. XMLElement* n = e->FirstChildElement("detaileddescription");
  799. if (n)
  800. getScriptFlagHelper(n, flag);
  801. return flag;
  802. }
  803. void Generator::getCreateFlag(XMLElement* e, FunctionBinding& b)
  804. {
  805. if (getScriptFlag(e) == "create")
  806. b.own = true;
  807. }
  808. string Generator::getName(XMLElement* e)
  809. {
  810. // Get the name for the binding.
  811. XMLElement* nameElement = e->FirstChildElement("name");
  812. if (!nameElement)
  813. {
  814. GP_ERROR("Missing 'name' child node in XML document '%s'.", _file);
  815. return string();
  816. }
  817. return nameElement->GetText();
  818. }
  819. bool Generator::getIsConstType(XMLElement* e)
  820. {
  821. XMLElement* typeElement = e->FirstChildElement("type");
  822. if (!typeElement)
  823. {
  824. GP_ERROR("Missing 'type' node in XML document '%s'.", _file);
  825. return false;
  826. }
  827. XMLNode* textNode = typeElement->FirstChild();
  828. if (textNode)
  829. {
  830. XMLText* text = textNode->ToText();
  831. if (text)
  832. {
  833. string type = text->Value();
  834. return type.find("const") != type.npos;
  835. }
  836. }
  837. return false;
  838. }
  839. FunctionBinding::Param Generator::getParam(XMLElement* e, bool isVariable, string classname)
  840. {
  841. // Get the type for the current element (either the return type or a parameter type).
  842. XMLElement* typeElement = e->FirstChildElement("type");
  843. if (!typeElement)
  844. {
  845. GP_ERROR("Missing 'type' node in XML document '%s'.", _file);
  846. }
  847. FunctionBinding::Param p;
  848. XMLNode* textNode = typeElement->FirstChild();
  849. if (!textNode)
  850. {
  851. // Get the name of the current element to see if it is a destructor.
  852. string name = getName(e);
  853. if (name.find("~") == 0)
  854. {
  855. p = FunctionBinding::Param(FunctionBinding::Param::TYPE_DESTRUCTOR);
  856. }
  857. else
  858. {
  859. // Assume it's a constructor.
  860. p = FunctionBinding::Param(FunctionBinding::Param::TYPE_CONSTRUCTOR, FunctionBinding::Param::KIND_POINTER, name);
  861. }
  862. }
  863. else
  864. {
  865. // Get the type string without const or reference qualifiers (and trim whitespace).
  866. string refId = "";
  867. string typeStr = "";
  868. FunctionBinding::Param::Kind kind;
  869. {
  870. // Attempt to process the type as reference (i.e. class, struct, enum, typedef, etc.) type.
  871. XMLNode* node = textNode;
  872. while (node)
  873. {
  874. if (strcmp(node->Value(), "ref") == 0)
  875. {
  876. refId = node->ToElement()->Attribute("refid");
  877. typeStr += node->ToElement()->GetText();
  878. }
  879. else if (node->ToText())
  880. {
  881. typeStr += node->ToText()->Value();
  882. }
  883. node = node->NextSibling();
  884. }
  885. typeStr = stripTypeQualifiers(typeStr, kind);
  886. }
  887. if (typeStr == "void")
  888. {
  889. p = FunctionBinding::Param(FunctionBinding::Param::TYPE_VOID, kind);
  890. }
  891. else if (typeStr == "bool")
  892. {
  893. p = FunctionBinding::Param(FunctionBinding::Param::TYPE_BOOL, kind);
  894. }
  895. else if (typeStr == "char" && kind != FunctionBinding::Param::KIND_POINTER)
  896. {
  897. p = FunctionBinding::Param(FunctionBinding::Param::TYPE_CHAR, kind);
  898. }
  899. else if (typeStr == "short")
  900. {
  901. p = FunctionBinding::Param(FunctionBinding::Param::TYPE_SHORT, kind);
  902. }
  903. else if (typeStr == "int")
  904. {
  905. p = FunctionBinding::Param(FunctionBinding::Param::TYPE_INT, kind);
  906. }
  907. else if (typeStr == "long")
  908. {
  909. p = FunctionBinding::Param(FunctionBinding::Param::TYPE_LONG, kind);
  910. }
  911. else if (typeStr == "unsigned char")
  912. {
  913. p = FunctionBinding::Param(FunctionBinding::Param::TYPE_UCHAR, kind);
  914. }
  915. else if (typeStr == "unsigned short")
  916. {
  917. p = FunctionBinding::Param(FunctionBinding::Param::TYPE_USHORT, kind);
  918. }
  919. else if (typeStr == "unsigned int")
  920. {
  921. p = FunctionBinding::Param(FunctionBinding::Param::TYPE_UINT, kind);
  922. }
  923. else if (typeStr == "unsigned long")
  924. {
  925. p = FunctionBinding::Param(FunctionBinding::Param::TYPE_ULONG, kind);
  926. }
  927. else if (typeStr == "float")
  928. {
  929. p = FunctionBinding::Param(FunctionBinding::Param::TYPE_FLOAT, kind);
  930. }
  931. else if (typeStr == "double")
  932. {
  933. p = FunctionBinding::Param(FunctionBinding::Param::TYPE_DOUBLE, kind);
  934. }
  935. else if (typeStr == "string" || typeStr == "std::string")
  936. {
  937. p = FunctionBinding::Param(FunctionBinding::Param::TYPE_STRING, kind, "string");
  938. }
  939. else if (typeStr == "char" && kind == FunctionBinding::Param::KIND_POINTER)
  940. {
  941. p = FunctionBinding::Param(FunctionBinding::Param::TYPE_STRING, kind, "char*");
  942. }
  943. else if (_enums.find(typeStr) != _enums.end() ||
  944. (classname.size() > 0 && _enums.find(classname + string("::") + typeStr) != _enums.end()))
  945. {
  946. p = FunctionBinding::Param(FunctionBinding::Param::TYPE_ENUM, kind, refId);
  947. }
  948. else if (typeStr == "...")
  949. {
  950. __printVarargWarning = true;
  951. p = FunctionBinding::Param(FunctionBinding::Param::TYPE_VARARGS);
  952. }
  953. else
  954. {
  955. p = FunctionBinding::Param(FunctionBinding::Param::TYPE_UNRECOGNIZED, kind, (refId.size() > 0) ? refId : typeStr);
  956. }
  957. // Check if the type is a pointer declared with square brackets (i.e. float x[4]).
  958. XMLElement* arrayElement = NULL;
  959. if ((arrayElement = e->FirstChildElement("array")) != NULL ||
  960. (isVariable && (arrayElement = e->FirstChildElement("argsstring")) != NULL))
  961. {
  962. const char* text = arrayElement->GetText();
  963. string arrayString = (text ? text : "");
  964. string::size_type i = arrayString.find("[");
  965. string::size_type k = arrayString.find("]");
  966. if (i != arrayString.npos && k != arrayString.npos)
  967. {
  968. p.kind = FunctionBinding::Param::KIND_POINTER;
  969. if (i != k - 1)
  970. p.info = arrayString.substr(i + 1, k - (i + 1));
  971. }
  972. }
  973. }
  974. // Get the default value for the parameter if it has one.
  975. XMLElement* defaultValueElement = e->FirstChildElement("defval");
  976. if (defaultValueElement)
  977. {
  978. p.hasDefaultValue = true;
  979. }
  980. return p;
  981. }
  982. void Generator::getParams(XMLElement* e, FunctionBinding& b)
  983. {
  984. XMLElement* param = e->FirstChildElement("param");
  985. while (param)
  986. {
  987. FunctionBinding::Param p = getParam(param, false, b.classname);
  988. if (p.type != FunctionBinding::Param::TYPE_VARARGS)
  989. b.paramTypes.push_back(p);
  990. param = param->NextSiblingElement("param");
  991. }
  992. }
  993. void Generator::resolveMembers(const ClassBinding& c)
  994. {
  995. vector<ClassBinding*> derived;
  996. // Go through the derived classes' bindings and update them.
  997. ClassBinding* cb = NULL;
  998. map<string, vector<FunctionBinding> >::const_iterator iter;
  999. for (unsigned int i = 0; i < c.derived.size(); i++)
  1000. {
  1001. // If the class is not in the map of classes, then
  1002. // it was marked to be ignored, so skip over it.
  1003. string derivedClassName = getIdentifier(c.derived[i]);
  1004. if (_classes.find(derivedClassName) == _classes.end())
  1005. continue;
  1006. cb = &_classes[derivedClassName];
  1007. // Go through this class' bindings and add them to the current
  1008. // derived class if they are not already there (excluding constructors and destructors).
  1009. for (iter = c.bindings.begin(); iter != c.bindings.end(); iter++)
  1010. {
  1011. FunctionBinding b(cb->classname, cb->uniquename);
  1012. b.type = iter->second[0].type;
  1013. b.name = iter->second[0].name;
  1014. map<string, vector<FunctionBinding> >::iterator findIter = cb->bindings.find(b.getFunctionName());
  1015. map<string, vector<FunctionBinding> >::iterator hiddenIter = cb->hidden.find(b.getFunctionName());
  1016. if (findIter == cb->bindings.end() && hiddenIter == cb->hidden.end())
  1017. {
  1018. for (unsigned int i = 0, iCount = iter->second.size(); i < iCount; i++)
  1019. {
  1020. if (iter->second[i].returnParam.type != FunctionBinding::Param::TYPE_CONSTRUCTOR &&
  1021. iter->second[i].returnParam.type != FunctionBinding::Param::TYPE_DESTRUCTOR)
  1022. {
  1023. // Copy the binding, but set its function name to
  1024. // empty so that it is regenerated correctly.
  1025. b = iter->second[i];
  1026. b.functionName = "";
  1027. b.classname = cb->classname;
  1028. b.uniquename = cb->uniquename;
  1029. cb->bindings[b.getFunctionName()].push_back(b);
  1030. }
  1031. }
  1032. }
  1033. else
  1034. {
  1035. bool addBinding;
  1036. for (unsigned int i = 0, iCount = iter->second.size(); i < iCount; i++)
  1037. {
  1038. string name = iter->second[i].name;
  1039. addBinding = true;
  1040. if (findIter != cb->bindings.end())
  1041. {
  1042. for (unsigned int j = 0, jCount = findIter->second.size(); j < jCount; j++)
  1043. {
  1044. if (FunctionBinding::signaturesMatch(iter->second[i], findIter->second[j]))
  1045. {
  1046. addBinding = false;
  1047. break;
  1048. }
  1049. }
  1050. // To call the base function, we have to qualify the call since
  1051. // the derived class has a function with the same name and different parameters.
  1052. if (addBinding)
  1053. name = iter->second[i].classname + string("::") + iter->second[i].name;
  1054. }
  1055. if (hiddenIter != cb->hidden.end())
  1056. {
  1057. for (unsigned int j = 0, jCount = hiddenIter->second.size(); j < jCount; j++)
  1058. {
  1059. if (FunctionBinding::signaturesMatch(iter->second[i], hiddenIter->second[j]))
  1060. {
  1061. addBinding = false;
  1062. break;
  1063. }
  1064. }
  1065. }
  1066. if (addBinding)
  1067. {
  1068. FunctionBinding b = iter->second[i];
  1069. b.name = name;
  1070. b.functionName = findIter->first;
  1071. b.classname = cb->classname;
  1072. b.uniquename = getUniqueName(cb->classname);
  1073. if (findIter != cb->bindings.end())
  1074. findIter->second.push_back(b);
  1075. else
  1076. cb->bindings[b.getFunctionName()].push_back(b);
  1077. }
  1078. }
  1079. }
  1080. }
  1081. derived.push_back(cb);
  1082. }
  1083. // Go through the derived classes' bindings and resolve the members for their derived classes.
  1084. for (unsigned int i = 0; i < derived.size(); i++)
  1085. {
  1086. resolveMembers(*derived[i]);
  1087. }
  1088. }
  1089. void Generator::resolveInheritance()
  1090. {
  1091. // Go through the class inheritance tree and update each class's bindings list
  1092. // to include the bindings from the base class that haven't been overridden.
  1093. for (unsigned int i = 0; i < _topLevelBaseClasses.size(); i++)
  1094. {
  1095. resolveMembers(_classes[_topLevelBaseClasses[i]]);
  1096. }
  1097. }
  1098. void Generator::resolveIncludes(const ClassBinding& c)
  1099. {
  1100. vector<ClassBinding*> derived;
  1101. // Go through the derived classes' bindings and update them.
  1102. ClassBinding* cb = NULL;
  1103. map<string, vector<FunctionBinding> >::const_iterator iter;
  1104. for (unsigned int i = 0; i < c.derived.size(); i++)
  1105. {
  1106. // If the class is not in the map of classes, then
  1107. // it was marked to be ignored, so skip over it.
  1108. string derivedClassName = getIdentifier(c.derived[i]);
  1109. if (_classes.find(derivedClassName) == _classes.end())
  1110. continue;
  1111. cb = &_classes[derivedClassName];
  1112. // Add all include files (uniquely) from the base class to the derived class.
  1113. map<string, set<string> >::iterator baseIncludes = _includes.find(c.include);
  1114. if (baseIncludes != _includes.end() && baseIncludes->second.size() > 0)
  1115. {
  1116. set<string>::iterator iter = baseIncludes->second.begin();
  1117. set<string>& derivedIncludes = _includes[cb->include];
  1118. for (; iter != baseIncludes->second.end(); iter++)
  1119. {
  1120. derivedIncludes.insert(*iter);
  1121. }
  1122. }
  1123. derived.push_back(cb);
  1124. }
  1125. // Go through the derived classes' bindings and resolve the members for their derived classes.
  1126. for (unsigned int i = 0; i < derived.size(); i++)
  1127. {
  1128. resolveIncludes(*derived[i]);
  1129. }
  1130. }
  1131. void Generator::resolveInheritedIncludes()
  1132. {
  1133. // Go through the class inheritance tree and update each class's
  1134. // list of includes to include the includes from the base class
  1135. for (unsigned int i = 0; i < _topLevelBaseClasses.size(); i++)
  1136. {
  1137. resolveIncludes(_classes[_topLevelBaseClasses[i]]);
  1138. }
  1139. }
  1140. void Generator::resolveType(FunctionBinding::Param* param, string functionName, string header)
  1141. {
  1142. string name = getIdentifier(param->info);
  1143. if (param->type == FunctionBinding::Param::TYPE_UNRECOGNIZED)
  1144. {
  1145. map<string, TypedefBinding>::iterator typedefIter = _typedefs.find(name);
  1146. if (typedefIter != _typedefs.end() && typedefIter->second.refId.size() > 0)
  1147. {
  1148. param->type = FunctionBinding::Param::TYPE_OBJECT;
  1149. param->info = typedefIter->second.refId;
  1150. }
  1151. else
  1152. {
  1153. map<string, ClassBinding>::iterator classIter = _classes.find(name);
  1154. if (classIter != _classes.end())
  1155. {
  1156. param->type = FunctionBinding::Param::TYPE_OBJECT;
  1157. }
  1158. else
  1159. {
  1160. map<string, EnumBinding>::iterator enumIter = _enums.find(name);
  1161. if (enumIter != _enums.end())
  1162. {
  1163. param->type = FunctionBinding::Param::TYPE_ENUM;
  1164. }
  1165. else
  1166. {
  1167. __warnings.insert(string("Unrecognized C++ type: ") + functionName + string(" -- ") + (name.size() > 0 ? name : param->info));
  1168. }
  1169. }
  1170. }
  1171. }
  1172. // Ensure that the header for the Lua enum conversion
  1173. // functions is included in the file containing the
  1174. // generated binding that this param/return value is part of.
  1175. if (param->type == FunctionBinding::Param::TYPE_ENUM)
  1176. {
  1177. string enumHeader = string("lua_") + getUniqueName(name) + string(".h");
  1178. if (_includes.find(header) != _includes.end())
  1179. {
  1180. set<string>& includes = _includes[header];
  1181. if (includes.find(enumHeader) == includes.end())
  1182. includes.insert(enumHeader);
  1183. }
  1184. else
  1185. {
  1186. _includes[header].insert(enumHeader);
  1187. }
  1188. }
  1189. }
  1190. void Generator::resolveTypes()
  1191. {
  1192. // Go through all member functions and attempt to resolve unrecognized types.
  1193. for (map<string, ClassBinding>::iterator iter = _classes.begin(); iter != _classes.end(); iter++)
  1194. {
  1195. map<string, vector<FunctionBinding> >::iterator functionNameIter = iter->second.bindings.begin();
  1196. for (; functionNameIter != iter->second.bindings.end(); functionNameIter++)
  1197. {
  1198. vector<FunctionBinding>::iterator functionIter = functionNameIter->second.begin();
  1199. for (; functionIter != functionNameIter->second.end(); functionIter++)
  1200. {
  1201. resolveType(&functionIter->returnParam, iter->first + string("::") + functionIter->name, iter->second.include);
  1202. vector<FunctionBinding::Param>::iterator paramIter = functionIter->paramTypes.begin();
  1203. for (; paramIter != functionIter->paramTypes.end(); paramIter++)
  1204. {
  1205. resolveType(&(*paramIter), iter->first + string("::") + functionIter->name, iter->second.include);
  1206. }
  1207. }
  1208. }
  1209. }
  1210. // Go through all non-member functions and attempt to resolve unrecognized types.
  1211. string globalHeader = string("lua_") + string(LUA_GLOBAL_FILENAME) + string(".h");
  1212. for (map<string, vector<FunctionBinding> >::iterator iter = _functions.begin(); iter != _functions.end(); iter++)
  1213. {
  1214. vector<FunctionBinding>::iterator functionIter = iter->second.begin();
  1215. for (; functionIter != iter->second.end(); functionIter++)
  1216. {
  1217. resolveType(&functionIter->returnParam, functionIter->name, globalHeader);
  1218. vector<FunctionBinding::Param>::iterator paramIter = functionIter->paramTypes.begin();
  1219. for (; paramIter != functionIter->paramTypes.end(); paramIter++)
  1220. {
  1221. resolveType(&(*paramIter), functionIter->name, globalHeader);
  1222. }
  1223. }
  1224. }
  1225. }
  1226. void Generator::generateBindings(string* bindingNS)
  1227. {
  1228. bool generatingGameplay = false;
  1229. if (bindingNS && (*bindingNS == "gameplay"))
  1230. generatingGameplay = true;
  1231. string luaAllHStr = _outDir + string(LUA_ALL_BINDINGS_FILENAME) + string(".h");
  1232. ofstream luaAllH(luaAllHStr.c_str());
  1233. string includeGuard = string(LUA_ALL_BINDINGS_FILENAME) + string("_H_");
  1234. transform(includeGuard.begin(), includeGuard.end(), includeGuard.begin(), ::toupper);
  1235. luaAllH << "#ifndef " << includeGuard << "\n";
  1236. luaAllH << "#define " << includeGuard << "\n\n";
  1237. string luaAllCppStr = _outDir + string(LUA_ALL_BINDINGS_FILENAME) + string(".cpp");
  1238. ofstream luaAllCpp(luaAllCppStr.c_str());
  1239. luaAllCpp << "#include \"Base.h\"\n";
  1240. luaAllCpp << "#include \"" << string(LUA_ALL_BINDINGS_FILENAME) << ".h\"\n\n";
  1241. if (bindingNS)
  1242. {
  1243. luaAllCpp << "namespace " << *bindingNS << "\n";
  1244. luaAllCpp << "{\n\n";
  1245. }
  1246. luaAllCpp << "void lua_RegisterAllBindings()\n";
  1247. luaAllCpp << "{\n";
  1248. // Write out all the class bindings.
  1249. if (_classes.size() > 0)
  1250. {
  1251. map<string, ClassBinding>::iterator iter = _classes.begin();
  1252. for (; iter != _classes.end(); iter++)
  1253. {
  1254. if (generatingGameplay || (!generatingGameplay && _namespaces["gameplay"].find(iter->second.classname) == _namespaces["gameplay"].end()))
  1255. {
  1256. cout << "Generating bindings for '" << iter->first << "'...\n";
  1257. iter->second.write(_outDir, _includes[iter->second.include], bindingNS);
  1258. luaAllH << "#include \"lua_" << iter->second.uniquename << ".h\"\n";
  1259. luaAllCpp << " luaRegister_" << iter->second.uniquename << "();\n";
  1260. }
  1261. }
  1262. }
  1263. // Go through all the classes and if they have any derived classes, add them to the list of base classes.
  1264. vector<string> baseClasses;
  1265. for (map<string, ClassBinding>::iterator iter = _classes.begin(); iter != _classes.end(); iter++)
  1266. {
  1267. if (iter->second.derived.size() > 0)
  1268. baseClasses.push_back(iter->first);
  1269. }
  1270. // Write out all the enum files.
  1271. if (_enums.size() > 0)
  1272. {
  1273. // Write out the enum conversion function declarations.
  1274. for (map<string, EnumBinding>::iterator iter = _enums.begin(); iter != _enums.end(); iter++)
  1275. {
  1276. if (generatingGameplay || (!generatingGameplay && _namespaces["gameplay"].find(iter->first) == _namespaces["gameplay"].end()))
  1277. {
  1278. cout << "Generating bindings for '" << iter->first << "'...\n";
  1279. // Header.
  1280. string enumHStr = _outDir + string("lua_") + getUniqueName(iter->first) + string(".h");
  1281. ofstream enumH(enumHStr.c_str());
  1282. includeGuard = string("lua_") + getUniqueName(iter->first) + string("_H_");
  1283. transform(includeGuard.begin(), includeGuard.end(), includeGuard.begin(), ::toupper);
  1284. enumH << "#ifndef " << includeGuard << "\n";
  1285. enumH << "#define " << includeGuard << "\n\n";
  1286. enumH << "#include \"" << iter->second.include << "\"\n\n";
  1287. if (bindingNS)
  1288. {
  1289. enumH << "namespace " << *bindingNS << "\n";
  1290. enumH << "{\n\n";
  1291. }
  1292. enumH << "// Lua bindings for enum conversion functions for " << iter->first << ".\n";
  1293. enumH << iter->first << " lua_enumFromString_" << getUniqueName(iter->first) << "(const char* s);\n";
  1294. enumH << "const char* lua_stringFromEnum_" << getUniqueName(iter->first) << "(" << iter->first << " e);\n\n";
  1295. if (bindingNS)
  1296. {
  1297. enumH << "}\n\n";
  1298. }
  1299. enumH << "#endif\n";
  1300. enumH.close();
  1301. // Implementation.
  1302. string enumCppStr = _outDir + string("lua_") + getUniqueName(iter->first) + string(".cpp");
  1303. ofstream enumCpp(enumCppStr.c_str());
  1304. enumCpp << "#include \"Base.h\"\n";
  1305. enumCpp << "#include \"lua_" << getUniqueName(iter->first) << ".h\"\n\n";
  1306. if (bindingNS)
  1307. {
  1308. enumCpp << "namespace " << *bindingNS << "\n";
  1309. enumCpp << "{\n\n";
  1310. }
  1311. enumCpp << "static const char* enumStringEmpty = \"\";\n\n";
  1312. // Build the scope string if applicable.
  1313. string scope;
  1314. if (iter->second.scopePath.size() > 0)
  1315. {
  1316. for (unsigned int i = 0; i < iter->second.scopePath.size(); i++)
  1317. {
  1318. scope += iter->second.scopePath[i] + string("::");
  1319. }
  1320. }
  1321. // Write out the string constants that correspond to the enumeration values.
  1322. for (unsigned int i = 0; i < iter->second.values.size(); i++)
  1323. {
  1324. enumCpp << "static const char* luaEnumString_" << getUniqueName(iter->first) << "_";
  1325. enumCpp << iter->second.values[i] << " = \"" << iter->second.values[i] << "\";\n";
  1326. }
  1327. enumCpp << "\n";
  1328. enumCpp << iter->first << " lua_enumFromString_" << getUniqueName(iter->first) << "(const char* s)\n";
  1329. enumCpp << "{\n";
  1330. for (unsigned int i = 0; i < iter->second.values.size(); i++)
  1331. {
  1332. enumCpp << " ";
  1333. enumCpp << "if (strcmp(s, luaEnumString_" << getUniqueName(iter->first) << "_" << iter->second.values[i] << ") == 0)\n";
  1334. enumCpp << " return ";
  1335. if (scope.size() > 0)
  1336. enumCpp << scope;
  1337. enumCpp << iter->second.values[i] << ";\n";
  1338. if (i == iter->second.values.size() - 1)
  1339. {
  1340. enumCpp << " GP_ERROR(\"Invalid enumeration value '%s' for enumeration " << iter->first << ".\", s);\n";
  1341. enumCpp << " return ";
  1342. if (scope.size() > 0)
  1343. enumCpp << scope;
  1344. enumCpp << iter->second.values[0] << ";\n";
  1345. }
  1346. }
  1347. enumCpp << "}\n\n";
  1348. enumCpp << "const char* lua_stringFromEnum_" << getUniqueName(iter->first) << "(" << iter->first << " e)\n";
  1349. enumCpp << "{\n";
  1350. // Write out the enum-to-string conversion code.
  1351. for (unsigned int i = 0; i < iter->second.values.size(); i++)
  1352. {
  1353. enumCpp << " ";
  1354. enumCpp << "if (e == ";
  1355. if (scope.size() > 0)
  1356. enumCpp << scope;
  1357. enumCpp << iter->second.values[i] << ")\n";
  1358. enumCpp << " return luaEnumString_" << getUniqueName(iter->first) << "_" << iter->second.values[i] << ";\n";
  1359. if (i == iter->second.values.size() - 1)
  1360. {
  1361. enumCpp << " GP_ERROR(\"Invalid enumeration value '%d' for enumeration " << iter->first << ".\", e);\n";
  1362. enumCpp << " return enumStringEmpty;\n";
  1363. }
  1364. }
  1365. enumCpp << "}\n\n";
  1366. if (bindingNS)
  1367. {
  1368. enumCpp << "}\n\n";
  1369. }
  1370. enumCpp.close();
  1371. }
  1372. }
  1373. }
  1374. // Write out the global bindings file.
  1375. cout << "Generating global bindings...\n";
  1376. if (baseClasses.size() > 0 || _functions.size() > 0 || _enums.size() > 0)
  1377. {
  1378. // Calculate if there are global function bindings to write out.
  1379. bool generateGlobalFunctionBindings = false;
  1380. if (_functions.size() > 0)
  1381. {
  1382. for (map<string, vector<FunctionBinding> >::iterator iter = _functions.begin(); iter != _functions.end(); iter++)
  1383. {
  1384. if (generatingGameplay || (!generatingGameplay && _namespaces["gameplay"].find(iter->second[0].name) == _namespaces["gameplay"].end()))
  1385. {
  1386. generateGlobalFunctionBindings = true;
  1387. break;
  1388. }
  1389. }
  1390. }
  1391. // Calculate if there are enum bindings to write out.
  1392. bool generateEnumBindings = false;
  1393. if (_enums.size() > 0)
  1394. {
  1395. for (map<string, EnumBinding>::iterator iter = _enums.begin(); iter != _enums.end(); iter++)
  1396. {
  1397. if (generatingGameplay || (!generatingGameplay && _namespaces["gameplay"].find(iter->first) == _namespaces["gameplay"].end()))
  1398. {
  1399. generateEnumBindings = true;
  1400. break;
  1401. }
  1402. }
  1403. }
  1404. // Write out the header file.
  1405. {
  1406. string path = _outDir + string(LUA_GLOBAL_FILENAME) + string(".h");
  1407. ofstream global(path.c_str());
  1408. includeGuard = string(LUA_GLOBAL_FILENAME) + string("_H_");
  1409. transform(includeGuard.begin(), includeGuard.end(), includeGuard.begin(), ::toupper);
  1410. global << "#ifndef " << includeGuard << "\n";
  1411. global << "#define " << includeGuard << "\n\n";
  1412. // Write out the needed includes for the global enumeration function.
  1413. for (map<string, EnumBinding>::iterator iter = _enums.begin(); iter != _enums.end(); iter++)
  1414. {
  1415. if (generatingGameplay || (!generatingGameplay && _namespaces["gameplay"].find(iter->first) == _namespaces["gameplay"].end()))
  1416. global << "#include \"lua_" << getUniqueName(iter->first) << ".h\"\n";
  1417. }
  1418. global << "\n";
  1419. luaAllH << "#include \"" << string(LUA_GLOBAL_FILENAME) << ".h\"\n";
  1420. luaAllCpp << " luaRegister_" << LUA_GLOBAL_FILENAME << "();\n";
  1421. if (bindingNS)
  1422. {
  1423. global << "namespace " << *bindingNS << "\n";
  1424. global << "{\n\n";
  1425. }
  1426. if (generateGlobalFunctionBindings)
  1427. {
  1428. global << "// Lua bindings for global functions.\n";
  1429. // Write out the binding function declarations.
  1430. for (map<string, vector<FunctionBinding> >::iterator iter = _functions.begin(); iter != _functions.end(); iter++)
  1431. {
  1432. if (generatingGameplay || (!generatingGameplay && _namespaces["gameplay"].find(iter->second[0].name) == _namespaces["gameplay"].end()))
  1433. global << "int " << iter->second[0].getFunctionName() << "(lua_State* state);\n";
  1434. }
  1435. global << "\n";
  1436. }
  1437. if (generateEnumBindings)
  1438. {
  1439. global << "// Global enum to string conversion function (used to pass enums to Lua from C++).\n";
  1440. global << "const char* lua_stringFromEnumGlobal(std::string& enumname, unsigned int value);\n\n";
  1441. }
  1442. // Write out the signature of the function used to register the global functions with Lua.
  1443. global << "void luaRegister_" << LUA_GLOBAL_FILENAME << "();\n\n";
  1444. if (bindingNS)
  1445. global << "}\n\n";
  1446. global << "#endif\n";
  1447. global.close();
  1448. }
  1449. // Write out the implementation.
  1450. {
  1451. string path = _outDir + string(LUA_GLOBAL_FILENAME) + string(".cpp");
  1452. ofstream global(path.c_str());
  1453. global << "#include \"ScriptController.h\"\n";
  1454. global << "#include \"" << LUA_GLOBAL_FILENAME << ".h\"\n";
  1455. map<string, set<string> >::iterator iter = _includes.find(string(LUA_GLOBAL_FILENAME) + string(".h"));
  1456. if (iter != _includes.end())
  1457. {
  1458. set<string>::iterator includeIter = iter->second.begin();
  1459. for (; includeIter != iter->second.end(); includeIter++)
  1460. {
  1461. global << "#include \"" << *includeIter << "\"\n";
  1462. }
  1463. }
  1464. global << "\n";
  1465. if (bindingNS)
  1466. {
  1467. global << "namespace " << *bindingNS << "\n";
  1468. global << "{\n\n";
  1469. }
  1470. // Write out the function used to register all global bindings with Lua.
  1471. global << "void luaRegister_" << LUA_GLOBAL_FILENAME << "()\n";
  1472. global << "{\n";
  1473. if (generateGlobalFunctionBindings)
  1474. {
  1475. // Bind the non-member functions.
  1476. for (map<string, vector<FunctionBinding> >::iterator iter = _functions.begin(); iter != _functions.end(); iter++)
  1477. {
  1478. if (generatingGameplay || (!generatingGameplay && _namespaces["gameplay"].find(iter->second[0].name) == _namespaces["gameplay"].end()))
  1479. global << " ScriptUtil::registerFunction(\"" << iter->second[0].name << "\", " << iter->second[0].getFunctionName() << ");\n";
  1480. }
  1481. }
  1482. // Generate the hierarchy map.
  1483. if (baseClasses.size() > 0)
  1484. {
  1485. for (unsigned int i = 0, count = baseClasses.size(); i < count; i++)
  1486. {
  1487. set<string> derived;
  1488. getAllDerived(derived, baseClasses[i]);
  1489. for (set<string>::iterator iter = derived.begin(); iter != derived.end(); iter++)
  1490. {
  1491. if (generatingGameplay || (!generatingGameplay && _namespaces["gameplay"].find(*iter) == _namespaces["gameplay"].end()))
  1492. global << " ScriptUtil::setGlobalHierarchyPair(\"" << baseClasses[i] << "\", \"" << *iter << "\");\n";
  1493. }
  1494. }
  1495. }
  1496. // Register all enums.
  1497. if (generateEnumBindings)
  1498. {
  1499. global << " ScriptUtil::addStringFromEnumConversionFunction(&";
  1500. if (bindingNS)
  1501. global << *bindingNS << "::";
  1502. global << "lua_stringFromEnumGlobal);\n";
  1503. for (map<string, EnumBinding>::iterator iter = _enums.begin(); iter != _enums.end(); iter++)
  1504. {
  1505. if (generatingGameplay || (!generatingGameplay && _namespaces["gameplay"].find(iter->first) == _namespaces["gameplay"].end()))
  1506. {
  1507. global << "\n // Register enumeration " << iter->first << ".\n";
  1508. global << " {\n";
  1509. global << " std::vector<std::string> scopePath;\n";
  1510. for (unsigned int i = 0; i < iter->second.scopePath.size(); i++)
  1511. {
  1512. global << " scopePath.push_back(\"" << iter->second.scopePath[i] << "\");\n";
  1513. }
  1514. vector<string>::iterator enumIter = iter->second.values.begin();
  1515. for (; enumIter != iter->second.values.end(); enumIter++)
  1516. {
  1517. global << " ScriptUtil::registerConstantString(\"" << *enumIter << "\", \"" << *enumIter << "\", scopePath);\n";
  1518. }
  1519. global << " }\n";
  1520. }
  1521. }
  1522. }
  1523. global << "}\n\n";
  1524. // Write out the binding functions.
  1525. if (generateGlobalFunctionBindings)
  1526. {
  1527. for (map<string, vector<FunctionBinding> >::iterator iter = _functions.begin(); iter != _functions.end(); iter++)
  1528. {
  1529. if (generatingGameplay || (!generatingGameplay && _namespaces["gameplay"].find(iter->second[0].name) == _namespaces["gameplay"].end()))
  1530. FunctionBinding::write(global, iter->second);
  1531. }
  1532. }
  1533. // Write out the global enum conversion function (used to pass enums from C++ to Lua).
  1534. if (generateEnumBindings)
  1535. {
  1536. global << "static const char* enumStringEmpty = \"\";\n\n";
  1537. global << "const char* lua_stringFromEnumGlobal(std::string& enumname, unsigned int value)\n";
  1538. global << "{\n";
  1539. for (map<string, EnumBinding>::iterator iter = _enums.begin(); iter != _enums.end(); iter++)
  1540. {
  1541. if (generatingGameplay || (!generatingGameplay && _namespaces["gameplay"].find(iter->first) == _namespaces["gameplay"].end()))
  1542. {
  1543. global << " if (enumname == \"";
  1544. global << iter->first << "\")\n";
  1545. global << " return lua_stringFromEnum_" << getUniqueName(iter->first) << "((" << iter->first << ")value);\n";
  1546. }
  1547. }
  1548. global << "\n";
  1549. global << " GP_ERROR(\"Unrecognized enumeration type '%s'.\", enumname.c_str());\n";
  1550. global << " return enumStringEmpty;\n";
  1551. global << "}\n\n";
  1552. }
  1553. if (bindingNS)
  1554. global << "}\n";
  1555. global.close();
  1556. }
  1557. }
  1558. luaAllCpp << "}\n\n";
  1559. if (bindingNS)
  1560. luaAllCpp << "}\n\n";
  1561. luaAllCpp.close();
  1562. if (bindingNS)
  1563. {
  1564. luaAllH << "\nnamespace " << *bindingNS << "\n";
  1565. luaAllH << "{\n\n";
  1566. }
  1567. luaAllH << "void lua_RegisterAllBindings();\n\n";
  1568. if (bindingNS)
  1569. luaAllH<< "}\n\n";
  1570. luaAllH << "#endif\n";
  1571. luaAllH.close();
  1572. }
  1573. void Generator::getAllDerived(set<string>& derived, string classname)
  1574. {
  1575. for (unsigned int i = 0, count = _classes[classname].derived.size(); i < count; i++)
  1576. {
  1577. // If the derived class is not in the ref ID table, then it
  1578. // is a hidden (protected, private, etc.) class, so don't include it.
  1579. if (_refIds.find(_classes[classname].derived[i]) != _refIds.end())
  1580. {
  1581. string derivedClassName = getIdentifier(_classes[classname].derived[i]);
  1582. derived.insert(derivedClassName);
  1583. getAllDerived(derived, derivedClassName);
  1584. }
  1585. }
  1586. }
  1587. void Generator::getIncludes(XMLElement* e, string filename)
  1588. {
  1589. filename.replace(filename.find(".cpp"), 4, ".h");
  1590. for (e = e->FirstChildElement("includes"); e; e = e->NextSiblingElement("includes"))
  1591. {
  1592. if (e->Attribute("refid"))
  1593. _includes[filename].insert(e->GetText());
  1594. }
  1595. }
  1596. // ----------------------------------------------------------------------------
  1597. // Utility functions
  1598. static string trim(const string& str)
  1599. {
  1600. string s = str;
  1601. while (isspace(s[0]))
  1602. {
  1603. s.erase(s.begin());
  1604. }
  1605. while (isspace(s[s.size() - 1]))
  1606. {
  1607. s.erase(s.begin() + s.size() - 1);
  1608. }
  1609. return s;
  1610. }
  1611. static string stripTypeQualifiers(const string& typeStr, FunctionBinding::Param::Kind& kind)
  1612. {
  1613. string type = typeStr;
  1614. kind = FunctionBinding::Param::KIND_VALUE;
  1615. // Check if the type is a reference.
  1616. string::size_type i = type.find("&");
  1617. if (i != type.npos)
  1618. {
  1619. kind = FunctionBinding::Param::KIND_REFERENCE;
  1620. type.erase(type.begin() + i);
  1621. }
  1622. // Check if the type is a pointer.
  1623. i = type.find("*");
  1624. if (i != type.npos)
  1625. {
  1626. kind = FunctionBinding::Param::KIND_POINTER;
  1627. type.erase(type.begin() + i);
  1628. }
  1629. // Ignore const qualifiers.
  1630. i = type.find("const ");
  1631. if (i != type.npos)
  1632. {
  1633. type.erase(type.begin() + i, type.begin() + i + 6);
  1634. }
  1635. return trim(type);
  1636. }
  1637. static inline bool isWantedFileNormal(const string& s)
  1638. {
  1639. if (s.find(".xml") == s.size() - 4)
  1640. {
  1641. if (s.find("class") == 0 || s.find("struct") == 0 ||
  1642. (s.find("_") == 0 && (s.find("h.xml") != s.npos || s.find("cpp.xml") != s.npos)))
  1643. return true;
  1644. }
  1645. return false;
  1646. }
  1647. static inline bool isNamespaceFile(const string& s)
  1648. {
  1649. if (s.find(".xml") == s.size() - 4)
  1650. {
  1651. if (s.find("namespace") == 0)
  1652. return true;
  1653. }
  1654. return false;
  1655. }
  1656. static inline bool isGeneratedBindingFile(const string& s)
  1657. {
  1658. return ( (s.find(".cpp") == s.size() - 4) || (s.find(".h") == s.size() - 2) );
  1659. }
  1660. static bool getFileList(string directory, vector<string>& files, bool (*isWantedFile)(const string& s))
  1661. {
  1662. #ifdef WIN32
  1663. string path = directory + string("/*");
  1664. // Convert char to wchar.
  1665. basic_string<TCHAR> wPath;
  1666. wPath.assign(path.begin(), path.end());
  1667. WIN32_FIND_DATA FindFileData;
  1668. HANDLE hFind = FindFirstFile(wPath.c_str(), &FindFileData);
  1669. if (hFind == INVALID_HANDLE_VALUE)
  1670. {
  1671. return false;
  1672. }
  1673. do
  1674. {
  1675. // Add to the list if this is not a directory and it passes the test function.
  1676. if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
  1677. {
  1678. // Convert wchar to char.
  1679. basic_string<TCHAR> wfilename(FindFileData.cFileName);
  1680. string filename;
  1681. filename.assign(wfilename.begin(), wfilename.end());
  1682. if (isWantedFile(filename))
  1683. {
  1684. filename = string(directory) + string("/") + filename;
  1685. files.push_back(filename);
  1686. }
  1687. }
  1688. } while (FindNextFile(hFind, &FindFileData) != 0);
  1689. FindClose(hFind);
  1690. return true;
  1691. #else
  1692. string path = directory + string("/.");
  1693. struct dirent* dp;
  1694. DIR* dir = opendir(path.c_str());
  1695. if (!dir)
  1696. {
  1697. return false;
  1698. }
  1699. while ((dp = readdir(dir)) != NULL)
  1700. {
  1701. string filepath(path);
  1702. filepath.append("/");
  1703. filepath.append(dp->d_name);
  1704. struct stat buf;
  1705. if (!stat(filepath.c_str(), &buf))
  1706. {
  1707. // Add to the list if this is not a directory and it passes the test function.
  1708. if (!S_ISDIR(buf.st_mode))
  1709. {
  1710. string filename = dp->d_name;
  1711. if (isWantedFile(filename))
  1712. {
  1713. filename = string(directory) + string("/") + filename;
  1714. files.push_back(filename);
  1715. }
  1716. }
  1717. }
  1718. }
  1719. closedir(dir);
  1720. return true;
  1721. #endif
  1722. }
  1723. bool isReservedKeyword(string name)
  1724. {
  1725. static set<string> keywords;
  1726. if (keywords.size() == 0)
  1727. {
  1728. keywords.insert("and");
  1729. keywords.insert("break");
  1730. keywords.insert("do");
  1731. keywords.insert("else");
  1732. keywords.insert("elseif");
  1733. keywords.insert("end");
  1734. keywords.insert("false");
  1735. keywords.insert("for");
  1736. keywords.insert("function");
  1737. keywords.insert("if");
  1738. keywords.insert("in");
  1739. keywords.insert("local");
  1740. keywords.insert("nil");
  1741. keywords.insert("not");
  1742. keywords.insert("or");
  1743. keywords.insert("repeat");
  1744. keywords.insert("return");
  1745. keywords.insert("then");
  1746. keywords.insert("true");
  1747. keywords.insert("until");
  1748. keywords.insert("while");
  1749. };
  1750. return keywords.find(name) != keywords.end();
  1751. }
  1752. // ----------------------------------------------------------------------------