/tools/fbusgen/fbusgen.c

http://ftk.googlecode.com/ · C · 844 lines · 665 code · 115 blank · 64 comment · 151 complexity · 1fcc429f6f023d65ab87a479a64567cb MD5 · raw file

  1. /*
  2. * File:
  3. * Author: Li XianJing <xianjimli@hotmail.com>
  4. * Brief:
  5. *
  6. * Copyright (c) 2009 - 2010 Li XianJing <xianjimli@hotmail.com>
  7. *
  8. * Licensed under the Academic Free License version 2.1
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23. */
  24. /*
  25. * History:
  26. * ================================================================
  27. * 2010-07-31 Li XianJing <xianjimli@hotmail.com> created
  28. *
  29. */
  30. /*
  31. * File: luagen.c
  32. * Author: Li XianJing <xianjimli@hotmail.com>
  33. * Brief: a code generator to generate lua glue functions.
  34. *
  35. * Copyright (c) 2009 - 2010 Li XianJing <xianjimli@hotmail.com>
  36. *
  37. * Licensed under the Academic Free License version 2.1
  38. *
  39. * This program is free software; you can redistribute it and/or modify
  40. * it under the terms of the GNU General Public License as published by
  41. * the Free Software Foundation; either version 2 of the License, or
  42. * (at your option) any later version.
  43. *
  44. * This program is distributed in the hope that it will be useful,
  45. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  46. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  47. * GNU General Public License for more details.
  48. *
  49. * You should have received a copy of the GNU General Public License
  50. * along with this program; if not, write to the Free Software
  51. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  52. */
  53. /*
  54. * History:
  55. * ================================================================
  56. * 2010-03-07 Li XianJing <xianjimli@hotmail.com> created
  57. *
  58. */
  59. #include <stdio.h>
  60. #include <ctype.h>
  61. #include <assert.h>
  62. #include <stdlib.h>
  63. #include <string.h>
  64. #include <libIDL/IDL.h>
  65. #define STR_LENGTH 256
  66. typedef struct
  67. {
  68. FILE* h;
  69. FILE* c;
  70. IDL_ns ns;
  71. IDL_tree tree;
  72. GString* str_init;
  73. GString* str_types;
  74. GString* str_const;
  75. GString* str_funcs;
  76. char interface[STR_LENGTH+1];
  77. char interface_lower[STR_LENGTH+1];
  78. }CodeGenInfo;
  79. #define G_STRING_FREE(str) if(str != NULL){g_string_free(str, 1); str = NULL;}
  80. static gboolean lua_code_gen_end_interface(CodeGenInfo *info);
  81. static void code_gen_info_reset(CodeGenInfo* info)
  82. {
  83. G_STRING_FREE(info->str_types);
  84. G_STRING_FREE(info->str_funcs);
  85. G_STRING_FREE(info->str_init);
  86. G_STRING_FREE(info->str_const);
  87. if(info->h != NULL && info->h != stdout)
  88. {
  89. fclose(info->h);
  90. info->h = NULL;
  91. }
  92. if(info->c != NULL && info->c != stdout)
  93. {
  94. fclose(info->c);
  95. info->c = NULL;
  96. }
  97. return;
  98. }
  99. static char* name_to_upper(const char* src, char* dst, int skip)
  100. {
  101. int i = 0;
  102. int j = 0;
  103. dst[0] = toupper(src[0]);
  104. for(i = 1, j = 1; src[i]; i++)
  105. {
  106. if(src[i] == '_')
  107. {
  108. continue;
  109. }
  110. else if(src[i-1] == '_')
  111. {
  112. dst[j++] = toupper(src[i]);
  113. }
  114. else
  115. {
  116. dst[j++] = src[i];
  117. }
  118. }
  119. dst[j] = '\0';
  120. return dst + skip;
  121. }
  122. static const char* name_to_lower(const char* src, char* dst)
  123. {
  124. int i = 0;
  125. int j = 0;
  126. for(i = 0, j = 0; src[i] != '\0'; i++, j++)
  127. {
  128. if(isupper(src[i]))
  129. {
  130. if(i > 0)
  131. {
  132. dst[j++] = '_';
  133. }
  134. }
  135. dst[j] = tolower(src[i]);
  136. }
  137. dst[j] = '\0';
  138. return dst;
  139. }
  140. static void code_gen_info_init(CodeGenInfo* info, const char* intf)
  141. {
  142. const char* name = intf;
  143. char filename[260] = {0};
  144. code_gen_info_reset(info);
  145. info->str_types = g_string_sized_new(4096);
  146. info->str_funcs = g_string_sized_new(8192);
  147. info->str_init = g_string_sized_new(4096);
  148. info->str_const = g_string_sized_new(4096);
  149. strncpy(info->interface, name, sizeof(info->interface));
  150. name_to_lower(name, info->interface_lower);
  151. snprintf(filename, sizeof(filename), "lua_%s.h", info->interface_lower);
  152. info->h = fopen(filename, "w+");
  153. if(info->h == NULL) info->h = stdout;
  154. snprintf(filename, sizeof(filename), "lua_%s.c", info->interface_lower);
  155. info->c = fopen(filename, "w+");
  156. if(info->c == NULL) info->c = stdout;
  157. return;
  158. }
  159. static gboolean lua_code_gen_begin_interface(const char* name, const char* parent, CodeGenInfo *info)
  160. {
  161. char parent_lower[STR_LENGTH+1] = {0};
  162. /*close last interface*/
  163. if(info->interface[0] && info->c != NULL && info->h != NULL)
  164. {
  165. lua_code_gen_end_interface(info);
  166. }
  167. if(parent != NULL)
  168. {
  169. name_to_lower(parent, parent_lower);
  170. }
  171. code_gen_info_init(info, name);
  172. g_string_append_printf(info->str_init, "int tolua_%s_init(lua_State* L)\n", info->interface_lower);
  173. g_string_append(info->str_init, "{\n");
  174. g_string_append(info->str_init, " tolua_open(L);\n");
  175. g_string_append(info->str_init, " tolua_reg_types(L);\n");
  176. g_string_append(info->str_init, " tolua_module(L, NULL, 0);\n");
  177. g_string_append_printf(info->str_init, " tolua_beginmodule(L, NULL);\n");
  178. if(!info->only_globals)
  179. {
  180. g_string_append_printf(info->str_init, " tolua_cclass(L,\"%s\", \"%s\", \"%s\", NULL);\n",
  181. info->interface, info->interface, parent);
  182. g_string_append_printf(info->str_init, " tolua_beginmodule(L, \"%s\");\n", info->interface);
  183. }
  184. g_string_append(info->str_types, "static void tolua_reg_types (lua_State* L)\n{\n");
  185. if(!info->only_globals)
  186. {
  187. g_string_append_printf(info->str_types, " tolua_usertype(L, \"%s\");\n", info->interface);
  188. }
  189. fprintf(info->h, "/*This file is generated by luagen.*/\n");
  190. fprintf(info->h, "#include \"ftk.h\"\n");
  191. fprintf(info->h, "#include \"tolua++.h\"\n");
  192. fprintf(info->h, "#include \"%s.h\"\n", info->interface_lower);
  193. if(parent_lower[0])
  194. {
  195. fprintf(info->h, "#include \"lua_%s.h\"\n\n", parent_lower);
  196. }
  197. else
  198. {
  199. fprintf(info->h, "\n");
  200. }
  201. fprintf(info->h, "#ifndef LUA_%s_H\n", info->interface);
  202. fprintf(info->h, "#define LUA_%s_H\n\n", info->interface);
  203. if(parent != NULL && parent[0])
  204. {
  205. fprintf(info->h, "typedef %s %s;\n", parent, name);
  206. }
  207. fprintf(info->h, "int tolua_%s_init(lua_State* L);\n", info->interface_lower);
  208. fprintf(info->c, "/*This file is generated by luagen.*/\n");
  209. fprintf(info->c, "#include \"lua_%s.h\"\n", info->interface_lower);
  210. fprintf(info->c, "#include \"lua_ftk_callbacks.h\"\n\n");
  211. return TRUE;
  212. }
  213. static gboolean lua_code_gen_end_interface(CodeGenInfo *info)
  214. {
  215. if(info->interface[0])
  216. {
  217. if(!info->only_globals)
  218. {
  219. g_string_append_printf(info->str_init, " tolua_endmodule(L);\n");
  220. }
  221. else
  222. {
  223. g_string_append(info->str_init, info->str_const->str);
  224. }
  225. g_string_append_printf(info->str_init, " tolua_endmodule(L);\n\n");
  226. g_string_append_printf(info->str_init, "\n return 1;\n");
  227. g_string_append_printf(info->str_init, "}\n");
  228. g_string_append(info->str_types, "}\n\n");
  229. fprintf(info->c, "%s", info->str_types->str);
  230. fprintf(info->c, "%s", info->str_funcs->str);
  231. fprintf(info->c, "%s", info->str_init->str);
  232. fprintf(info->h, "\n#endif/*LUA_%s_H*/\n\n", info->interface);
  233. }
  234. return TRUE;
  235. }
  236. typedef struct _TypeInfo
  237. {
  238. gboolean is_function;
  239. gboolean is_userdata;
  240. char name[STR_LENGTH+1];
  241. char lua_name[STR_LENGTH+1];
  242. char check[STR_LENGTH+1];
  243. char pop[STR_LENGTH+1];
  244. char push[STR_LENGTH+1];
  245. char free[STR_LENGTH+1];
  246. char orignal_name[STR_LENGTH+1];
  247. }TypeInfo;
  248. static void int_type_init(TypeInfo* info)
  249. {
  250. memset(info, 0x00, sizeof(TypeInfo));
  251. strcpy(info->name , "int");
  252. strcpy(info->lua_name , "lua_Number");
  253. strcpy(info->check , "tolua_isnumber(L, %d, 0, &err)");
  254. strcpy(info->pop , "tolua_tonumber");
  255. strcpy(info->push , " tolua_pushnumber(L, (lua_Number)retv);\n");
  256. strcpy(info->free , "");
  257. return;
  258. }
  259. static void ret_type_init(TypeInfo* info)
  260. {
  261. memset(info, 0x00, sizeof(TypeInfo));
  262. strcpy(info->name , "Ret");
  263. strcpy(info->lua_name , "lua_Number");
  264. strcpy(info->check , "tolua_isnumber(L, %d, 0, &err)");
  265. strcpy(info->pop , "tolua_tonumber");
  266. strcpy(info->push , " tolua_pushnumber(L, (lua_Number)retv);\n");
  267. strcpy(info->free , "");
  268. return;
  269. }
  270. static void str_type_init(TypeInfo* info)
  271. {
  272. memset(info, 0x00, sizeof(TypeInfo));
  273. strcpy(info->name , "char*");
  274. strcpy(info->lua_name , "char*");
  275. strcpy(info->check , "tolua_isstring(L, %d, 0, &err)");
  276. strcpy(info->pop , "(char*)tolua_tostring");
  277. strcpy(info->push , " tolua_pushstring(L, (char*)retv);\n");
  278. strcpy(info->free , "");
  279. return;
  280. }
  281. static void func_type_init(const char* name, TypeInfo* info)
  282. {
  283. memset(info, 0x00, sizeof(TypeInfo));
  284. info->is_function = 1;
  285. strcpy(info->name , "char*");
  286. strcpy(info->lua_name , "void*");
  287. strcpy(info->check , "tolua_isstring(L, %d, 0, &err)");
  288. strcpy(info->pop , "(char*)tolua_tostring");
  289. strcpy(info->push , " assert(!\"not supported\");\n");
  290. strcpy(info->free , "");
  291. return;
  292. }
  293. static void str_array_type_init(TypeInfo* info)
  294. {
  295. memset(info, 0x00, sizeof(TypeInfo));
  296. strcpy(info->name , "char**");
  297. strcpy(info->lua_name , "char**");
  298. strcpy(info->check , "tolua_istable(L, %d, 0, &err)");
  299. strcpy(info->pop , "tolua_tostrings");
  300. strcpy(info->push , " assert(!\"not supported\");\n");
  301. strcpy(info->free , " free(%s);\n");
  302. return;
  303. }
  304. static void userdata_type_init(const char* name, TypeInfo* info)
  305. {
  306. memset(info, 0x00, sizeof(TypeInfo));
  307. char usertype[STR_LENGTH+1] = {0};
  308. strcpy(usertype, name);
  309. strcpy(info->name , name);
  310. strcpy(info->lua_name , "void*");
  311. strcpy(info->check , "tolua_isusertype(L, %d, \"");
  312. strcat(info->check , name);
  313. strcat(info->check , "\", 0, &err)");
  314. snprintf(info->pop, sizeof(info->pop), "*(%s*)tolua_tousertype", name);
  315. sprintf(info->push, " {%s* copy=malloc(sizeof(%s)); if(copy != NULL) memcpy(copy, &retv, sizeof(%s));tolua_pushusertype_and_takeownership(L, (%s*)copy, \"%s\");}\n",
  316. info->name, info->name, info->name, info->name, usertype);
  317. strcpy(info->free , "");
  318. return;
  319. }
  320. static void userdata_light_type_init(const char* name, TypeInfo* info)
  321. {
  322. char* ptr = NULL;
  323. char usertype[STR_LENGTH+1] = {0};
  324. memset(info, 0x00, sizeof(TypeInfo));
  325. strcpy(info->name , name);
  326. ptr = strstr(info->name, "Ptr");
  327. strcpy(ptr, "*");
  328. ptr = strstr(name, "Ptr");
  329. strncpy(usertype, name, ptr-name);
  330. strcpy(info->lua_name , "void*");
  331. strcpy(info->check , "tolua_isusertype(L, %d, \"");
  332. strncat(info->check, name, ptr - name);
  333. strcat(info->check , "\", 0, &err)");
  334. strcpy(info->pop , "tolua_tousertype");
  335. sprintf(info->push, " tolua_pushusertype(L, (%s)retv, \"%s\");\n",
  336. info->name, usertype);
  337. strcpy(info->free , "");
  338. return;
  339. }
  340. static gboolean is_pointer(const char* str)
  341. {
  342. const char* ptr = strstr(str, "Ptr");
  343. return ptr != NULL && strlen(ptr) == 3;
  344. }
  345. static gboolean is_function(const char* str)
  346. {
  347. const char* ptr = strstr(str, "Func");
  348. return ptr != NULL && strlen(ptr) == 4;
  349. }
  350. static int get_type_info(IDL_tree type, TypeInfo* info)
  351. {
  352. if(IDL_NODE_IS_TYPE(type))
  353. {
  354. switch(IDL_NODE_TYPE(type))
  355. {
  356. case IDLN_TYPE_INTEGER:
  357. {
  358. int_type_init(info);
  359. break;
  360. }
  361. case IDLN_TYPE_STRING:
  362. {
  363. /*TODO*/
  364. break;
  365. }
  366. case IDLN_TYPE_CHAR:
  367. {
  368. /*TODO*/
  369. break;
  370. }
  371. case IDLN_TYPE_BOOLEAN:
  372. {
  373. /*TODO*/
  374. break;
  375. }
  376. case IDLN_TYPE_FLOAT:
  377. {
  378. /*TODO*/
  379. break;
  380. }
  381. default:break;
  382. }
  383. }
  384. else if(IDL_NODE_TYPE(type) == IDLN_IDENT)
  385. {
  386. const char* type_str = IDL_IDENT(type).str;
  387. if(strcmp(type_str, "StrPtr") == 0 || strcmp(type_str, "CStrPtr") == 0)
  388. {
  389. str_type_init(info);
  390. }
  391. else if(strcmp(type_str, "StrArray") == 0 || strcmp(type_str, "CStrArray") == 0)
  392. {
  393. str_array_type_init(info);
  394. }
  395. else if(is_pointer(type_str))
  396. {
  397. char* p = NULL;
  398. userdata_light_type_init(type_str, info);
  399. }
  400. else if(is_function(type_str))
  401. {
  402. func_type_init(type_str, info);
  403. }
  404. else if(strcmp(type_str, "Ret") == 0)
  405. {
  406. ret_type_init(info);
  407. }
  408. else if(strcmp(type_str, "int") == 0
  409. || strcmp(type_str, "uint") == 0
  410. || strcmp(type_str, "size_t") == 0
  411. || strcmp(type_str, "short") == 0
  412. || strcmp(type_str, "ushort") == 0
  413. || strcmp(type_str, "char") == 0
  414. || strcmp(type_str, "uchar") == 0
  415. || strcmp(type_str, "long") == 0
  416. || strcmp(type_str, "ulong") == 0 )
  417. {
  418. int_type_init(info);
  419. }
  420. else
  421. {
  422. userdata_type_init(type_str, info);
  423. info->is_userdata = TRUE;
  424. }
  425. strcpy(info->orignal_name, type_str);
  426. }
  427. return 0;
  428. }
  429. static gboolean lua_code_gen_on_func_decl(struct _IDL_OP_DCL func, CodeGenInfo *info)
  430. {
  431. int i = 0;
  432. char new_name[64] = {0};
  433. TypeInfo type_info = {0};
  434. struct _IDL_LIST iter = {0};
  435. gboolean is_static_func = FALSE;
  436. GString* call = g_string_sized_new(512);
  437. GString* retv = g_string_sized_new(512);
  438. GString* param_get = g_string_sized_new(512);
  439. GString* param_decl = g_string_sized_new(512);
  440. GString* param_free = g_string_sized_new(512);
  441. GString* param_check = g_string_sized_new(512);
  442. const char* func_name = IDL_IDENT(func.ident).str;
  443. if(func.op_type_spec != NULL)
  444. {
  445. get_type_info(func.op_type_spec, &type_info);
  446. g_string_append_printf(call, " retv = %s(", func_name);
  447. g_string_append_printf(param_decl, " %s retv;\n", type_info.name);
  448. g_string_append_printf(retv, type_info.push, type_info.lua_name, type_info.name);
  449. }
  450. else
  451. {
  452. g_string_append_printf(call, " %s(", func_name);
  453. }
  454. g_string_append_printf(info->str_funcs, "static int lua_%s(lua_State* L)\n", func_name);
  455. g_string_append(info->str_funcs, "{\n");
  456. if(func.parameter_dcls != NULL)
  457. {
  458. for (i = 1, iter = IDL_LIST(func.parameter_dcls); iter.data != NULL; iter = IDL_LIST(iter.next))
  459. {
  460. const char* param_name = NULL;
  461. int attr = IDL_PARAM_DCL(iter.data).attr;
  462. get_type_info(IDL_PARAM_DCL(iter.data).param_type_spec, &type_info);
  463. param_name = IDL_IDENT(IDL_PARAM_DCL(iter.data).simple_declarator).str;
  464. if(i == 1)
  465. {
  466. is_static_func = strcmp(param_name, "thiz)") != 0;
  467. }
  468. else
  469. {
  470. if(attr != IDL_PARAM_OUT)
  471. {
  472. g_string_append_printf(param_check, " && ");
  473. }
  474. g_string_append(call, ", ");
  475. }
  476. g_string_append_printf(param_decl, " %s %s;\n", type_info.name, param_name);
  477. g_string_append_printf(param_free, type_info.free, param_name);
  478. if(attr == IDL_PARAM_OUT)
  479. {
  480. g_string_append_printf(call, "&%s", param_name);
  481. g_string_append_printf(retv, type_info.push, type_info.lua_name, type_info.name);
  482. }
  483. else
  484. {
  485. if(type_info.is_function)
  486. {
  487. char func_name[STR_LENGTH+1] = {0};
  488. g_string_append_printf(call, "lua_%s, %s", name_to_lower(type_info.orignal_name, func_name), param_name);
  489. }
  490. else
  491. {
  492. g_string_append_printf(call, "%s", param_name);
  493. }
  494. g_string_append_printf(param_check, type_info.check, i);
  495. g_string_append_printf(param_get, " %s = %s(L, %d, 0);\n", param_name, type_info.pop, i);
  496. i++;
  497. }
  498. if(iter.next == NULL) break;
  499. }
  500. }
  501. else
  502. {
  503. is_static_func = TRUE;
  504. }
  505. g_string_append(call, ");\n");
  506. if(i > 1)
  507. {
  508. g_string_append_printf(info->str_funcs, " tolua_Error err = {0};\n", param_check->str);
  509. }
  510. g_string_append(info->str_funcs, param_decl->str);
  511. if(i > 1)
  512. {
  513. g_string_append_printf(info->str_funcs, " int param_ok = %s;\n", param_check->str);
  514. g_string_append(info->str_funcs, "\n return_val_if_fail(param_ok, 0);\n\n");
  515. }
  516. g_string_append(info->str_funcs, param_get->str);
  517. g_string_append(info->str_funcs, call->str);
  518. g_string_append(info->str_funcs, retv->str);
  519. g_string_append(info->str_funcs, param_free->str);
  520. g_string_append_printf(info->str_funcs, "\n return 1;\n}\n\n", param_check->str);
  521. g_string_append_printf(info->str_init, " tolua_function(L, \"%s\", lua_%s);\n",
  522. name_to_upper(func_name, new_name, strlen(info->interface)), func_name);
  523. g_string_free(call, 1);
  524. g_string_free(retv, 1);
  525. g_string_free(param_free, 1);
  526. g_string_free(param_decl, 1);
  527. g_string_free(param_check, 1);
  528. g_string_free(param_get, 1);
  529. return FALSE;
  530. }
  531. static gboolean lua_code_gen_on_const(struct _IDL_CONST_DCL constant, CodeGenInfo *info)
  532. {
  533. if(IDL_NODE_TYPE (constant.const_type) == IDLN_TYPE_INTEGER)
  534. {
  535. const char* name = IDL_IDENT(constant.ident).str;
  536. g_string_append_printf(info->str_const, " tolua_constant(L, \"%s\", %s);\n", name, name);
  537. }
  538. return FALSE;
  539. }
  540. static void lua_code_gen_get_func(CodeGenInfo *info, const char* name, TypeInfo* type_info, const char* var)
  541. {
  542. g_string_append_printf(info->str_funcs, "static int tolua_get_%s_%s(lua_State* L)\n", name, var);
  543. g_string_append(info->str_funcs, "{\n");
  544. g_string_append_printf(info->str_funcs, " %s retv;\n", type_info->lua_name);
  545. g_string_append_printf(info->str_funcs, " %s* thiz = (%s*) tolua_tousertype(L, 1, 0);\n", name, name);
  546. g_string_append(info->str_funcs, " return_val_if_fail(thiz != NULL, 0);\n");
  547. if(type_info->is_userdata)
  548. {
  549. g_string_append_printf(info->str_funcs, " retv = (%s)&(thiz->%s);\n", type_info->lua_name, var);
  550. }
  551. else
  552. {
  553. g_string_append_printf(info->str_funcs, " retv = (%s)thiz->%s;\n", type_info->lua_name, var);
  554. }
  555. g_string_append_printf(info->str_funcs, type_info->push, type_info->lua_name);
  556. g_string_append(info->str_funcs, "\n return 1;\n");
  557. g_string_append(info->str_funcs, "}\n\n");
  558. return;
  559. }
  560. static void lua_code_gen_set_func(CodeGenInfo *info, const char* name, TypeInfo* type_info, const char* var)
  561. {
  562. g_string_append_printf(info->str_funcs, "static int tolua_set_%s_%s(lua_State* L)\n", name, var);
  563. g_string_append(info->str_funcs, "{\n");
  564. g_string_append_printf(info->str_funcs, " %s* thiz = (%s*) tolua_tousertype(L, 1, 0);\n", name, name);
  565. g_string_append(info->str_funcs, " return_val_if_fail(thiz != NULL, 0);\n");
  566. g_string_append_printf(info->str_funcs, " thiz->%s = (%s) (%s(L, 2, 0));\n", var, type_info->name, type_info->pop);
  567. g_string_append(info->str_funcs, "\n return 1;\n");
  568. g_string_append(info->str_funcs, "}\n\n");
  569. return;
  570. }
  571. static gboolean lua_code_gen_on_struct(struct _IDL_TYPE_STRUCT s, CodeGenInfo *info)
  572. {
  573. struct _IDL_LIST iter = {0};
  574. char lower_name[STR_LENGTH+1] = {0};
  575. const char* name = IDL_IDENT(s.ident).str;
  576. if(!info->only_globals)
  577. {
  578. return FALSE;
  579. }
  580. name_to_lower(name, lower_name);
  581. g_string_append_printf(info->str_types, " tolua_usertype(L, \"%s\");\n", name);
  582. g_string_append_printf(info->str_init, " tolua_cclass(L, \"%s\", \"%s\", \"\", NULL);\n",
  583. name, name);
  584. g_string_append_printf(info->str_funcs, "int lua_%s_create(lua_State* L)\n", lower_name);
  585. g_string_append_printf(info->str_funcs, "{\n");
  586. g_string_append_printf(info->str_funcs, " %s* retv = calloc(1, sizeof(%s));\n", name, name);
  587. g_string_append_printf(info->str_funcs, " tolua_pushusertype_and_takeownership(L, (void*)retv, \"%s\");\n\n", name);
  588. g_string_append_printf(info->str_funcs, " return 1;\n}\n\n");
  589. g_string_append_printf(info->str_init, " tolua_beginmodule(L, \"%s\");\n", name);
  590. g_string_append_printf(info->str_init, " tolua_function(L, \"Create\", lua_%s_create);\n", lower_name);
  591. for (iter = IDL_LIST(s.member_list); iter.data != NULL; iter = IDL_LIST(iter.next))
  592. {
  593. TypeInfo type_info = {0};
  594. const char* var = NULL;
  595. struct _IDL_MEMBER member = IDL_MEMBER(iter.data);
  596. get_type_info(member.type_spec, &type_info);
  597. var = IDL_IDENT(IDL_LIST(member.dcls).data).str;
  598. lua_code_gen_get_func(info, name, &type_info, var);
  599. lua_code_gen_set_func(info, name, &type_info, var);
  600. g_string_append_printf(info->str_init, " tolua_variable(L, \"%s\",tolua_get_%s_%s, tolua_set_%s_%s);\n",
  601. var, name, var, name, var);
  602. if(iter.next == NULL) break;
  603. }
  604. g_string_append_printf(info->str_init, " tolua_endmodule(L);\n");
  605. return FALSE;
  606. }
  607. static gboolean lua_code_gen_on_enum(struct _IDL_TYPE_ENUM e, CodeGenInfo *info)
  608. {
  609. struct _IDL_LIST iter = {0};
  610. if(!info->only_globals)
  611. {
  612. return FALSE;
  613. }
  614. for (iter = IDL_LIST(e.enumerator_list); iter.data != NULL; iter = IDL_LIST(iter.next))
  615. {
  616. const char* name = IDL_IDENT(iter.data).str;
  617. g_string_append_printf(info->str_const, " tolua_constant(L, \"%s\", %s);\n", name, name);
  618. if(iter.next == NULL) break;
  619. }
  620. return FALSE;
  621. }
  622. static gboolean lua_code_gen_on_union(struct _IDL_TYPE_UNION u, CodeGenInfo *info)
  623. {
  624. struct _IDL_LIST iter = {0};
  625. if(!info->only_globals)
  626. {
  627. return FALSE;
  628. }
  629. /*TODO*/
  630. return FALSE;
  631. }
  632. static gboolean lua_gen_code(IDL_tree_func_data *tfd, CodeGenInfo *info)
  633. {
  634. IDL_tree p = tfd->tree;
  635. if (IDL_NODE_TYPE (p) == IDLN_INTERFACE)
  636. {
  637. const char* parent = "";
  638. struct _IDL_INTERFACE intf = IDL_INTERFACE(p);
  639. const char* name = IDL_IDENT(intf.ident).str;
  640. if(intf.inheritance_spec != NULL)
  641. {
  642. struct _IDL_LIST list = IDL_LIST(intf.inheritance_spec);
  643. parent = IDL_IDENT(list.data).str;
  644. }
  645. return lua_code_gen_begin_interface(name, parent, info);
  646. }
  647. else if(IDL_NODE_TYPE (p) == IDLN_OP_DCL)
  648. {
  649. return lua_code_gen_on_func_decl(IDL_OP_DCL(p), info);
  650. }
  651. else if(IDL_NODE_TYPE (p) == IDLN_CONST_DCL)
  652. {
  653. return lua_code_gen_on_const(IDL_CONST_DCL(p), info);
  654. }
  655. else if(IDL_NODE_TYPE(p) == IDLN_TYPE_STRUCT)
  656. {
  657. return lua_code_gen_on_struct(IDL_TYPE_STRUCT(p), info);
  658. }
  659. else if(IDL_NODE_TYPE(p) == IDLN_TYPE_ENUM)
  660. {
  661. return lua_code_gen_on_enum(IDL_TYPE_ENUM(p), info);
  662. }
  663. else if(IDL_NODE_TYPE(p) == IDLN_TYPE_UNION)
  664. {
  665. return lua_code_gen_on_union(IDL_TYPE_UNION(p), info);
  666. }
  667. return TRUE;
  668. }
  669. static gboolean fbus_gen_intf_end(CodeGenInfo *info)
  670. {
  671. return TRUE;
  672. }
  673. static gboolean fbus_gen_intf(IDL_tree_func_data *tfd, CodeGenInfo *info)
  674. {
  675. }
  676. int main (int argc, char *argv[])
  677. {
  678. int rv = 0;
  679. IDL_ns ns = {0};
  680. IDL_tree tree = {0};
  681. CodeGenInfo info = {0};
  682. const char* type = NULL;
  683. const char* filename = NULL;
  684. unsigned long parse_flags = 0;
  685. IDL_check_cast_enable (TRUE);
  686. if (argc < 3 || (type = strstr(argv[1], "-type=")) == NULL)
  687. {
  688. fprintf (stderr, "usage: %s -type=intf|proxy|service|xxx idl \n", argv[0]);
  689. exit (1);
  690. }
  691. filename = argv[2];
  692. rv = IDL_parse_filename (filename, NULL, NULL, &tree, &ns, parse_flags, IDL_WARNING1);
  693. if (rv == IDL_ERROR)
  694. {
  695. g_message ("IDL_ERROR: %s\n", filename);
  696. exit (1);
  697. }
  698. else if (rv < 0)
  699. {
  700. perror (filename);
  701. exit (1);
  702. }
  703. info.ns = ns;
  704. info.tree = tree;
  705. if(strcmp(type, "intf") == 0)
  706. {
  707. IDL_tree_walk_in_order (tree, (IDL_tree_func)fbus_gen_intf, &info);
  708. fbus_gen_intf_end(&info);
  709. }
  710. else if(strcmp(type, "proxy") == 0)
  711. {
  712. IDL_tree_walk_in_order (tree, (IDL_tree_func)fbus_gen_proxy, &info);
  713. fbus_gen_proxy_end(&info);
  714. }
  715. else if(strcmp(type, "service") == 0)
  716. {
  717. IDL_tree_walk_in_order (tree, (IDL_tree_func)fbus_gen_service, &info);
  718. fbus_gen_service_end(&info);
  719. }
  720. else
  721. {
  722. IDL_tree_walk_in_order (tree, (IDL_tree_func)fbus_gen_impl, &info);
  723. fbus_gen_impl_end(&info);
  724. }
  725. IDL_ns_free (ns);
  726. IDL_tree_free (tree);
  727. code_gen_info_reset(&info);
  728. return 0;
  729. }