PageRenderTime 462ms CodeModel.GetById 81ms app.highlight 231ms RepoModel.GetById 141ms app.codeStats 0ms

/tools/fbusgen/fbusgen.c

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