1/* -----------------------------------------------------------------------------
2 * See the LICENSE file for information on copyright, usage and redistribution
3 * of SWIG, and the README file for authors - http://www.swig.org/release.html.
4 *
5 * lua.cxx
6 *
7 * Lua language module for SWIG.
8 * ----------------------------------------------------------------------------- */
9
10/* NEW LANGUAGE NOTE:
11 * ver001
12   this is simply a copy of tcl8.cxx, which has been renamed
13 * ver002
14   all non essential code commented out, program now does virtually nothing
15   it prints to stderr the list of functions to wrap, but does not create
16   the XXX_wrap.c file
17 * ver003
18   added back top(), still prints the list of fns to stderr
19   but now creates a rather empty XXX_wrap.c with some basic boilerplate code
20 * ver004
21   very basic version of functionWrapper()
22   also uncommented usage_string() to keep compiler happy
23   this will start producing proper looking code soon (I hope)
24   produced the wrapper code, but without any type conversion (in or out)
25   generates a few warning because of no wrappering
26   does not generate SWIG_init()
27   reason for this is that lua.swg is empty
28   we will need to add code into this to make it work
29 * ver005/6
30   massive rework, basing work on the pike module instead of tcl
31   (pike module it only 1/3 of the size)(though not as complete)
32 * ver007
33   added simple type checking
34 * ver008
35   INPUT, OUTPUT, INOUT typemaps handled (though not all types yet)
36 * ver009
37   class support: ok for basic types, but methods still TDB
38   (code is VERY messed up & needs to be cleaned)
39
40
41*/
42
43char cvsroot_lua_cxx[] = "$Id: lua.cxx 11133 2009-02-20 07:52:24Z wsfulton $";
44
45#include "swigmod.h"
46
47/**** Diagnostics:
48  With the #define REPORT(), you can change the amount of diagnostics given
49  This helps me search the parse tree & figure out what is going on inside SWIG
50  (because its not clear or documented)
51*/
52#define REPORT(T,D)		// no info:
53//#define REPORT(T,D)   {Printf(stdout,T"\n");} // only title
54//#define REPORT(T,D)		{Printf(stdout,T" %p\n",n);} // title & pointer
55//#define REPORT(T,D)   {Printf(stdout,T"\n");display_mapping(D);}      // the works
56//#define REPORT(T,D)   {Printf(stdout,T"\n");if(D)Swig_print_node(D);}      // the works
57
58void display_mapping(DOH *d) {
59  if (d == 0 || !DohIsMapping(d))
60    return;
61  for (DohIterator it = DohFirst(d); it.item; it = DohNext(it)) {
62    if (DohIsString(it.item))
63      Printf(stdout, "  %s = %s\n", it.key, it.item);
64    else if (DohIsMapping(it.item))
65      Printf(stdout, "  %s = <mapping>\n", it.key);
66    else if (DohIsSequence(it.item))
67      Printf(stdout, "  %s = <sequence>\n", it.key);
68    else
69      Printf(stdout, "  %s = <unknown>\n", it.key);
70  }
71}
72
73
74
75/* NEW LANGUAGE NOTE:***********************************************
76 most of the default options are handled by SWIG
77 you can add new ones here
78 (though for now I have not bothered)
79NEW LANGUAGE NOTE:END ************************************************/
80static const char *usage = (char *) "\
81                           Lua Options (available with -lua)\n\
82                           (coming soon.)\n\n";
83
84
85
86/* NEW LANGUAGE NOTE:***********************************************
87 To add a new language, you need to derive your class from
88 Language and the overload various virtual functions
89 (more on this as I figure it out)
90NEW LANGUAGE NOTE:END ************************************************/
91
92class LUA:public Language {
93private:
94
95  File *f_begin;
96  File *f_runtime;
97  File *f_header;
98  File *f_wrappers;
99  File *f_init;
100  File *f_initbeforefunc;
101  String *PrefixPlusUnderscore;
102  String *s_cmd_tab;		// table of command names
103  String *s_var_tab;		// table of global variables
104  String *s_const_tab;		// table of global constants
105  String *s_methods_tab;	// table of class methods
106  String *s_attr_tab;		// table of class atributes
107  String *s_luacode;		// luacode to be called during init
108
109  int have_constructor;
110  int have_destructor;
111  String *destructor_action;
112  String *class_name;
113  String *constructor_name;
114
115  enum {
116    NO_CPP,
117    VARIABLE,
118    MEMBER_FUNC,
119    CONSTRUCTOR,
120    DESTRUCTOR,
121    MEMBER_VAR,
122    CLASS_CONST,
123    STATIC_FUNC,
124    STATIC_VAR
125  }current;
126
127public:
128
129  /* ---------------------------------------------------------------------
130   * LUA()
131   *
132   * Initialize member data
133   * --------------------------------------------------------------------- */
134
135  LUA() {
136    f_begin = 0;
137    f_runtime = 0;
138    f_header = 0;
139    f_wrappers = 0;
140    f_init = 0;
141    f_initbeforefunc = 0;
142    PrefixPlusUnderscore = 0;
143
144    s_cmd_tab = s_var_tab = s_const_tab = s_luacode = 0;
145    current=NO_CPP;
146  }
147
148  /* NEW LANGUAGE NOTE:***********************************************
149     This is called to initalise the system & read any command line args
150     most of this is boilerplate code, except the command line args
151     which depends upon what args your code supports
152     NEW LANGUAGE NOTE:END ************************************************/
153
154  /* ---------------------------------------------------------------------
155  * main()
156  *
157  * Parse command line options and initializes variables.
158  * --------------------------------------------------------------------- */
159
160  virtual void main(int argc, char *argv[]) {
161
162    /* Set location of SWIG library */
163    SWIG_library_directory("lua");
164
165    /* Look for certain command line options */
166    for (int i = 1; i < argc; i++) {
167      if (argv[i]) {
168        if (strcmp(argv[i], "-help") == 0) {	// usage flags
169          fputs(usage, stderr);
170        }
171      }
172    }
173
174    /* NEW LANGUAGE NOTE:***********************************************
175     This is the boilerplate code, setting a few #defines
176     and which lib directory to use
177     the SWIG_library_directory() is also boilerplate code
178     but it always seems to be the first line of code
179    NEW LANGUAGE NOTE:END ************************************************/
180    /* Add a symbol to the parser for conditional compilation */
181    Preprocessor_define("SWIGLUA 1", 0);
182
183    /* Set language-specific configuration file */
184    SWIG_config_file("lua.swg");
185
186    /* Set typemap language */
187    SWIG_typemap_lang("lua");
188
189    /* Enable overloaded methods support */
190    allow_overloading();
191  }
192
193
194
195
196  /* NEW LANGUAGE NOTE:***********************************************
197   After calling main, SWIG parses the code to wrap (I believe)
198   then calls top()
199   in this is more boilerplate code to set everything up
200   and a call to Language::top()
201   which begins the code generations by calling the member fns
202   after all that is more boilerplate code to close all down
203   (overall there is virtually nothing here that needs to be edited
204   just use as is)
205  NEW LANGUAGE NOTE:END ************************************************/
206  /* ---------------------------------------------------------------------
207   * top()
208   * --------------------------------------------------------------------- */
209
210  virtual int top(Node *n) {
211    /* Get the module name */
212    String *module = Getattr(n, "name");
213
214    /* Get the output file name */
215    String *outfile = Getattr(n, "outfile");
216
217    /* Open the output file */
218    f_begin = NewFile(outfile, "w", SWIG_output_files());
219    if (!f_begin) {
220      FileErrorDisplay(outfile);
221      SWIG_exit(EXIT_FAILURE);
222    }
223    f_runtime = NewString("");
224    f_init = NewString("");
225    f_header = NewString("");
226    f_wrappers = NewString("");
227    f_initbeforefunc = NewString("");
228
229    /* Register file targets with the SWIG file handler */
230    Swig_register_filebyname("header", f_header);
231    Swig_register_filebyname("wrapper", f_wrappers);
232    Swig_register_filebyname("begin", f_begin);
233    Swig_register_filebyname("runtime", f_runtime);
234    Swig_register_filebyname("init", f_init);
235    Swig_register_filebyname("initbeforefunc", f_initbeforefunc);
236
237    /* NEW LANGUAGE NOTE:***********************************************
238     s_cmd_tab,s_var_tab & s_const_tab hold the names of the fns for
239     registering with SWIG.
240     These will be filled in when the functions/variables are wrapped &
241     then added to the end of the wrappering code
242     just before it is written to file
243    NEW LANGUAGE NOTE:END ************************************************/
244    // Initialize some variables for the object interface
245    s_cmd_tab = NewString("");
246    s_var_tab = NewString("");
247    //    s_methods_tab    = NewString("");
248    s_const_tab = NewString("");
249
250    s_luacode = NewString("");
251    Swig_register_filebyname("luacode", s_luacode);
252
253    current=NO_CPP;
254
255    /* Standard stuff for the SWIG runtime section */
256    Swig_banner(f_begin);
257
258    Printf(f_runtime, "\n");
259    Printf(f_runtime, "#define SWIGLUA\n");
260
261    //    if (NoInclude) {
262    //      Printf(f_runtime, "#define SWIG_NOINCLUDE\n");
263    //    }
264
265    Printf(f_runtime, "\n");
266
267    //String *init_name = NewStringf("%(title)s_Init", module);
268    //Printf(f_header, "#define SWIG_init    %s\n", init_name);
269    //Printf(f_header, "#define SWIG_name    \"%s\"\n", module);
270    /* SWIG_import is a special function name for importing within Lua5.1 */
271    //Printf(f_header, "#define SWIG_import  luaopen_%s\n\n", module);
272    Printf(f_header, "#define SWIG_name      \"%s\"\n", module);
273    Printf(f_header, "#define SWIG_init      luaopen_%s\n", module);
274    Printf(f_header, "#define SWIG_init_user luaopen_%s_user\n\n", module);
275    Printf(f_header, "#define SWIG_LUACODE   luaopen_%s_luacode\n\n", module);
276
277    Printf(s_cmd_tab, "\nstatic const struct luaL_reg swig_commands[] = {\n");
278    Printf(s_var_tab, "\nstatic swig_lua_var_info swig_variables[] = {\n");
279    Printf(s_const_tab, "\nstatic swig_lua_const_info swig_constants[] = {\n");
280    Printf(f_wrappers, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n");
281
282    /* %init code inclusion, effectively in the SWIG_init function */
283    Printf(f_init, "void SWIG_init_user(lua_State* L)\n{\n");
284    Language::top(n);
285    Printf(f_init,"/* exec Lua code if applicable */\nSWIG_Lua_dostring(L,SWIG_LUACODE);\n");
286    Printf(f_init, "}\n");
287
288    Printf(f_wrappers, "#ifdef __cplusplus\n}\n#endif\n");
289
290    // Done.  Close up the module & write to the wrappers
291    Printv(s_cmd_tab, tab4, "{0,0}\n", "};\n", NIL);
292    Printv(s_var_tab, tab4, "{0,0,0}\n", "};\n", NIL);
293    Printv(s_const_tab, tab4, "{0,0,0,0,0,0}\n", "};\n", NIL);
294    Printv(f_wrappers, s_cmd_tab, s_var_tab, s_const_tab, NIL);
295    SwigType_emit_type_table(f_runtime, f_wrappers);
296
297    /* NEW LANGUAGE NOTE:***********************************************
298     this basically combines several of the strings together
299     and then writes it all to a file
300    NEW LANGUAGE NOTE:END ************************************************/
301    Dump(f_runtime, f_begin);
302    Dump(f_header, f_begin);
303    Dump(f_wrappers, f_begin);
304    Dump(f_initbeforefunc, f_begin);
305    /* for the Lua code it needs to be properly excaped to be added into the C/C++ code */
306    EscapeCode(s_luacode);
307    Printf(f_begin, "const char* SWIG_LUACODE=\n  \"%s\";\n\n",s_luacode);
308    Wrapper_pretty_print(f_init, f_begin);
309    /* Close all of the files */
310    Delete(s_luacode);
311    Delete(s_cmd_tab);
312    Delete(s_var_tab);
313    Delete(s_const_tab);
314    Delete(f_header);
315    Delete(f_wrappers);
316    Delete(f_init);
317    Delete(f_initbeforefunc);
318    Close(f_begin);
319    Delete(f_runtime);
320    Delete(f_begin);
321
322    /* Done */
323    return SWIG_OK;
324  }
325
326  /* ------------------------------------------------------------
327   * importDirective()
328   * ------------------------------------------------------------ */
329
330  virtual int importDirective(Node *n) {
331    return Language::importDirective(n);
332  }
333
334  /* NEW LANGUAGE NOTE:***********************************************
335   This is it!
336   you get this one right, and most of your work is done
337   but its going to take soem file to get it working right
338   quite a bit of this is generally boilerplate code
339   (or stuff I dont understand)
340   that which matters will have extra added comments
341  NEW LANGUAGE NOTE:END ************************************************/
342  /* ---------------------------------------------------------------------
343   * functionWrapper()
344   *
345   * Create a function declaration and register it with the interpreter.
346   * --------------------------------------------------------------------- */
347
348  virtual int functionWrapper(Node *n) {
349    REPORT("functionWrapper",n);
350
351    String *name = Getattr(n, "name");
352    String *iname = Getattr(n, "sym:name");
353    SwigType *d = Getattr(n, "type");
354    ParmList *l = Getattr(n, "parms");
355    //Printf(stdout,"functionWrapper %s %s\n",name,iname);
356    Parm *p;
357    String *tm;
358    int i;
359    //Printf(stdout,"functionWrapper %s %s %d\n",name,iname,current);
360    //    int returnval=0;  // number of arguments returned
361
362    String *overname = 0;
363    if (Getattr(n, "sym:overloaded")) {
364      overname = Getattr(n, "sym:overname");
365    } else {
366      if (!addSymbol(iname, n)) {
367        Printf(stderr,"addSymbol(%s) failed\n",iname);
368        return SWIG_ERROR;
369      }
370    }
371
372    /* NEW LANGUAGE NOTE:***********************************************
373       the wrapper object holds all the wrappering code
374        we need to add a couple of local variables
375    NEW LANGUAGE NOTE:END ************************************************/
376    Wrapper *f = NewWrapper();
377    Wrapper_add_local(f, "SWIG_arg", "int SWIG_arg = 0");
378
379
380    String *wname = Swig_name_wrapper(iname);
381    if (overname) {
382      Append(wname, overname);
383    }
384
385    /* NEW LANGUAGE NOTE:***********************************************
386       the format of a lua fn is:
387         static int wrap_XXX(lua_State* L){...}
388       this line adds this into the wrappering code
389    NEW LANGUAGE NOTE:END ************************************************/
390    Printv(f->def, "static int ", wname, "(lua_State* L) {", NIL);
391
392    /* NEW LANGUAGE NOTE:***********************************************
393       this prints the list of args, eg for a C fn
394       int gcd(int x,int y);
395       it will print
396         int arg1;
397         int arg2;
398    NEW LANGUAGE NOTE:END ************************************************/
399    /* Write code to extract function parameters. */
400    emit_parameter_variables(l, f);
401
402    /* Attach the standard typemaps */
403    emit_attach_parmmaps(l, f);
404    Setattr(n, "wrap:parms", l);
405
406    /* Get number of required and total arguments */
407    int num_arguments = emit_num_arguments(l);
408    int num_required = emit_num_required(l);
409    int varargs = emit_isvarargs(l);
410
411    // Check if we have to ignore arguments that are passed by LUA.
412    // Needed for unary minus, where lua passes two arguments and
413    // we have to ignore the second.
414
415    int args_to_ignore = 0;
416    if (Getattr(n, "lua:ignore_args")) {
417      args_to_ignore = GetInt(n, "lua:ignore_args");
418    }
419
420
421    /* Which input argument to start with? */
422    //    int start = (current == MEMBER_FUNC || current == MEMBER_VAR || current == DESTRUCTOR) ? 1 : 0;
423
424    /* Offset to skip over the attribute name */
425    // int offset = (current == MEMBER_VAR) ? 1 : 0;
426
427    /* NEW LANGUAGE NOTE:***********************************************
428       from here on in, it gets rather hairy
429       this is the code to convert from the scripting language to C/C++
430       some of the stuff will refer to the typemaps code written in your swig file
431       (lua.swg), and some is done in the code here
432       I suppose you could do all the conversion on C, but it would be a nightmare to do
433    NEW LANGUAGE NOTE:END ************************************************/
434    /* Generate code for argument marshalling */
435    //    String *description = NewString("");
436    /* NEW LANGUAGE NOTE:***********************************************
437       argument_check is a new feature I added to check types of arguments:
438       eg for int gcd(int,int)
439       I want to check that arg1 & arg2 really are integers
440    NEW LANGUAGE NOTE:END ************************************************/
441    String *argument_check = NewString("");
442    String *argument_parse = NewString("");
443    String *checkfn = NULL;
444    //    String *numoutputs=NULL;
445    char source[64];
446    //Printf(argument_check, "SWIG_check_num_args(\"%s\",%d,%d)\n",name,num_required,num_arguments);
447    Printf(argument_check, "SWIG_check_num_args(\"%s\",%d,%d)\n",name,num_required+args_to_ignore,num_arguments+args_to_ignore);
448
449    for (i = 0, p = l; i < num_arguments; i++) {
450
451      while (checkAttribute(p, "tmap:in:numinputs", "0")) {
452        p = Getattr(p, "tmap:in:next");
453      }
454
455      SwigType *pt = Getattr(p, "type");
456      String *ln = Getattr(p, "lname");
457
458      /* Look for an input typemap */
459      sprintf(source, "%d", i + 1);
460      if ((tm = Getattr(p, "tmap:in"))) {
461        Replaceall(tm, "$source", source);
462        Replaceall(tm, "$target", ln);
463        Replaceall(tm, "$input", source);
464        Setattr(p, "emit:input", source);
465        if (Getattr(p, "wrap:disown") || (Getattr(p, "tmap:in:disown"))) {
466          Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN");
467        } else {
468          Replaceall(tm, "$disown", "0");
469        }
470        /* NEW LANGUAGE NOTE:***********************************************
471           look for a 'checkfn' typemap
472           this an additional parameter added to the in typemap
473           if found the type will be tested for
474           this will result in code either in the
475           argument_check or argument_parse string
476        NEW LANGUAGE NOTE:END ************************************************/
477        if ((checkfn = Getattr(p, "tmap:in:checkfn"))) {
478          if (i < num_required) {
479            Printf(argument_check, "if(!%s(L,%s))", checkfn, source);
480          } else {
481            Printf(argument_check, "if(lua_gettop(L)>=%s && !%s(L,%s))", source, checkfn, source);
482          }
483          Printf(argument_check, " SWIG_fail_arg(\"%s\",%s,\"%s\");\n", name, source, SwigType_str(pt, 0));
484        }
485        /* NEW LANGUAGE NOTE:***********************************************
486           lua states the number of arguments passed to a function using the fn
487           lua_gettop()
488           we can use this to deal with default arguments
489        NEW LANGUAGE NOTE:END ************************************************/
490        if (i < num_required) {
491          Printf(argument_parse, "%s\n", tm);
492        } else {
493          Printf(argument_parse, "if(lua_gettop(L)>=%s){%s}\n", source, tm);
494        }
495        p = Getattr(p, "tmap:in:next");
496        continue;
497      } else {
498        /* NEW LANGUAGE NOTE:***********************************************
499        		   // why is this code not called when I dont have a typemap?
500        		   // instead of giving a warning, no code is generated
501        NEW LANGUAGE NOTE:END ************************************************/
502        Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
503        break;
504      }
505    }
506
507    // add all argcheck code
508    Printv(f->code, argument_check, argument_parse, NIL);
509
510    /* Check for trailing varargs */
511    if (varargs) {
512      if (p && (tm = Getattr(p, "tmap:in"))) {
513        Replaceall(tm, "$input", "varargs");
514        Printv(f->code, tm, "\n", NIL);
515      }
516    }
517
518    /* Insert constraint checking code */
519    for (p = l; p;) {
520      if ((tm = Getattr(p, "tmap:check"))) {
521        Replaceall(tm, "$target", Getattr(p, "lname"));
522        Printv(f->code, tm, "\n", NIL);
523        p = Getattr(p, "tmap:check:next");
524      } else {
525        p = nextSibling(p);
526      }
527    }
528
529    /* Insert cleanup code */
530    String *cleanup = NewString("");
531    for (p = l; p;) {
532      if ((tm = Getattr(p, "tmap:freearg"))) {
533        Replaceall(tm, "$source", Getattr(p, "lname"));
534        Printv(cleanup, tm, "\n", NIL);
535        p = Getattr(p, "tmap:freearg:next");
536      } else {
537        p = nextSibling(p);
538      }
539    }
540
541    /* Insert argument output code */
542    String *outarg = NewString("");
543    for (p = l; p;) {
544      if ((tm = Getattr(p, "tmap:argout"))) {
545        //          // managing the number of returning variables
546        //        if (numoutputs=Getattr(p,"tmap:argout:numoutputs")){
547        //                      int i=GetInt(p,"tmap:argout:numoutputs");
548        //                      printf("got argout:numoutputs of %d\n",i);
549        //                      returnval+=GetInt(p,"tmap:argout:numoutputs");
550        //        }
551        //        else returnval++;
552        Replaceall(tm, "$source", Getattr(p, "lname"));
553        Replaceall(tm, "$target", "result");
554        Replaceall(tm, "$arg", Getattr(p, "emit:input"));
555        Replaceall(tm, "$input", Getattr(p, "emit:input"));
556        Printv(outarg, tm, "\n", NIL);
557        p = Getattr(p, "tmap:argout:next");
558      } else {
559        p = nextSibling(p);
560      }
561    }
562
563    Setattr(n, "wrap:name", wname);
564
565    /* Emit the function call */
566    String *actioncode = emit_action(n);
567
568    /* NEW LANGUAGE NOTE:***********************************************
569    FIXME:
570    returns 1 if there is a void return type
571    this is because there is a typemap for void
572    NEW LANGUAGE NOTE:END ************************************************/
573    // Return value if necessary
574    if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) {
575      // managing the number of returning variables
576      //      if (numoutputs=Getattr(tm,"numoutputs")){
577      //              int i=GetInt(tm,"numoutputs");
578      //              printf("return numoutputs %d\n",i);
579      //              returnval+=GetInt(tm,"numoutputs");
580      //      }
581      //        else returnval++;
582      Replaceall(tm, "$source", "result");
583      if (GetFlag(n, "feature:new")) {
584        Replaceall(tm, "$owner", "1");
585      } else {
586        Replaceall(tm, "$owner", "0");
587      }
588      Printf(f->code, "%s\n", tm);
589      //      returnval++;
590    } else {
591      Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(d, 0), name);
592    }
593    emit_return_variable(n, d, f);
594
595    /* Output argument output code */
596    Printv(f->code, outarg, NIL);
597
598    /* Output cleanup code */
599    Printv(f->code, cleanup, NIL);
600
601    /* Look to see if there is any newfree cleanup code */
602    if (GetFlag(n, "feature:new")) {
603      if ((tm = Swig_typemap_lookup("newfree", n, "result", 0))) {
604        Replaceall(tm, "$source", "result");
605        Printf(f->code, "%s\n", tm);
606      }
607    }
608
609    /* See if there is any return cleanup code */
610    if ((tm = Swig_typemap_lookup("ret", n, "result", 0))) {
611      Replaceall(tm, "$source", "result");
612      Printf(f->code, "%s\n", tm);
613    }
614
615
616    /* Close the function */
617    Printv(f->code, "return SWIG_arg;\n", NIL);
618    // add the failure cleanup code:
619    Printv(f->code, "\nif(0) SWIG_fail;\n", NIL);
620    Printv(f->code, "\nfail:\n", NIL);
621    Printv(f->code, "$cleanup", "lua_error(L);\n", NIL);
622    Printv(f->code, "return SWIG_arg;\n", NIL);
623    Printf(f->code, "}\n");
624
625    /* Substitute the cleanup code */
626    Replaceall(f->code, "$cleanup", cleanup);
627
628    /* Substitute the function name */
629    Replaceall(f->code, "$symname", iname);
630    Replaceall(f->code, "$result", "result");
631
632    /* Dump the function out */
633    /* in Lua we will not emit the destructor as a wrappered function,
634    Lua will automatically call the destructor when the object is free'd
635    However: you cannot just skip this function as it will not emit
636    any custom destructor (using %extend), as you need to call emit_action()
637    Therefore we go though the whole function,
638    but do not write the code into the wrapper
639    */
640    if(current!=DESTRUCTOR) {
641       Wrapper_print(f, f_wrappers);
642    }
643
644    /* NEW LANGUAGE NOTE:***********************************************
645    register the function in SWIG
646    different language mappings seem to use different ideas
647    NEW LANGUAGE NOTE:END ************************************************/
648    /* Now register the function with the interpreter. */
649    if (!Getattr(n, "sym:overloaded")) {
650      //      add_method(n, iname, wname, description);
651      if (current==NO_CPP || current==STATIC_FUNC) // emit normal fns & static fns
652        Printv(s_cmd_tab, tab4, "{ \"", iname, "\", ", Swig_name_wrapper(iname), "},\n", NIL);
653      //      Printv(s_cmd_tab, tab4, "{ SWIG_prefix \"", iname, "\", (swig_wrapper_func) ", Swig_name_wrapper(iname), "},\n", NIL);
654    } else {
655      if (!Getattr(n, "sym:nextSibling")) {
656        dispatchFunction(n);
657      }
658    }
659
660    Delete(argument_check);
661    Delete(argument_parse);
662
663    Delete(cleanup);
664    Delete(outarg);
665    //    Delete(description);
666    Delete(wname);
667    DelWrapper(f);
668
669    return SWIG_OK;
670  }
671
672  /* ------------------------------------------------------------
673   * dispatchFunction()
674   *
675   * Emit overloading dispatch function
676   * ------------------------------------------------------------ */
677
678  /* NEW LANGUAGE NOTE:***********************************************
679  This is an extra function used for overloading of functions
680  it checks the args & then calls the relevant fn
681  nost of the real work in again typemaps:
682  look for %typecheck(SWIG_TYPECHECK_*) in the .swg file
683  NEW LANGUAGE NOTE:END ************************************************/
684  void dispatchFunction(Node *n) {
685    /* Last node in overloaded chain */
686
687    int maxargs;
688    String *tmp = NewString("");
689    String *dispatch = Swig_overload_dispatch(n, "return %s(L);", &maxargs);
690
691    /* Generate a dispatch wrapper for all overloaded functions */
692
693    Wrapper *f = NewWrapper();
694    String *symname = Getattr(n, "sym:name");
695    String *wname = Swig_name_wrapper(symname);
696
697    //Printf(stdout,"Swig_overload_dispatch %s %s '%s' %d\n",symname,wname,dispatch,maxargs);
698
699    Printv(f->def, "static int ", wname, "(lua_State* L) {", NIL);
700    Wrapper_add_local(f, "argc", "int argc");
701    Printf(tmp, "int argv[%d]={1", maxargs + 1);
702    for (int i = 1; i <= maxargs; i++) {
703      Printf(tmp, ",%d", i + 1);
704    }
705    Printf(tmp, "}");
706    Wrapper_add_local(f, "argv", tmp);
707    Printf(f->code, "argc = lua_gettop(L);\n");
708
709    Replaceall(dispatch, "$args", "self,args");
710    Printv(f->code, dispatch, "\n", NIL);
711
712    Node *sibl = n;
713    while (Getattr(sibl, "sym:previousSibling"))
714      sibl = Getattr(sibl, "sym:previousSibling");	// go all the way up
715    String *protoTypes = NewString("");
716    do {
717      Printf(protoTypes, "\n\"    %s(%s)\\n\"", SwigType_str(Getattr(sibl, "name"), 0), ParmList_protostr(Getattr(sibl, "wrap:parms")));
718    } while ((sibl = Getattr(sibl, "sym:nextSibling")));
719    Printf(f->code, "lua_pushstring(L,\"Wrong arguments for overloaded function '%s'\\n\"\n"
720        "\"  Possible C/C++ prototypes are:\\n\"%s);\n",symname,protoTypes);
721    Delete(protoTypes);
722
723    Printf(f->code, "lua_error(L);return 0;\n");
724    Printv(f->code, "}\n", NIL);
725    Wrapper_print(f, f_wrappers);
726    //add_method(symname,wname,0);
727    if (current==NO_CPP || current==STATIC_FUNC) // emit normal fns & static fns
728      Printv(s_cmd_tab, tab4, "{ \"", symname, "\",", wname, "},\n", NIL);
729
730    DelWrapper(f);
731    Delete(dispatch);
732    Delete(tmp);
733    Delete(wname);
734  }
735
736
737  /* ------------------------------------------------------------
738   * variableWrapper()
739   * ------------------------------------------------------------ */
740
741  virtual int variableWrapper(Node *n) {
742    /* NEW LANGUAGE NOTE:***********************************************
743    Language::variableWrapper(n) will generate two wrapper fns
744    Foo_get & Foo_set by calling functionWrapper()
745    so we will just add these into the variable lists
746    ideally we should not have registered these as functions,
747    only WRT this variable will look into this later.
748    NEW LANGUAGE NOTE:END ************************************************/
749    //    REPORT("variableWrapper", n);
750    String *iname = Getattr(n, "sym:name");
751    current=VARIABLE;
752    // let SWIG generate the wrappers
753    int result = Language::variableWrapper(n);
754    current=NO_CPP;
755    // normally SWIG will generate 2 wrappers, a get and a set
756    // but in certain scenarios (immutable, or if its arrays), it will not
757    String *getName = Swig_name_wrapper(Swig_name_get(iname));
758    String *setName = 0;
759    // checking whether it can be set to or not appears to be a very error prone issue
760    // I refered to the Language::variableWrapper() to find this out
761    bool assignable=is_assignable(n) ? true : false;
762    SwigType *type = Getattr(n, "type");
763    String *tm = Swig_typemap_lookup("globalin", n, iname, 0);
764    if (!tm && SwigType_isarray(type))
765      assignable=false;
766    Delete(tm);
767
768    if (assignable) {
769      setName = Swig_name_wrapper(Swig_name_set(iname));
770    } else {
771      // how about calling a 'this is not settable' error message?
772      setName = NewString("SWIG_Lua_set_immutable"); // error message
773      //setName = NewString("0");
774    }
775    // register the variable
776    Printf(s_var_tab, "%s{ \"%s\", %s, %s },\n", tab4, iname, getName, setName);
777    Delete(getName);
778    Delete(setName);
779    return result;
780  }
781
782  /* ------------------------------------------------------------
783   * constantWrapper()
784   * ------------------------------------------------------------ */
785  virtual int constantWrapper(Node *n) {
786    //    REPORT("constantWrapper", n);
787    String *name = Getattr(n, "name");
788    String *iname = Getattr(n, "sym:name");
789    //String *nsname    = !nspace ? Copy(iname) : NewStringf("%s::%s",ns_name,iname);
790    String *nsname = Copy(iname);
791    SwigType *type = Getattr(n, "type");
792    String *rawval = Getattr(n, "rawval");
793    String *value = rawval ? rawval : Getattr(n, "value");
794    String *tm;
795
796    if (!addSymbol(iname, n))
797      return SWIG_ERROR;
798    //if (nspace) Setattr(n,"sym:name",nsname);
799
800    /* Special hook for member pointer */
801    if (SwigType_type(type) == T_MPOINTER) {
802      String *wname = Swig_name_wrapper(iname);
803      Printf(f_wrappers, "static %s = %s;\n", SwigType_str(type, wname), value);
804      value = Char(wname);
805    }
806
807    if ((tm = Swig_typemap_lookup("consttab", n, name, 0))) {
808      Replaceall(tm, "$source", value);
809      Replaceall(tm, "$target", name);
810      Replaceall(tm, "$value", value);
811      Replaceall(tm, "$nsname", nsname);
812      Printf(s_const_tab, "%s,\n", tm);
813    } else if ((tm = Swig_typemap_lookup("constcode", n, name, 0))) {
814      Replaceall(tm, "$source", value);
815      Replaceall(tm, "$target", name);
816      Replaceall(tm, "$value", value);
817      Replaceall(tm, "$nsname", nsname);
818      Printf(f_init, "%s\n", tm);
819    } else {
820      Delete(nsname);
821      Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number, "Unsupported constant value.\n");
822      return SWIG_NOWRAP;
823    }
824    Delete(nsname);
825    return SWIG_OK;
826  }
827
828  /* ------------------------------------------------------------
829   * nativeWrapper()
830   * ------------------------------------------------------------ */
831
832  virtual int nativeWrapper(Node *n) {
833    //    REPORT("nativeWrapper", n);
834    String *symname = Getattr(n, "sym:name");
835    String *wrapname = Getattr(n, "wrap:name");
836    if (!addSymbol(wrapname, n))
837      return SWIG_ERROR;
838
839    Printv(s_cmd_tab, tab4, "{ \"", symname, "\",", wrapname, "},\n", NIL);
840    //   return Language::nativeWrapper(n); // this does nothing...
841    return SWIG_OK;
842  }
843
844  /* ------------------------------------------------------------
845   * enumDeclaration()
846   * ------------------------------------------------------------ */
847
848  virtual int enumDeclaration(Node *n) {
849    return Language::enumDeclaration(n);
850  }
851
852  /* ------------------------------------------------------------
853   * enumvalueDeclaration()
854   * ------------------------------------------------------------ */
855
856  virtual int enumvalueDeclaration(Node *n) {
857    return Language::enumvalueDeclaration(n);
858  }
859
860  /* ------------------------------------------------------------
861   * classDeclaration()
862   * ------------------------------------------------------------ */
863
864  virtual int classDeclaration(Node *n) {
865    return Language::classDeclaration(n);
866  }
867
868  /* ------------------------------------------------------------
869   * classHandler()
870   * ------------------------------------------------------------ */
871
872  virtual int classHandler(Node *n) {
873    //REPORT("classHandler", n);
874
875    String *mangled_classname = 0;
876    String *real_classname = 0;
877
878    constructor_name = 0;
879    have_constructor = 0;
880    have_destructor = 0;
881    destructor_action = 0;
882
883    class_name = Getattr(n, "sym:name");
884    if (!addSymbol(class_name, n))
885      return SWIG_ERROR;
886
887    real_classname = Getattr(n, "name");
888    mangled_classname = Swig_name_mangle(real_classname);
889
890    // not sure exactly how this workswhat this works,
891    // but tcl has a static hashtable of all classes emitted and then only emits code for them once.
892    // this fixes issues in test suites: template_default2 & template_specialization
893
894    // * if i understand correctly, this is a bug.
895    // * consider effect on template_specialization_defarg
896
897    static Hash *emitted = NewHash();
898    if (Getattr(emitted, mangled_classname))
899      return SWIG_NOWRAP;
900    Setattr(emitted, mangled_classname, "1");
901
902    s_attr_tab = NewString("");
903    Printf(s_attr_tab, "static swig_lua_attribute swig_");
904    Printv(s_attr_tab, mangled_classname, "_attributes[] = {\n", NIL);
905
906    s_methods_tab = NewString("");
907    Printf(s_methods_tab, "static swig_lua_method swig_");
908    Printv(s_methods_tab, mangled_classname, "_methods[] = {\n", NIL);
909
910    // Generate normal wrappers
911    Language::classHandler(n);
912
913    SwigType *t = Copy(Getattr(n, "name"));
914    SwigType_add_pointer(t);
915
916    // Catch all: eg. a class with only static functions and/or variables will not have 'remembered'
917    String *wrap_class = NewStringf("&_wrap_class_%s", mangled_classname);
918    SwigType_remember_clientdata(t, wrap_class);
919
920    String *rt = Copy(Getattr(n, "classtype"));
921    SwigType_add_pointer(rt);
922
923    // Register the class structure with the type checker
924    //    Printf(f_init,"SWIG_TypeClientData(SWIGTYPE%s, (void *) &_wrap_class_%s);\n", SwigType_manglestr(t), mangled_classname);
925
926    // emit a function to be called to delete the object
927    if (have_destructor) {
928      Printv(f_wrappers, "static void swig_delete_", class_name, "(void *obj) {\n", NIL);
929      if (destructor_action) {
930        Printv(f_wrappers, SwigType_str(rt, "arg1"), " = (", SwigType_str(rt, 0), ") obj;\n", NIL);
931        Printv(f_wrappers, destructor_action, "\n", NIL);
932      } else {
933        if (CPlusPlus) {
934          Printv(f_wrappers, "    delete (", SwigType_str(rt, 0), ") obj;\n", NIL);
935        } else {
936          Printv(f_wrappers, "    free((char *) obj);\n", NIL);
937        }
938      }
939      Printf(f_wrappers, "}\n");
940    }
941
942    Printf(s_methods_tab, "    {0,0}\n};\n");
943    Printv(f_wrappers, s_methods_tab, NIL);
944
945    Printf(s_attr_tab, "    {0,0,0}\n};\n");
946    Printv(f_wrappers, s_attr_tab, NIL);
947
948    Delete(s_methods_tab);
949    Delete(s_attr_tab);
950
951    // Handle inheritance
952    // note: with the idea of class hireachied spread over multiple modules
953    // cf test-suite: imports.i
954    // it is not possible to just add the pointers to the base classes to the code
955    // (as sometimes these classes are not present)
956    // therefore we instead hold the name of the base class and a null pointer
957    // at runtime: we can query the swig type manager & see if the class exists
958    // if so, we can get the pointer to the base class & replace the null pointer
959    // if the type does not exist, then we cannot...
960    String *base_class = NewString("");
961    String *base_class_names = NewString("");
962
963    List *baselist = Getattr(n, "bases");
964    if (baselist && Len(baselist)) {
965      Iterator b;
966      int index = 0;
967      b = First(baselist);
968      while (b.item) {
969        String *bname = Getattr(b.item, "name");
970        if ((!bname) || GetFlag(b.item, "feature:ignore") || (!Getattr(b.item, "module"))) {
971          b = Next(b);
972          continue;
973        }
974        // old code: (used the pointer to the base class)
975        //String *bmangle = Swig_name_mangle(bname);
976        //Printf(base_class, "&_wrap_class_%s", bmangle);
977        //Putc(',', base_class);
978        //Delete(bmangle);
979        // new code: stores a null pointer & the name
980        Printf(base_class, "0,");
981        Printf(base_class_names, "\"%s *\",", SwigType_namestr(bname));
982
983        b = Next(b);
984        index++;
985      }
986    }
987
988    Printv(f_wrappers, "static swig_lua_class *swig_", mangled_classname, "_bases[] = {", base_class, "0};\n", NIL);
989    Delete(base_class);
990    Printv(f_wrappers, "static const char *swig_", mangled_classname, "_base_names[] = {", base_class_names, "0};\n", NIL);
991    Delete(base_class_names);
992
993    Printv(f_wrappers, "static swig_lua_class _wrap_class_", mangled_classname, " = { \"", class_name, "\", &SWIGTYPE", SwigType_manglestr(t), ",", NIL);
994
995    if (have_constructor) {
996      Printf(f_wrappers, "%s", Swig_name_wrapper(Swig_name_construct(constructor_name)));
997      Delete(constructor_name);
998      constructor_name = 0;
999    } else {
1000      Printf(f_wrappers, "0");
1001    }
1002
1003    if (have_destructor) {
1004      Printv(f_wrappers, ", swig_delete_", class_name, NIL);
1005    } else {
1006      Printf(f_wrappers, ",0");
1007    }
1008    Printf(f_wrappers, ", swig_%s_methods, swig_%s_attributes, swig_%s_bases, swig_%s_base_names };\n\n", mangled_classname, mangled_classname, mangled_classname, mangled_classname);
1009
1010    //    Printv(f_wrappers, ", swig_", mangled_classname, "_methods, swig_", mangled_classname, "_attributes, swig_", mangled_classname, "_bases };\n\n", NIL);
1011    //    Printv(s_cmd_tab, tab4, "{ SWIG_prefix \"", class_name, "\", (swig_wrapper_func) SWIG_ObjectConstructor, &_wrap_class_", mangled_classname, "},\n", NIL);
1012    Delete(t);
1013    Delete(mangled_classname);
1014    return SWIG_OK;
1015  }
1016
1017  /* ------------------------------------------------------------
1018   * memberfunctionHandler()
1019   * ------------------------------------------------------------ */
1020
1021  virtual int memberfunctionHandler(Node *n) {
1022    String *name = Getattr(n, "name");
1023    String *iname = GetChar(n, "sym:name");
1024    //Printf(stdout,"memberfunctionHandler %s %s\n",name,iname);
1025
1026    // Special case unary minus: LUA passes two parameters for the
1027    // wrapper function while we want only one. Tell our
1028    // functionWrapper to ignore a parameter.
1029
1030    if (Cmp(Getattr(n, "sym:name"), "__unm") == 0) {
1031      //Printf(stdout, "unary minus: ignore one argument\n");
1032      SetInt(n, "lua:ignore_args", 1);
1033    }
1034
1035    String *realname, *rname;
1036
1037    current = MEMBER_FUNC;
1038    Language::memberfunctionHandler(n);
1039    current = NO_CPP;
1040
1041    realname = iname ? iname : name;
1042    rname = Swig_name_wrapper(Swig_name_member(class_name, realname));
1043    if (!Getattr(n, "sym:nextSibling")) {
1044      Printv(s_methods_tab, tab4, "{\"", realname, "\", ", rname, "}, \n", NIL);
1045    }
1046    Delete(rname);
1047    return SWIG_OK;
1048  }
1049
1050  /* ------------------------------------------------------------
1051   * membervariableHandler()
1052   * ------------------------------------------------------------ */
1053
1054  virtual int membervariableHandler(Node *n) {
1055    //    REPORT("membervariableHandler",n);
1056    String *symname = Getattr(n, "sym:name");
1057    String *gname, *sname;
1058
1059    current = MEMBER_VAR;
1060    Language::membervariableHandler(n);
1061    current = NO_CPP;
1062    gname = Swig_name_wrapper(Swig_name_get(Swig_name_member(class_name, symname)));
1063    if (!GetFlag(n, "feature:immutable")) {
1064      sname = Swig_name_wrapper(Swig_name_set(Swig_name_member(class_name, symname)));
1065    } else {
1066      //sname = NewString("0");
1067      sname = NewString("SWIG_Lua_set_immutable"); // error message
1068    }
1069    Printf(s_attr_tab,"%s{ \"%s\", %s, %s},\n",tab4,symname,gname,sname);
1070    Delete(gname);
1071    Delete(sname);
1072    return SWIG_OK;
1073  }
1074
1075  /* ------------------------------------------------------------
1076   * constructorHandler()
1077   *
1078   * Method for adding C++ member constructor
1079   * ------------------------------------------------------------ */
1080
1081  virtual int constructorHandler(Node *n) {
1082    //    REPORT("constructorHandler", n);
1083    current = CONSTRUCTOR;
1084    Language::constructorHandler(n);
1085    current = NO_CPP;
1086    constructor_name = NewString(Getattr(n, "sym:name"));
1087    have_constructor = 1;
1088    return SWIG_OK;
1089  }
1090
1091  /* ------------------------------------------------------------
1092   * destructorHandler()
1093   * ------------------------------------------------------------ */
1094
1095  virtual int destructorHandler(Node *n) {
1096    REPORT("destructorHandler", n);
1097    current = DESTRUCTOR;
1098    Language::destructorHandler(n);
1099    current = NO_CPP;
1100    have_destructor = 1;
1101    destructor_action = Getattr(n, "wrap:action");
1102    return SWIG_OK;
1103  }
1104
1105  /* -----------------------------------------------------------------------
1106   * staticmemberfunctionHandler()
1107   *
1108   * Wrap a static C++ function
1109   * ---------------------------------------------------------------------- */
1110
1111  virtual int staticmemberfunctionHandler(Node *n) {
1112    current = STATIC_FUNC;
1113    return Language::staticmemberfunctionHandler(n);
1114  }
1115
1116  /* ------------------------------------------------------------
1117   * memberconstantHandler()
1118   *
1119   * Create a C++ constant
1120   * ------------------------------------------------------------ */
1121
1122  virtual int memberconstantHandler(Node *n) {
1123    //    REPORT("memberconstantHandler",n);
1124    return Language::memberconstantHandler(n);
1125  }
1126
1127  /* ---------------------------------------------------------------------
1128   * staticmembervariableHandler()
1129   * --------------------------------------------------------------------- */
1130
1131  virtual int staticmembervariableHandler(Node *n) {
1132    //    REPORT("staticmembervariableHandler",n);
1133    current = STATIC_VAR;
1134    return Language::staticmembervariableHandler(n);
1135  }
1136
1137  /* ---------------------------------------------------------------------
1138   * external runtime generation
1139   * --------------------------------------------------------------------- */
1140
1141  /* This is to support the usage
1142     SWIG -external-runtime <filename>
1143     The code consists of two functions:
1144     String *runtimeCode()  // returns a large string with all the runtimes in
1145     String *defaultExternalRuntimeFilename() // returns the default filename
1146     I am writing a generic solution, even though SWIG-Lua only has one file right now...
1147   */
1148  String *runtimeCode() {
1149    String *s = NewString("");
1150    const char *filenames[] = { "luarun.swg", 0
1151                              }
1152                              ;	// must be 0 termiated
1153    String *sfile;
1154    for (int i = 0; filenames[i] != 0; i++) {
1155      sfile = Swig_include_sys(filenames[i]);
1156      if (!sfile) {
1157        Printf(stderr, "*** Unable to open '%s'\n", filenames[i]);
1158      } else {
1159        Append(s, sfile);
1160        Delete(sfile);
1161      }
1162    }
1163
1164    return s;
1165  }
1166
1167  String *defaultExternalRuntimeFilename() {
1168    return NewString("swigluarun.h");
1169  }
1170
1171  /* ---------------------------------------------------------------------
1172   * helpers
1173   * --------------------------------------------------------------------- */
1174
1175  /* This is to convert the string of Lua code into a proper string, which can then be
1176     emitted into the C/C++ code.
1177     Basically is is a lot of search & replacing of odd sequences
1178   */
1179  void EscapeCode(String* str)
1180  {
1181    //Printf(f_runtime,"/* original luacode:[[[\n%s\n]]]\n*/\n",str);
1182    Chop(str); // trim
1183    Replace(str,"\\","\\\\",DOH_REPLACE_ANY); // \ to \\ (this must be done first)
1184    Replace(str,"\"","\\\"",DOH_REPLACE_ANY); // " to \"
1185    Replace(str,"\n","\\n\"\n  \"",DOH_REPLACE_ANY); // \n to \n"\n" (ie quoting every line)
1186    //Printf(f_runtime,"/* hacked luacode:[[[\n%s\n]]]\n*/\n",str);
1187  }
1188};
1189
1190/* NEW LANGUAGE NOTE:***********************************************
1191 in order to add you language into swig, you need to make the following changes:
1192 - write this file (obviously)
1193 - add into the makefile (not 100% clear on how to do this)
1194 - edit swigmain.cxx to add your module
1195
1196near the top of swigmain.cxx, look for this code & add you own codes
1197======= begin change ==========
1198extern "C" {
1199  Language *swig_tcl(void);
1200  Language *swig_python(void);
1201  //etc,etc,etc...
1202  Language *swig_lua(void);	// this is my code
1203}
1204
1205  //etc,etc,etc...
1206
1207swig_module  modules[] = {
1208  {"-guile",     swig_guile,     "Guile"},
1209  {"-java",      swig_java,      "Java"},
1210  //etc,etc,etc...
1211  {"-lua",       swig_lua,       "Lua"},	// this is my code
1212  {NULL, NULL, NULL}	// this must come at the end of the list
1213};
1214======= end change ==========
1215
1216This is all that is needed
1217
1218NEW LANGUAGE NOTE:END ************************************************/
1219
1220/* -----------------------------------------------------------------------------
1221 * swig_lua()    - Instantiate module
1222 * ----------------------------------------------------------------------------- */
1223
1224extern "C" Language *swig_lua(void) {
1225  return new LUA();
1226}
1227