12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240 |
- /* -----------------------------------------------------------------------------
- * This file is part of SWIG, which is licensed as a whole under version 3
- * (or any later version) of the GNU General Public License. Some additional
- * terms also apply to certain portions of SWIG. The full details of the SWIG
- * license and copyrights can be found in the LICENSE and COPYRIGHT files
- * included with the SWIG source code as distributed by the SWIG developers
- * and at https://www.swig.org/legal.html.
- *
- * lua.cxx
- *
- * Lua language module for SWIG.
- * ----------------------------------------------------------------------------- */
- /* NEW LANGUAGE NOTE:
- * ver001
- this is simply a copy of tcl8.cxx, which has been renamed
- * ver002
- all non essential code commented out, program now does virtually nothing
- it prints to stderr the list of functions to wrap, but does not create
- the XXX_wrap.c file
- * ver003
- added back top(), still prints the list of fns to stderr
- but now creates a rather empty XXX_wrap.c with some basic boilerplate code
- * ver004
- very basic version of functionWrapper()
- also uncommented usage_string() to keep compiler happy
- this will start producing proper looking code soon (I hope)
- produced the wrapper code, but without any type conversion (in or out)
- generates a few warning because of no wrappering
- does not generate SWIG_init()
- reason for this is that lua.swg is empty
- we will need to add code into this to make it work
- * ver005/6
- massive rework, basing work on the pike module instead of tcl
- (pike module it only 1/3 of the size)(though not as complete)
- * ver007
- added simple type checking
- * ver008
- INPUT, OUTPUT, INOUT typemaps handled (though not all types yet)
- * ver009
- class support: ok for basic types, but methods still TDB
- (code is VERY messed up & needs to be cleaned)
- * ver010
- Added support for embedded Lua. Try swig -lua -help for more information
- */
- #include "swigmod.h"
- #include "cparse.h"
- /**** Diagnostics:
- With the #define REPORT(), you can change the amount of diagnostics given
- This helps me search the parse tree & figure out what is going on inside SWIG
- (because it's not clear or documented)
- */
- #define REPORT(T,D) // no info:
- //#define REPORT(T,D) {Printf(stdout,T"\n");} // only title
- //#define REPORT(T,D) {Printf(stdout,T" %p\n",n);} // title & pointer
- //#define REPORT(T,D) {Printf(stdout,T"\n");display_mapping(D);} // the works
- //#define REPORT(T,D) {Printf(stdout,T"\n");if(D)Swig_print_node(D);} // the works
- void display_mapping(DOH *d) {
- if (d == 0 || !DohIsMapping(d))
- return;
- for (Iterator it = First(d); it.item; it = Next(it)) {
- if (DohIsString(it.item))
- Printf(stdout, " %s = %s\n", it.key, it.item);
- else if (DohIsMapping(it.item))
- Printf(stdout, " %s = <mapping>\n", it.key);
- else if (DohIsSequence(it.item))
- Printf(stdout, " %s = <sequence>\n", it.key);
- else
- Printf(stdout, " %s = <unknown>\n", it.key);
- }
- }
- extern "C"
- {
- static int compareByLen(const DOH *f, const DOH *s) {
- return Len(s) - Len(f);
- }
- }
- /* NEW LANGUAGE NOTE:***********************************************
- most of the default options are handled by SWIG
- you can add new ones here
- (though for now I have not bothered)
- NEW LANGUAGE NOTE:END ************************************************/
- static const char *usage = "\
- Lua Options (available with -lua)\n\
- -elua - Generates LTR compatible wrappers for smaller devices running elua\n\
- -eluac - LTR compatible wrappers in \"crass compress\" mode for elua\n\
- -elua-emulate - Emulates behaviour of eLua. Useful only for testing.\n\
- Incompatible with -elua/-eluac options.\n\
- -nomoduleglobal - Do not register the module name as a global variable \n\
- but return the module table from calls to require.\n\
- -no-old-metatable-bindings\n\
- - Disable support for old-style bindings name generation, some\n\
- old-style members scheme etc.\n\
- -squash-bases - Squashes symbols from all inheritance tree of a given class\n\
- into itself. Emulates pre-SWIG3.0 inheritance. Insignificantly\n\
- speeds things up, but increases memory consumption.\n\
- \n";
- static int nomoduleglobal = 0;
- static int elua_ltr = 0;
- static int eluac_ltr = 0;
- static int elua_emulate = 0;
- static int squash_bases = 0;
- /* The new metatable bindings were introduced in SWIG 3.0.0.
- * old_metatable_bindings in v2:
- * 1. static methods will be put into the scope their respective class
- * belongs to as well as into the class scope itself. (only for classes without %nspace given)
- * 2. The layout in elua mode is somewhat different
- */
- static int old_metatable_bindings = 1;
- static int old_compatible_names = 1; // This flag can temporarily disable backward compatible names generation if old_metatable_bindings is enabled
- /* NEW LANGUAGE NOTE:***********************************************
- To add a new language, you need to derive your class from
- Language and the overload various virtual functions
- (more on this as I figure it out)
- NEW LANGUAGE NOTE:END ************************************************/
- class LUA:public Language {
- private:
- File *f_begin;
- File *f_runtime;
- File *f_header;
- File *f_wrappers;
- File *f_init;
- File *f_initbeforefunc;
- String *s_luacode; // luacode to be called during init
- String *module; //name of the module
- // Parameters for current class. NIL if not parsing class
- int have_constructor;
- int have_destructor;
- String *destructor_action;
- // This variable holds the name of the current class in Lua. Usually it is
- // the same as C++ class name, but rename directives can change it.
- String *proxy_class_name;
- // This is a so called fully qualified symname - the above proxy class name
- // prepended with class namespace. If class Lua name is the same as class C++ name,
- // then it is basically C++ fully qualified name with colons replaced with dots.
- String *full_proxy_class_name;
- // All static methods and/or variables are treated as if they were in the
- // special C++ namespace $(classname).SwigStatic. This is internal mechanism only
- // and is not visible to user in any manner. This variable holds the name
- // of such pseudo-namespace a.k.a the result of above expression evaluation
- String *class_static_nspace;
- // This variable holds the name of generated C function that acts as a constructor
- // for the currently parsed class.
- String *constructor_name;
- // Many wrappers forward calls to each other, for example staticmembervariableHandler
- // forwards calls to variableHandler, which, in turn, makes to call to functionWrapper.
- // In order to access information about whether it is a static member of class or just
- // a plain old variable, the current array is kept and used as a 'log' of the call stack.
- enum TState {
- NO_CPP,
- VARIABLE,
- GLOBAL_FUNC,
- GLOBAL_VAR,
- MEMBER_FUNC,
- CONSTRUCTOR,
- DESTRUCTOR,
- MEMBER_VAR,
- STATIC_FUNC,
- STATIC_VAR,
- STATIC_CONST, // enums and things like static const int x = 5;
- ENUM_CONST, // This is only needed for backward compatibility in C mode
- STATES_COUNT
- };
- bool current[STATES_COUNT];
- public:
- /* ---------------------------------------------------------------------
- * LUA()
- *
- * Initialize member data
- * --------------------------------------------------------------------- */
- LUA():
- f_begin(0),
- f_runtime(0),
- f_header(0),
- f_wrappers(0),
- f_init(0),
- f_initbeforefunc(0),
- s_luacode(0),
- module(0),
- have_constructor(0),
- have_destructor(0),
- destructor_action(0),
- proxy_class_name(0),
- full_proxy_class_name(0),
- class_static_nspace(0),
- constructor_name(0) {
- for (int i = 0; i < STATES_COUNT; i++)
- current[i] = false;
- }
- /* NEW LANGUAGE NOTE:***********************************************
- This is called to initialise the system & read any command line args
- most of this is boilerplate code, except the command line args
- which depends upon what args your code supports
- NEW LANGUAGE NOTE:END *********************************************** */
- /* ---------------------------------------------------------------------
- * main()
- *
- * Parse command line options and initializes variables.
- * --------------------------------------------------------------------- */
- virtual void main(int argc, char *argv[]) {
- /* Set location of SWIG library */
- SWIG_library_directory("lua");
- /* Look for certain command line options */
- for (int i = 1; i < argc; i++) {
- if (argv[i]) {
- if (strcmp(argv[i], "-help") == 0) { // usage flags
- fputs(usage, stdout);
- } else if (strcmp(argv[i], "-nomoduleglobal") == 0) {
- nomoduleglobal = 1;
- Swig_mark_arg(i);
- } else if (strcmp(argv[i], "-elua") == 0) {
- elua_ltr = 1;
- Swig_mark_arg(i);
- } else if (strcmp(argv[i], "-eluac") == 0) {
- eluac_ltr = 1;
- Swig_mark_arg(i);
- } else if (strcmp(argv[i], "-no-old-metatable-bindings") == 0) {
- Swig_mark_arg(i);
- old_metatable_bindings = 0;
- } else if (strcmp(argv[i], "-squash-bases") == 0) {
- Swig_mark_arg(i);
- squash_bases = 1;
- } else if (strcmp(argv[i], "-elua-emulate") == 0) {
- Swig_mark_arg(i);
- elua_emulate = 1;
- }
- }
- }
- if (elua_emulate && (eluac_ltr || elua_ltr )) {
- Printf(stderr, "Cannot have -elua-emulate with either -eluac or -elua\n");
- Swig_arg_error();
- }
- // Set elua_ltr if elua_emulate is requested
- if(elua_emulate)
- elua_ltr = 1;
- /* NEW LANGUAGE NOTE:***********************************************
- This is the boilerplate code, setting a few #defines
- and which lib directory to use
- the SWIG_library_directory() is also boilerplate code
- but it always seems to be the first line of code
- NEW LANGUAGE NOTE:END *********************************************** */
- /* Add a symbol to the parser for conditional compilation */
- Preprocessor_define("SWIGLUA 1", 0);
- /* Set language-specific configuration file */
- SWIG_config_file("lua.swg");
- /* Set typemap language */
- SWIG_typemap_lang("lua");
- /* Enable overloaded methods support */
- allow_overloading();
- }
- /* NEW LANGUAGE NOTE:***********************************************
- After calling main, SWIG parses the code to wrap (I believe)
- then calls top()
- in this is more boilerplate code to set everything up
- and a call to Language::top()
- which begins the code generations by calling the member fns
- after all that is more boilerplate code to close all down
- (overall there is virtually nothing here that needs to be edited
- just use as is)
- NEW LANGUAGE NOTE:END *********************************************** */
- /* ---------------------------------------------------------------------
- * top()
- * --------------------------------------------------------------------- */
- virtual int top(Node *n) {
- /* Get the module name */
- module = Getattr(n, "name");
- /* Get the output file name */
- String *outfile = Getattr(n, "outfile");
- /* Open the output file */
- f_begin = NewFile(outfile, "w", SWIG_output_files());
- if (!f_begin) {
- FileErrorDisplay(outfile);
- Exit(EXIT_FAILURE);
- }
- f_runtime = NewString("");
- f_init = NewString("");
- f_header = NewString("");
- f_wrappers = NewString("");
- f_initbeforefunc = NewString("");
- /* Register file targets with the SWIG file handler */
- Swig_register_filebyname("header", f_header);
- Swig_register_filebyname("wrapper", f_wrappers);
- Swig_register_filebyname("begin", f_begin);
- Swig_register_filebyname("runtime", f_runtime);
- Swig_register_filebyname("init", f_init);
- Swig_register_filebyname("initbeforefunc", f_initbeforefunc);
- s_luacode = NewString("");
- Swig_register_filebyname("luacode", s_luacode);
- current[NO_CPP] = true;
- /* Standard stuff for the SWIG runtime section */
- Swig_banner(f_begin);
- Swig_obligatory_macros(f_runtime, "LUA");
- emitLuaFlavor(f_runtime);
- if (nomoduleglobal) {
- Printf(f_runtime, "#define SWIG_LUA_NO_MODULE_GLOBAL\n");
- } else {
- Printf(f_runtime, "#define SWIG_LUA_MODULE_GLOBAL\n");
- }
- if (squash_bases)
- Printf(f_runtime, "#define SWIG_LUA_SQUASH_BASES\n");
- // if (NoInclude) {
- // Printf(f_runtime, "#define SWIG_NOINCLUDE\n");
- // }
- Printf(f_runtime, "\n");
- //String *init_name = NewStringf("%(title)s_Init", module);
- //Printf(f_header, "#define SWIG_init %s\n", init_name);
- //Printf(f_header, "#define SWIG_name \"%s\"\n", module);
- /* SWIG_import is a special function name for importing within Lua5.1 */
- //Printf(f_header, "#define SWIG_import luaopen_%s\n\n", module);
- Printf(f_header, "#define SWIG_name \"%s\"\n", module);
- Printf(f_header, "#define SWIG_init luaopen_%s\n", module);
- Printf(f_header, "#define SWIG_init_user luaopen_%s_user\n\n", module);
- Printf(f_header, "#define SWIG_LUACODE luaopen_%s_luacode\n", module);
- Printf(f_wrappers, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n");
- /* %init code inclusion, effectively in the SWIG_init function */
- Printf(f_init, "void SWIG_init_user(lua_State* L)\n{\n");
- Language::top(n);
- Printf(f_init, "/* exec Lua code if applicable */\nSWIG_Lua_dostring(L,SWIG_LUACODE);\n");
- Printf(f_init, "}\n");
- // Done. Close up the module & write to the wrappers
- closeNamespaces(f_wrappers);
- Printf(f_wrappers, "#ifdef __cplusplus\n}\n#endif\n");
- SwigType_emit_type_table(f_runtime, f_wrappers);
- /* NEW LANGUAGE NOTE:***********************************************
- this basically combines several of the strings together
- and then writes it all to a file
- NEW LANGUAGE NOTE:END *********************************************** */
- Dump(f_runtime, f_begin);
- Dump(f_header, f_begin);
- Dump(f_wrappers, f_begin);
- Dump(f_initbeforefunc, f_begin);
- /* for the Lua code it needs to be properly escaped to be added into the C/C++ code */
- escapeCode(s_luacode);
- Printf(f_begin, "const char* SWIG_LUACODE=\n \"%s\";\n\n", s_luacode);
- Wrapper_pretty_print(f_init, f_begin);
- /* Close all of the files */
- Delete(s_luacode);
- Delete(f_header);
- Delete(f_wrappers);
- Delete(f_init);
- Delete(f_initbeforefunc);
- Delete(f_runtime);
- Delete(f_begin);
- /* Done */
- return SWIG_OK;
- }
- /* ------------------------------------------------------------
- * importDirective()
- * ------------------------------------------------------------ */
- virtual int importDirective(Node *n) {
- return Language::importDirective(n);
- }
- /* ------------------------------------------------------------
- * cDeclaration()
- * It copies sym:name to lua:name to preserve its original value
- * ------------------------------------------------------------ */
- virtual int cDeclaration(Node *n) {
- // class 'Language' is messing with symname in a really heavy way.
- // Although documentation states that sym:name is a name in
- // the target language space, it is not true. sym:name and
- // its derivatives are used in various places, including
- // behind-the-scene C code generation. The best way is not to
- // touch it at all.
- // But we need to know what was the name of function/variable
- // etc that user desired, that's why we store correct symname
- // as lua:name
- String *symname = Getattr(n, "sym:name");
- if (symname)
- Setattr(n, "lua:name", symname);
- return Language::cDeclaration(n);
- }
- virtual int constructorDeclaration(Node *n) {
- Setattr(n, "lua:name", Getattr(n, "sym:name"));
- return Language::constructorDeclaration(n);
- }
- virtual int destructorDeclaration(Node *n) {
- Setattr(n, "lua:name", Getattr(n, "sym:name"));
- return Language::destructorDeclaration(n);
- }
- /* NEW LANGUAGE NOTE:***********************************************
- This is it!
- you get this one right, and most of your work is done
- but it's going to take some file to get it working right
- quite a bit of this is generally boilerplate code
- (or stuff I don't understand)
- that which matters will have extra added comments
- NEW LANGUAGE NOTE:END *********************************************** */
- /* ---------------------------------------------------------------------
- * functionWrapper()
- *
- * Create a function declaration and register it with the interpreter.
- * --------------------------------------------------------------------- */
- /* -----------------------------------------------------------------------
- * registerMethod()
- *
- * Determines wrap name of a method, its scope etc and calls
- * registerMethod overload with correct arguments
- * Overloaded variant adds method to the "methods" array of specified lua scope/class
- * ---------------------------------------------------------------------- */
- void registerMethod(Node *n, bool overwrite = false, String *overwriteLuaScope = 0) {
- String *symname = Getattr(n, "sym:name");
- assert(symname);
- if (Getattr(n, "sym:nextSibling"))
- return;
- // Lua scope. It is not symbol NSpace, it is the actual key to retrieve getCArraysHash.
- String *luaScope = luaCurrentSymbolNSpace();
- if (overwrite)
- luaScope = overwriteLuaScope;
- String *wrapname = 0;
- String *mrename;
- if (current[NO_CPP] || !getCurrentClass()) {
- mrename = symname;
- } else {
- assert(!current[NO_CPP]);
- if (current[STATIC_FUNC] || current[MEMBER_FUNC]) {
- mrename = Swig_name_member(getNSpace(), getClassPrefix(), symname);
- } else {
- mrename = symname;
- }
- }
- wrapname = Swig_name_wrapper(mrename);
- registerMethod(n, wrapname, luaScope);
- }
- /* -----------------------------------------------------------------------
- * registerMethod()
- *
- * Add method to the "methods" C array of given namespace/class
- * ---------------------------------------------------------------------- */
- void registerMethod(Node *n, String* wname, String *luaScope) {
- assert(n);
- Hash *nspaceHash = getCArraysHash(luaScope);
- String *s_ns_methods_tab = Getattr(nspaceHash, "methods");
- String *lua_name = Getattr(n, "lua:name");
- if (elua_ltr || eluac_ltr)
- Printv(s_ns_methods_tab, tab4, "{LSTRKEY(\"", lua_name, "\")", ", LFUNCVAL(", wname, ")", "},\n", NIL);
- else
- Printv(s_ns_methods_tab, tab4, "{ \"", lua_name, "\", ", wname, "},\n", NIL);
- // Add to the metatable if method starts with '__'
- const char * tn = Char(lua_name);
- if (tn[0]=='_' && tn[1] == '_' && !eluac_ltr) {
- String *metatable_tab = Getattr(nspaceHash, "metatable");
- assert(metatable_tab);
- if (elua_ltr)
- Printv(metatable_tab, tab4, "{LSTRKEY(\"", lua_name, "\")", ", LFUNCVAL(", wname, ")", "},\n", NIL);
- else
- Printv(metatable_tab, tab4, "{ \"", lua_name, "\", ", wname, "},\n", NIL);
- }
- }
- virtual int functionWrapper(Node *n) {
- REPORT("functionWrapper", n);
- String *name = Getattr(n, "name");
- String *iname = Getattr(n, "sym:name");
- String *lua_name = Getattr(n, "lua:name");
- assert(lua_name);
- SwigType *d = Getattr(n, "type");
- ParmList *l = Getattr(n, "parms");
- Parm *p;
- String *tm;
- int i;
- //Printf(stdout,"functionWrapper %s %s %d\n",name,iname,current);
- String *overname = 0;
- if (Getattr(n, "sym:overloaded")) {
- overname = Getattr(n, "sym:overname");
- } else {
- if (!luaAddSymbol(lua_name, n)) {
- return SWIG_ERROR;
- }
- }
- /* NEW LANGUAGE NOTE:***********************************************
- the wrapper object holds all the wrapper code
- we need to add a couple of local variables
- NEW LANGUAGE NOTE:END *********************************************** */
- Wrapper *f = NewWrapper();
- Wrapper_add_local(f, "SWIG_arg", "int SWIG_arg = 0");
- String *wname = Swig_name_wrapper(iname);
- if (overname) {
- Append(wname, overname);
- }
- if (current[CONSTRUCTOR]) {
- if (constructor_name != 0)
- Delete(constructor_name);
- constructor_name = Copy(wname);
- }
- /* NEW LANGUAGE NOTE:***********************************************
- the format of a lua fn is:
- static int wrap_XXX(lua_State* L){...}
- this line adds this into the wrapper code
- NEW LANGUAGE NOTE:END *********************************************** */
- Printv(f->def, "static int ", wname, "(lua_State* L) {", NIL);
- // SWIG_fail in lua leads to a call to lua_error() which calls longjmp()
- // which means the destructors of any live function-local C++ objects won't
- // get run. To avoid this happening, we wrap almost everything in the
- // function in a block, and end that right before lua_error() at which
- // point those destructors will get called.
- if (CPlusPlus) Append(f->def, "\n{");
- /* NEW LANGUAGE NOTE:***********************************************
- this prints the list of args, eg for a C fn
- int gcd(int x,int y);
- it will print
- int arg1;
- int arg2;
- NEW LANGUAGE NOTE:END *********************************************** */
- /* Write code to extract function parameters. */
- emit_parameter_variables(l, f);
- /* Attach the standard typemaps */
- emit_attach_parmmaps(l, f);
- Setattr(n, "wrap:parms", l);
- /* Get number of required and total arguments */
- int num_arguments = emit_num_arguments(l);
- int num_required = emit_num_required(l);
- int varargs = emit_isvarargs(l);
- // Check if we have to ignore arguments that are passed by LUA.
- // Needed for unary minus, where lua passes two arguments and
- // we have to ignore the second.
- int args_to_ignore = 0;
- if (Getattr(n, "lua:ignore_args")) {
- args_to_ignore = GetInt(n, "lua:ignore_args");
- }
- /* NEW LANGUAGE NOTE:***********************************************
- from here on in, it gets rather hairy
- this is the code to convert from the scripting language to C/C++
- some of the stuff will refer to the typemaps code written in your swig file
- (lua.swg), and some is done in the code here
- I suppose you could do all the conversion in C, but it would be a nightmare to do
- NEW LANGUAGE NOTE:END *********************************************** */
- /* Generate code for argument marshalling */
- // String *description = NewString("");
- /* NEW LANGUAGE NOTE:***********************************************
- argument_check is a new feature I added to check types of arguments:
- eg for int gcd(int,int)
- I want to check that arg1 & arg2 really are integers
- NEW LANGUAGE NOTE:END *********************************************** */
- String *argument_check = NewString("");
- String *argument_parse = NewString("");
- String *checkfn = NULL;
- char source[64];
- Printf(argument_check, "SWIG_check_num_args(\"%s\",%d,%d)\n", Swig_name_str(n), num_required + args_to_ignore, num_arguments + args_to_ignore);
- for (i = 0, p = l; i < num_arguments; i++) {
- while (checkAttribute(p, "tmap:in:numinputs", "0")) {
- p = Getattr(p, "tmap:in:next");
- }
- SwigType *pt = Getattr(p, "type");
- /* Look for an input typemap */
- sprintf(source, "%d", i + 1);
- if ((tm = Getattr(p, "tmap:in"))) {
- Replaceall(tm, "$input", source);
- Setattr(p, "emit:input", source);
- if (Getattr(p, "wrap:disown") || (Getattr(p, "tmap:in:disown"))) {
- Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN");
- } else {
- Replaceall(tm, "$disown", "0");
- }
- /* NEW LANGUAGE NOTE:***********************************************
- look for a 'checkfn' typemap
- this an additional parameter added to the in typemap
- if found the type will be tested for
- this will result in code either in the
- argument_check or argument_parse string
- NEW LANGUAGE NOTE:END *********************************************** */
- if ((checkfn = Getattr(p, "tmap:in:checkfn"))) {
- if (i < num_required) {
- Printf(argument_check, "if(!%s(L,%s))", checkfn, source);
- } else {
- Printf(argument_check, "if(lua_gettop(L)>=%s && !%s(L,%s))", source, checkfn, source);
- }
- Printf(argument_check, " SWIG_fail_arg(\"%s\",%s,\"%s\");\n", Swig_name_str(n), source, SwigType_str(pt, 0));
- }
- /* NEW LANGUAGE NOTE:***********************************************
- lua states the number of arguments passed to a function using the fn
- lua_gettop()
- we can use this to deal with default arguments
- NEW LANGUAGE NOTE:END *********************************************** */
- if (i < num_required) {
- Printf(argument_parse, "%s\n", tm);
- } else {
- Printf(argument_parse, "if(lua_gettop(L)>=%s){%s}\n", source, tm);
- }
- p = Getattr(p, "tmap:in:next");
- continue;
- } else {
- /* NEW LANGUAGE NOTE:***********************************************
- // why is this code not called when I don't have a typemap?
- // instead of giving a warning, no code is generated
- NEW LANGUAGE NOTE:END *********************************************** */
- Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
- break;
- }
- }
- // add all argcheck code
- Printv(f->code, argument_check, argument_parse, NIL);
- /* Check for trailing varargs */
- if (varargs) {
- if (p && (tm = Getattr(p, "tmap:in"))) {
- Replaceall(tm, "$input", "varargs");
- Printv(f->code, tm, "\n", NIL);
- }
- }
- /* Insert constraint checking code */
- for (p = l; p;) {
- if ((tm = Getattr(p, "tmap:check"))) {
- Printv(f->code, tm, "\n", NIL);
- p = Getattr(p, "tmap:check:next");
- } else {
- p = nextSibling(p);
- }
- }
- /* Insert cleanup code */
- String *cleanup = NewString("");
- for (p = l; p;) {
- if ((tm = Getattr(p, "tmap:freearg"))) {
- Printv(cleanup, tm, "\n", NIL);
- p = Getattr(p, "tmap:freearg:next");
- } else {
- p = nextSibling(p);
- }
- }
- /* Insert argument output code */
- String *outarg = NewString("");
- for (p = l; p;) {
- if ((tm = Getattr(p, "tmap:argout"))) {
- // // managing the number of returning variables
- // if (numoutputs=Getattr(p,"tmap:argout:numoutputs")){
- // int i=GetInt(p,"tmap:argout:numoutputs");
- // printf("got argout:numoutputs of %d\n",i);
- // returnval+=GetInt(p,"tmap:argout:numoutputs");
- // }
- // else returnval++;
- Replaceall(tm, "$arg", Getattr(p, "emit:input"));
- Replaceall(tm, "$input", Getattr(p, "emit:input"));
- Printv(outarg, tm, "\n", NIL);
- p = Getattr(p, "tmap:argout:next");
- } else {
- p = nextSibling(p);
- }
- }
- // Remember C name of the wrapping function
- Setattr(n, "wrap:name", wname);
- /* Emit the function call */
- String *actioncode = emit_action(n);
- /* NEW LANGUAGE NOTE:***********************************************
- FIXME:
- returns 1 if there is a void return type
- this is because there is a typemap for void
- NEW LANGUAGE NOTE:END *********************************************** */
- // Return value if necessary
- if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
- // managing the number of returning variables
- // if (numoutputs=Getattr(tm,"numoutputs")){
- // int i=GetInt(tm,"numoutputs");
- // printf("return numoutputs %d\n",i);
- // returnval+=GetInt(tm,"numoutputs");
- // }
- // else returnval++;
- if (GetFlag(n, "feature:new")) {
- Replaceall(tm, "$owner", "1");
- } else {
- Replaceall(tm, "$owner", "0");
- }
- Printf(f->code, "%s\n", tm);
- // returnval++;
- } else {
- 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);
- }
- emit_return_variable(n, d, f);
- /* Output argument output code */
- Printv(f->code, outarg, NIL);
- /* Output cleanup code */
- Printv(f->code, cleanup, NIL);
- /* Look to see if there is any newfree cleanup code */
- if (GetFlag(n, "feature:new")) {
- if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
- Printf(f->code, "%s\n", tm);
- }
- }
- /* See if there is any return cleanup code */
- if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
- Printf(f->code, "%s\n", tm);
- }
- /* Close the function */
- Printv(f->code, "return SWIG_arg;\n", NIL);
- // add the failure cleanup code:
- Printv(f->code, "\nfail: SWIGUNUSED;\n", "$cleanup", NIL);
- if (CPlusPlus) Append(f->code, "}\n");
- Printv(f->code, "lua_error(L);\n", NIL);
- // lua_error() calls longjmp() but we need a dummy return to avoid compiler
- // warnings.
- Printv(f->code, "return 0;\n", NIL);
- Printf(f->code, "}\n");
- /* Substitute the cleanup code */
- Replaceall(f->code, "$cleanup", cleanup);
- /* Substitute the function name */
- Replaceall(f->code, "$symname", iname);
- Replaceall(f->code, "$result", Swig_cresult_name());
- /* Dump the function out */
- /* in Lua we will not emit the destructor as a wrapper function,
- Lua will automatically call the destructor when the object is free'd
- However: you cannot just skip this function as it will not emit
- any custom destructor (using %extend), as you need to call emit_action()
- Therefore we go though the whole function,
- but do not write the code into the wrapper
- */
- if (!current[DESTRUCTOR]) {
- Wrapper_print(f, f_wrappers);
- }
- /* NEW LANGUAGE NOTE:***********************************************
- register the function in SWIG
- different language mappings seem to use different ideas
- NEW LANGUAGE NOTE:END *********************************************** */
- /* Now register the function with the interpreter. */
- int result = SWIG_OK;
- if (Getattr(n, "sym:overloaded")) {
- if (!Getattr(n, "sym:nextSibling")) {
- result = dispatchFunction(n);
- }
- }
- Delete(argument_check);
- Delete(argument_parse);
- Delete(cleanup);
- Delete(outarg);
- // Delete(description);
- DelWrapper(f);
- return result;
- }
- /* ------------------------------------------------------------
- * dispatchFunction()
- *
- * Emit overloading dispatch function
- * ------------------------------------------------------------ */
- /* NEW LANGUAGE NOTE:***********************************************
- This is an extra function used for overloading of functions
- it checks the args & then calls the relevant fn
- most of the real work in again typemaps:
- look for %typecheck(SWIG_TYPECHECK_*) in the .swg file
- NEW LANGUAGE NOTE:END *********************************************** */
- int dispatchFunction(Node *n) {
- //REPORT("dispatchFunction", n);
- /* Last node in overloaded chain */
- int maxargs;
- String *tmp = NewString("");
- String *dispatch = Swig_overload_dispatch(n, "return %s(L);", &maxargs);
- /* Generate a dispatch wrapper for all overloaded functions */
- Wrapper *f = NewWrapper();
- String *symname = Getattr(n, "sym:name");
- String *lua_name = Getattr(n, "lua:name");
- assert(lua_name);
- String *wname = Swig_name_wrapper(symname);
- //Printf(stdout,"Swig_overload_dispatch %s %s '%s' %d\n",symname,wname,dispatch,maxargs);
- if (!luaAddSymbol(lua_name, n)) {
- DelWrapper(f);
- Delete(dispatch);
- Delete(tmp);
- return SWIG_ERROR;
- }
- Printv(f->def, "static int ", wname, "(lua_State* L) {", NIL);
- Wrapper_add_local(f, "argc", "int argc");
- Printf(tmp, "int argv[%d]={1", maxargs + 1);
- for (int i = 1; i <= maxargs; i++) {
- Printf(tmp, ",%d", i + 1);
- }
- Printf(tmp, "}");
- Wrapper_add_local(f, "argv", tmp);
- Printf(f->code, "argc = lua_gettop(L);\n");
- Replaceall(dispatch, "$args", "self,args");
- Printv(f->code, dispatch, "\n", NIL);
- Node *sibl = n;
- while (Getattr(sibl, "sym:previousSibling"))
- sibl = Getattr(sibl, "sym:previousSibling"); // go all the way up
- String *protoTypes = NewString("");
- do {
- String *fulldecl = Swig_name_decl(sibl);
- Printf(protoTypes, "\n\" %s\\n\"", fulldecl);
- Delete(fulldecl);
- } while ((sibl = Getattr(sibl, "sym:nextSibling")));
- Printf(f->code, "SWIG_Lua_pusherrstring(L,\"Wrong arguments for overloaded function '%s'\\n\"\n"
- "\" Possible C/C++ prototypes are:\\n\"%s);\n", symname, protoTypes);
- Delete(protoTypes);
- Printf(f->code, "lua_error(L);return 0;\n");
- Printv(f->code, "}\n", NIL);
- Wrapper_print(f, f_wrappers);
- // Remember C name of the wrapping function
- Setattr(n, "wrap:name", wname);
- if (current[CONSTRUCTOR]) {
- if (constructor_name != 0)
- Delete(constructor_name);
- constructor_name = Copy(wname);
- }
- DelWrapper(f);
- Delete(dispatch);
- Delete(tmp);
- return SWIG_OK;
- }
- /* ------------------------------------------------------------
- * Add variable to "attributes" C arrays of given namespace or class.
- * Input is node. Based on the state of "current" array it determines
- * the name of the getter function, setter function etc and calls
- * registerVariable overload with necessary params.
- * Lua scope could be overwritten. (Used only for backward compatibility)
- * ------------------------------------------------------------ */
- void registerVariable(Node *n, bool overwrite = false, String *overwriteLuaScope = 0) {
- int assignable = is_assignable(n);
- String *symname = Getattr(n, "sym:name");
- assert(symname);
- // Lua scope. It is not symbol NSpace, it is the actual key to retrieve getCArraysHash.
- String *luaScope = luaCurrentSymbolNSpace();
- if (overwrite)
- luaScope = overwriteLuaScope;
- // Getter and setter
- String *getName = 0;
- String *setName = 0;
- String *mrename = 0;
- if (current[NO_CPP] || !getCurrentClass()) {
- // Global variable
- getName = Swig_name_get(getNSpace(), symname);
- if (assignable)
- setName = Swig_name_set(getNSpace(), symname);
- } else {
- assert(!current[NO_CPP]);
- if (current[STATIC_VAR] ) {
- mrename = Swig_name_member(getNSpace(), getClassPrefix(), symname);
- getName = Swig_name_get(0, mrename);
- if (assignable)
- setName = Swig_name_set(0, mrename);
- } else if (current[MEMBER_VAR]) {
- mrename = Swig_name_member(0, getClassPrefix(), symname);
- getName = Swig_name_get(getNSpace(), mrename);
- if (assignable)
- setName = Swig_name_set(getNSpace(), mrename);
- } else {
- assert(false);
- }
- }
- getName = Swig_name_wrapper(getName);
- if (setName)
- setName = Swig_name_wrapper(setName);
- registerVariable(luaScope, n, getName, setName);
- }
- /* ------------------------------------------------------------
- * registerVariable()
- *
- * Add variable to the "attributes" (or "get"/"set" in
- * case of elua_ltr) C arrays of given namespace or class
- * ------------------------------------------------------------ */
- void registerVariable(String *lua_nspace_or_class_name, Node *n, String *getName, String *setName) {
- String *unassignable = NewString("SWIG_Lua_set_immutable");
- if (setName == 0 || GetFlag(n, "feature:immutable")) {
- setName = unassignable;
- }
- Hash *nspaceHash = getCArraysHash(lua_nspace_or_class_name);
- String *s_ns_methods_tab = Getattr(nspaceHash, "methods");
- String *s_ns_var_tab = Getattr(nspaceHash, "attributes");
- String *lua_name = Getattr(n, "lua:name");
- if (elua_ltr) {
- String *s_ns_dot_get = Getattr(nspaceHash, "get");
- String *s_ns_dot_set = Getattr(nspaceHash, "set");
- Printf(s_ns_dot_get, "%s{LSTRKEY(\"%s\"), LFUNCVAL(%s)},\n", tab4, lua_name, getName);
- Printf(s_ns_dot_set, "%s{LSTRKEY(\"%s\"), LFUNCVAL(%s)},\n", tab4, lua_name, setName);
- } else if (eluac_ltr) {
- Printv(s_ns_methods_tab, tab4, "{LSTRKEY(\"", lua_name, "_get", "\")", ", LFUNCVAL(", getName, ")", "},\n", NIL);
- Printv(s_ns_methods_tab, tab4, "{LSTRKEY(\"", lua_name, "_set", "\")", ", LFUNCVAL(", setName, ")", "},\n", NIL);
- } else {
- Printf(s_ns_var_tab, "%s{ \"%s\", %s, %s },\n", tab4, lua_name, getName, setName);
- }
- }
- /* ------------------------------------------------------------
- * variableWrapper()
- * ------------------------------------------------------------ */
- virtual int variableWrapper(Node *n) {
- /* NEW LANGUAGE NOTE:***********************************************
- Language::variableWrapper(n) will generate two wrapper fns
- Foo_get & Foo_set by calling functionWrapper()
- so we will just add these into the variable lists
- ideally we should not have registered these as functions,
- only WRT this variable will look into this later.
- NEW LANGUAGE NOTE:END *********************************************** */
- // REPORT("variableWrapper", n);
- String *lua_name = Getattr(n, "lua:name");
- assert(lua_name);
- (void)lua_name;
- current[VARIABLE] = true;
- // let SWIG generate the wrappers
- int result = Language::variableWrapper(n);
-
- // It is impossible to use registerVariable, because sym:name of the Node is currently
- // in an undefined state - the callees of this function may have modified it.
- // registerVariable should be used from respective callees.*
- current[VARIABLE] = false;
- return result;
- }
- /* ------------------------------------------------------------
- * Add constant to appropriate C array. constantRecord is an array record.
- * Actually, in current implementation it is resolved consttab typemap
- * ------------------------------------------------------------ */
- void registerConstant(String *nspace, String *constantRecord) {
- Hash *nspaceHash = getCArraysHash(nspace);
- String *s_const_tab = 0;
- if (eluac_ltr || elua_ltr)
- // In elua everything goes to "methods" tab
- s_const_tab = Getattr(nspaceHash, "methods");
- else
- s_const_tab = Getattr(nspaceHash, "constants");
- assert(s_const_tab);
- Printf(s_const_tab, " %s,\n", constantRecord);
- if ((eluac_ltr || elua_ltr) && old_metatable_bindings) {
- s_const_tab = Getattr(nspaceHash, "constants");
- assert(s_const_tab);
- Printf(s_const_tab, " %s,\n", constantRecord);
- }
- }
- /* ------------------------------------------------------------
- * constantWrapper()
- * ------------------------------------------------------------ */
- virtual int constantWrapper(Node *n) {
- REPORT("constantWrapper", n);
- String *name = Getattr(n, "name");
- String *iname = Getattr(n, "sym:name");
- String *lua_name = Getattr(n, "lua:name");
- if (lua_name == 0)
- lua_name = iname;
- String *nsname = Copy(iname);
- SwigType *type = Getattr(n, "type");
- String *rawval = Getattr(n, "rawval");
- String *value = rawval ? rawval : Getattr(n, "value");
- String *tm;
- String *lua_name_v2 = 0;
- String *tm_v2 = 0;
- String *iname_v2 = 0;
- Node *n_v2 = 0;
- if (!luaAddSymbol(lua_name, n))
- return SWIG_ERROR;
- Swig_save("lua_constantMember", n, "sym:name", NIL);
- Setattr(n, "sym:name", lua_name);
- /* Special hook for member pointer */
- if (SwigType_type(type) == T_MPOINTER) {
- String *wname = Swig_name_wrapper(iname);
- Printf(f_wrappers, "static %s = %s;\n", SwigType_str(type, wname), value);
- value = Char(wname);
- }
- if ((tm = Swig_typemap_lookup("consttab", n, name, 0))) {
- Replaceall(tm, "$value", value);
- Replaceall(tm, "$nsname", nsname);
- registerConstant(luaCurrentSymbolNSpace(), tm);
- } else if ((tm = Swig_typemap_lookup("constcode", n, name, 0))) {
- Replaceall(tm, "$value", value);
- Replaceall(tm, "$nsname", nsname);
- Printf(f_init, "%s\n", tm);
- } else {
- Delete(nsname);
- nsname = 0;
- Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number, "Unsupported constant value.\n");
- Swig_restore(n);
- return SWIG_NOWRAP;
- }
- bool make_v2_compatible = old_metatable_bindings && getCurrentClass() && old_compatible_names;
- if (make_v2_compatible) {
- // Don't do anything for enums in C mode - they are already
- // wrapped correctly
- if (CPlusPlus || !current[ENUM_CONST]) {
- lua_name_v2 = Swig_name_member(0, proxy_class_name, lua_name);
- iname_v2 = Swig_name_member(0, proxy_class_name, iname);
- n_v2 = Copy(n);
- if (!luaAddSymbol(iname_v2, n, getNSpace())) {
- Swig_restore(n);
- return SWIG_ERROR;
- }
- Setattr(n_v2, "sym:name", lua_name_v2);
- tm_v2 = Swig_typemap_lookup("consttab", n_v2, name, 0);
- if (tm_v2) {
- Replaceall(tm_v2, "$value", value);
- Replaceall(tm_v2, "$nsname", nsname);
- registerConstant(getNSpace(), tm_v2);
- } else {
- tm_v2 = Swig_typemap_lookup("constcode", n_v2, name, 0);
- if (!tm_v2) {
- // This can't be.
- assert(false);
- Swig_restore(n);
- return SWIG_ERROR;
- }
- Replaceall(tm_v2, "$value", value);
- Replaceall(tm_v2, "$nsname", nsname);
- Printf(f_init, "%s\n", tm_v2);
- }
- Delete(n_v2);
- }
- }
- Swig_restore(n);
- Delete(nsname);
- return SWIG_OK;
- }
- /* ------------------------------------------------------------
- * nativeWrapper()
- * ------------------------------------------------------------ */
- virtual int nativeWrapper(Node *n) {
- // REPORT("nativeWrapper", n);
- String *symname = Getattr(n, "sym:name");
- String *wrapname = Getattr(n, "wrap:name");
- if (!luaAddSymbol(wrapname, n))
- return SWIG_ERROR;
- Hash *nspaceHash = getCArraysHash(getNSpace());
- String *s_ns_methods_tab = Getattr(nspaceHash, "methods");
- Printv(s_ns_methods_tab, tab4, "{ \"", symname, "\",", wrapname, "},\n", NIL);
- // return Language::nativeWrapper(n); // this does nothing...
- return SWIG_OK;
- }
- /* ------------------------------------------------------------
- * enumDeclaration()
- * ------------------------------------------------------------ */
- virtual int enumDeclaration(Node *n) {
- if (getCurrentClass() && (cplus_mode != PUBLIC))
- return SWIG_NOWRAP;
- current[STATIC_CONST] = true;
- current[ENUM_CONST] = true;
- // There is some slightly specific behaviour with enums. Basically,
- // their NSpace may be tracked separately. The code below tries to work around
- // this issue to some degree.
- // The idea is the same as in classHandler - to drop old names generation if
- // enum is in class in namespace.
- const int old_compatible_names_saved = old_compatible_names;
- if (getNSpace() || ( Getattr(n, "sym:nspace") != 0 && Len(Getattr(n, "sym:nspace")) > 0 ) ) {
- old_compatible_names = 0;
- }
- int result = Language::enumDeclaration(n);
- current[STATIC_CONST] = false;
- current[ENUM_CONST] = false;
- old_compatible_names = old_compatible_names_saved;
- return result;
- }
- /* ------------------------------------------------------------
- * enumvalueDeclaration()
- * ------------------------------------------------------------ */
- virtual int enumvalueDeclaration(Node *n) {
- if (getCurrentClass() && (cplus_mode != PUBLIC))
- return SWIG_NOWRAP;
- Swig_require("enumvalueDeclaration", n, "*name", "?value", "*sym:name", NIL);
- String *symname = Getattr(n, "sym:name");
- String *value = Getattr(n, "value");
- String *name = Getattr(n, "name");
- String *tmpValue;
- Node *parent = parentNode(n);
- if (value)
- tmpValue = NewString(value);
- else
- tmpValue = NewString(name);
- Setattr(n, "value", tmpValue);
- Setattr(n, "name", tmpValue); /* for wrapping of enums in a namespace when emit_action is used */
- if (GetFlag(parent, "scopedenum")) {
- symname = Swig_name_member(0, Getattr(parent, "sym:name"), symname);
- Setattr(n, "sym:name", symname);
- Delete(symname);
- }
- int result = constantWrapper(n);
- Delete(tmpValue);
- Swig_restore(n);
- return result;
- }
- /* ------------------------------------------------------------
- * classDeclaration()
- * ------------------------------------------------------------ */
- virtual int classDeclaration(Node *n) {
- return Language::classDeclaration(n);
- }
- /* ------------------------------------------------------------
- * Helper function that adds record to appropriate C arrays
- * ------------------------------------------------------------ */
- void registerClass(String *scope, String *wrap_class) {
- assert(wrap_class);
- Hash *nspaceHash = getCArraysHash(scope);
- String *ns_classes = Getattr(nspaceHash, "classes");
- Printv(ns_classes, "&", wrap_class, ",\n", NIL);
- if (elua_ltr || eluac_ltr) {
- String *ns_methods = Getattr(nspaceHash, "methods");
- Hash *class_hash = getCArraysHash(class_static_nspace);
- assert(class_hash);
- String *cls_methods = Getattr(class_hash, "methods:name");
- assert(cls_methods);
- Printv(ns_methods, tab4, "{LSTRKEY(\"", proxy_class_name, "\")", ", LROVAL(", cls_methods, ")", "},\n", NIL);
- }
- }
- /* ------------------------------------------------------------
- * classHandler()
- * ------------------------------------------------------------ */
- virtual int classHandler(Node *n) {
- //REPORT("classHandler", n);
- String *mangled_full_proxy_class_name = 0;
- String *destructor_name = 0;
- String *nspace = getNSpace();
- constructor_name = 0;
- have_constructor = 0;
- have_destructor = 0;
- destructor_action = 0;
- assert(class_static_nspace == 0);
- assert(full_proxy_class_name == 0);
- assert(proxy_class_name == 0);
- current[NO_CPP] = false;
- proxy_class_name = Getattr(n, "sym:name");
- // We have to enforce nspace here, because technically we are already
- // inside class parsing (getCurrentClass != 0), but we should register
- // class in its parent namespace
- if (!luaAddSymbol(proxy_class_name, n, nspace))
- return SWIG_ERROR;
- if (nspace == 0)
- full_proxy_class_name = NewStringf("%s", proxy_class_name);
- else
- full_proxy_class_name = NewStringf("%s.%s", nspace, proxy_class_name);
- assert(full_proxy_class_name);
- mangled_full_proxy_class_name = Swig_name_mangle(full_proxy_class_name);
- SwigType *t = Copy(Getattr(n, "name"));
- SwigType *fr_t = SwigType_typedef_resolve_all(t); /* Create fully resolved type */
- SwigType *t_tmp = 0;
- t_tmp = SwigType_typedef_qualified(fr_t); // Temporal variable
- Delete(fr_t);
- fr_t = SwigType_strip_qualifiers(t_tmp);
- String *mangled_fr_t = 0;
- mangled_fr_t = SwigType_manglestr(fr_t);
- // not sure exactly how this works,
- // but tcl has a static hashtable of all classes emitted and then only emits code for them once.
- // this fixes issues in test suites: template_default2 & template_specialization
- // * if i understand correctly, this is a bug.
- // * consider effect on template_specialization_defarg
- static Hash *emitted = NewHash();
- if (GetFlag(emitted, mangled_fr_t)) {
- full_proxy_class_name = 0;
- proxy_class_name = 0;
- return SWIG_NOWRAP;
- }
- SetFlag(emitted, mangled_fr_t);
- // We treat class T as both 'class' and 'namespace'. All static members, attributes
- // and constants are considered part of namespace T, all members - part of the 'class'
- // Now, here is a trick. Static methods, attributes and non-static methods and attributes
- // are described with same structures - swig_lua_attribute/swig_lua_method. Instead of calling
- // getCArraysHash(class name) to initialize things for static methods/attributes and then
- // manually doing same initialization for non-static methods, we call getCArraysHash 2 times:
- // 1) With name "class name" + "." + "SwigStatic" to initialize static things
- // 2) With "class name" to initialize non-static things
- Hash *instance_cls = getCArraysHash(full_proxy_class_name, false);
- assert(instance_cls);
- String *s_attr_tab_name = Getattr(instance_cls, "attributes:name");
- String *s_methods_tab_name = Getattr(instance_cls, "methods:name");
- SetFlag(instance_cls, "lua:no_namespaces");
- SetFlag(instance_cls, "lua:no_classes");
- SetFlag(instance_cls, "lua:class_instance");
- /* There is no use for "constants", "classes" and "namespaces" arrays.
- * All constants are considered part of static part of class.
- */
- class_static_nspace = NewStringf("%s%sSwigStatic", full_proxy_class_name, NSPACE_SEPARATOR);
- Hash *static_cls = getCArraysHash(class_static_nspace, false);
- assert(static_cls);
- SetFlag(static_cls, "lua:no_namespaces");
- SetFlag(static_cls, "lua:class_static");
- // Notifying instance_cls and static_cls hashes about each other
- Setattr(instance_cls, "lua:class_instance:static_hash", static_cls);
- Setattr(static_cls, "lua:class_static:instance_hash", instance_cls);
- const int old_compatible_names_saved = old_compatible_names;
- // If class has %nspace enabled, then generation of backward compatible names
- // should be disabled
- if (getNSpace()) {
- old_compatible_names = 0;
- }
- /* There is no use for "classes" and "namespaces" arrays. Subclasses are not supported
- * by SWIG and namespaces couldn't be nested inside classes (C++ Standard)
- */
- // Generate normal wrappers
- Language::classHandler(n);
- old_compatible_names = old_compatible_names_saved;
- SwigType_add_pointer(t);
- // Catch all: eg. a class with only static functions and/or variables will not have 'remembered'
- String *wrap_class_name = Swig_name_wrapper(NewStringf("class_%s", mangled_full_proxy_class_name));
- String *wrap_class = NewStringf("&%s", wrap_class_name);
- SwigType_remember_clientdata(t, wrap_class);
- String *rt = Copy(getClassType());
- SwigType_add_pointer(rt);
- // Adding class to appropriate namespace
- registerClass(nspace, wrap_class_name);
- Hash *nspaceHash = getCArraysHash(nspace);
- // Register the class structure with the type checker
- // Printf(f_init,"SWIG_TypeClientData(SWIGTYPE%s, (void *) &_wrap_class_%s);\n", SwigType_manglestr(t), mangled_full_proxy_class_name);
- // emit a function to be called to delete the object
- if (have_destructor) {
- destructor_name = NewStringf("swig_delete_%s", mangled_full_proxy_class_name);
- Printv(f_wrappers, "static void ", destructor_name, "(void *obj) {\n", NIL);
- if (destructor_action) {
- Printv(f_wrappers, SwigType_str(rt, "arg1"), " = (", SwigType_str(rt, 0), ") obj;\n", NIL);
- Printv(f_wrappers, destructor_action, "\n", NIL);
- } else {
- if (CPlusPlus) {
- Printv(f_wrappers, " delete (", SwigType_str(rt, 0), ") obj;\n", NIL);
- } else {
- Printv(f_wrappers, " free((char *) obj);\n", NIL);
- }
- }
- Printf(f_wrappers, "}\n");
- }
- // Wrap constructor wrapper into one more proxy function. It will be used as class namespace __call method, thus
- // allowing both
- // Module.ClassName.StaticMethod to access static method/variable/constant
- // Module.ClassName() to create new object
- if (have_constructor) {
- assert(constructor_name);
- String *constructor_proxy_name = NewStringf("_proxy_%s", constructor_name);
- Printv(f_wrappers, "static int ", constructor_proxy_name, "(lua_State *L) {\n", NIL);
- Printv(f_wrappers,
- tab4, "assert(lua_istable(L,1));\n",
- tab4, "lua_pushcfunction(L,", constructor_name, ");\n",
- tab4, "assert(!lua_isnil(L,-1));\n",
- tab4, "lua_replace(L,1); /* replace our table with real constructor */\n",
- tab4, "lua_call(L,lua_gettop(L)-1,1);\n",
- tab4, "return 1;\n}\n", NIL);
- Delete(constructor_name);
- constructor_name = constructor_proxy_name;
- if (elua_ltr) {
- String *static_cls_metatable_tab = Getattr(static_cls, "metatable");
- assert(static_cls_metatable_tab);
- Printf(static_cls_metatable_tab, " {LSTRKEY(\"__call\"), LFUNCVAL(%s)},\n", constructor_name);
- } else if (eluac_ltr) {
- String *ns_methods_tab = Getattr(nspaceHash, "methods");
- assert(ns_methods_tab);
- Printv(ns_methods_tab, tab4, "{LSTRKEY(\"", "new_", proxy_class_name, "\")", ", LFUNCVAL(", constructor_name, ")", "},\n", NIL);
- }
- }
- if (have_destructor) {
- if (eluac_ltr) {
- String *ns_methods_tab = Getattr(nspaceHash, "methods");
- assert(ns_methods_tab);
- Printv(ns_methods_tab, tab4, "{LSTRKEY(\"", "free_", mangled_full_proxy_class_name, "\")", ", LFUNCVAL(", destructor_name, ")", "},\n", NIL);
- }
- }
- closeCArraysHash(full_proxy_class_name, f_wrappers);
- closeCArraysHash(class_static_nspace, f_wrappers);
- // Handle inheritance
- // note: with the idea of class hierarchies spread over multiple modules
- // cf test-suite: imports.i
- // it is not possible to just add the pointers to the base classes to the code
- // (as sometimes these classes are not present)
- // therefore we instead hold the name of the base class and a null pointer
- // at runtime: we can query the swig type manager & see if the class exists
- // if so, we can get the pointer to the base class & replace the null pointer
- // if the type does not exist, then we cannot...
- String *base_class = NewString("");
- String *base_class_names = NewString("");
- List *baselist = Getattr(n, "bases");
- if (baselist && Len(baselist)) {
- Iterator b;
- b = First(baselist);
- while (b.item) {
- String *bname = Getattr(b.item, "name");
- if ((!bname) || GetFlag(b.item, "feature:ignore") || (!Getattr(b.item, "module"))) {
- b = Next(b);
- continue;
- }
- // stores a null pointer & the name
- Printf(base_class, "0,");
- Printf(base_class_names, "\"%s *\",", SwigType_namestr(bname));
- b = Next(b);
- }
- }
- // First, print class static part
- printCArraysDefinition(class_static_nspace, proxy_class_name, f_wrappers);
- assert(mangled_full_proxy_class_name);
- assert(base_class);
- assert(base_class_names);
- assert(proxy_class_name);
- assert(full_proxy_class_name);
-
- // Then print class instance part
- Printv(f_wrappers, "static swig_lua_class *swig_", mangled_full_proxy_class_name, "_bases[] = {", base_class, "0};\n", NIL);
- Delete(base_class);
- Printv(f_wrappers, "static const char *swig_", mangled_full_proxy_class_name, "_base_names[] = {", base_class_names, "0};\n", NIL);
- Delete(base_class_names);
- Printv(f_wrappers, "static swig_lua_class _wrap_class_", mangled_full_proxy_class_name, " = { \"", proxy_class_name, "\", \"", full_proxy_class_name, "\", &SWIGTYPE",
- SwigType_manglestr(t), ",", NIL);
- if (have_constructor) {
- Printv(f_wrappers, constructor_name, NIL);
- Delete(constructor_name);
- constructor_name = 0;
- } else {
- Printf(f_wrappers, "0");
- }
- if (have_destructor) {
- Printv(f_wrappers, ", ", destructor_name, NIL);
- } else {
- Printf(f_wrappers, ",0");
- }
- Printf(f_wrappers, ", %s, %s, &%s", s_methods_tab_name, s_attr_tab_name, Getattr(static_cls, "cname"));
-
- if (!eluac_ltr) {
- Printf(f_wrappers, ", %s", Getattr(instance_cls,"metatable:name"));
- }
- else
- Printf(f_wrappers, ", 0");
- Printf(f_wrappers, ", swig_%s_bases, swig_%s_base_names };\n\n", mangled_full_proxy_class_name, mangled_full_proxy_class_name);
- current[NO_CPP] = true;
- Delete(class_static_nspace);
- class_static_nspace = 0;
- Delete(mangled_full_proxy_class_name);
- mangled_full_proxy_class_name = 0;
- Delete(destructor_name);
- destructor_name = 0;
- Delete(full_proxy_class_name);
- full_proxy_class_name = 0;
- proxy_class_name = 0;
- return SWIG_OK;
- }
- /* ------------------------------------------------------------
- * memberfunctionHandler()
- * ------------------------------------------------------------ */
- virtual int memberfunctionHandler(Node *n) {
- String *symname = GetChar(n, "sym:name");
- //Printf(stdout,"memberfunctionHandler %s %s\n",name,iname);
- // Special case unary minus: LUA passes two parameters for the
- // wrapper function while we want only one. Tell our
- // functionWrapper to ignore a parameter.
- if (Cmp(symname, "__unm") == 0) {
- //Printf(stdout, "unary minus: ignore one argument\n");
- SetInt(n, "lua:ignore_args", 1);
- }
- current[MEMBER_FUNC] = true;
- Language::memberfunctionHandler(n);
- registerMethod(n);
- current[MEMBER_FUNC] = false;
- return SWIG_OK;
- }
- /* ------------------------------------------------------------
- * membervariableHandler()
- * ------------------------------------------------------------ */
- virtual int membervariableHandler(Node *n) {
- // REPORT("membervariableHandler",n);
- current[MEMBER_VAR] = true;
- Language::membervariableHandler(n);
- registerVariable(n);
- current[MEMBER_VAR] = false;
- return SWIG_OK;
- }
- /* ------------------------------------------------------------
- * constructorHandler()
- *
- * Method for adding C++ member constructor
- * ------------------------------------------------------------ */
- virtual int constructorHandler(Node *n) {
- // REPORT("constructorHandler", n);
- current[CONSTRUCTOR] = true;
- Language::constructorHandler(n);
- current[CONSTRUCTOR] = false;
- //constructor_name = NewString(Getattr(n, "sym:name"));
- have_constructor = 1;
- return SWIG_OK;
- }
- /* ------------------------------------------------------------
- * destructorHandler()
- * ------------------------------------------------------------ */
- virtual int destructorHandler(Node *n) {
- REPORT("destructorHandler", n);
- current[DESTRUCTOR] = true;
- Language::destructorHandler(n);
- current[DESTRUCTOR] = false;
- have_destructor = 1;
- destructor_action = Getattr(n, "wrap:action");
- return SWIG_OK;
- }
- /* ----------------------------------------------------------------------
- * globalfunctionHandler()
- *
- * It can be called:
- * 1. Usual C/C++ global function.
- * 2. During class parsing for functions declared/defined as friend
- * 3. During class parsing from staticmemberfunctionHandler
- * ---------------------------------------------------------------------- */
- virtual int globalfunctionHandler(Node *n) {
- bool oldVal = current[NO_CPP];
- if (!current[STATIC_FUNC]) // If static function, don't switch to NO_CPP
- current[NO_CPP] = true;
- const int result = Language::globalfunctionHandler(n);
-
- if (!current[STATIC_FUNC]) // Register only if not called from static function handler
- registerMethod(n);
- current[NO_CPP] = oldVal;
- return result;
- }
- /* ----------------------------------------------------------------------
- * globalvariableHandler()
- *
- * Sets "current" array correctly
- * ---------------------------------------------------------------------- */
- virtual int globalvariableHandler(Node *n) {
- bool oldVal = current[NO_CPP];
- current[GLOBAL_VAR] = true;
- current[NO_CPP] = true;
- const int result = Language::globalvariableHandler(n);
- registerVariable(n);
- current[GLOBAL_VAR] = false;
- current[NO_CPP] = oldVal;
- return result;
- }
- /* -----------------------------------------------------------------------
- * staticmemberfunctionHandler()
- *
- * Wrap a static C++ function
- * ---------------------------------------------------------------------- */
- virtual int staticmemberfunctionHandler(Node *n) {
- REPORT("staticmemberfunctionHandler", n);
- current[STATIC_FUNC] = true;
- const int result = Language::staticmemberfunctionHandler(n);
- registerMethod(n);
- if (old_metatable_bindings && result == SWIG_OK && old_compatible_names) {
- Swig_require("lua_staticmemberfunctionHandler", n, "*lua:name", NIL);
- String *lua_name = Getattr(n, "lua:name");
- // Although this function uses Swig_name_member, it actually generates the Lua name,
- // not the C++ name. This is because an earlier version used such a scheme for static function
- // name generation and we have to maintain backward compatibility.
- String *compat_name = Swig_name_member(0, proxy_class_name, lua_name);
- Setattr(n, "lua:name", compat_name);
- registerMethod(n, true, getNSpace());
- Delete(compat_name);
- Swig_restore(n);
- }
- current[STATIC_FUNC] = false;;
- return result;
- }
- /* ------------------------------------------------------------
- * memberconstantHandler()
- *
- * Create a C++ constant
- * ------------------------------------------------------------ */
- virtual int memberconstantHandler(Node *n) {
- REPORT("memberconstantHandler", n);
- int result = Language::memberconstantHandler(n);
- return result;
- }
- /* ---------------------------------------------------------------------
- * staticmembervariableHandler()
- * --------------------------------------------------------------------- */
- virtual int staticmembervariableHandler(Node *n) {
- REPORT("staticmembervariableHandler", n);
- current[STATIC_VAR] = true;
- //String *symname = Getattr(n, "sym:name");
- int result = Language::staticmembervariableHandler(n);
- if (!GetFlag(n, "wrappedasconstant")) {
- registerVariable(n);
- }
- if (result == SWIG_OK) {
- // This will add static member variable to the class namespace with name ClassName_VarName
- if (old_metatable_bindings && old_compatible_names) {
- Swig_save("lua_staticmembervariableHandler", n, "lua:name", NIL);
- String *lua_name = Getattr(n, "lua:name");
- // Although this function uses Swig_name_member, it actually generates the Lua name,
- // not the C++ name. This is because an earlier version used such a scheme for static function
- // name generation and we have to maintain backward compatibility.
- String *v2_name = Swig_name_member(NIL, proxy_class_name, lua_name);
- if (!GetFlag(n, "wrappedasconstant")) {
- Setattr(n, "lua:name", v2_name);
- // Registering static var in the class parent nspace
- registerVariable(n, true, getNSpace());
- }
- // If static member variable was wrapped as a constant, then
- // constant wrapper has already performed all actions necessary for old_metatable_bindings
- Delete(v2_name);
- Swig_restore(n);
- }
- }
- current[STATIC_VAR] = false;
- return result;
- }
- /* ---------------------------------------------------------------------
- * external runtime generation
- * --------------------------------------------------------------------- */
- /* This is to support the usage
- SWIG -external-runtime <filename>
- The code consists of two functions:
- String *runtimeCode() // returns a large string with all the runtimes in
- String *defaultExternalRuntimeFilename() // returns the default filename
- I am writing a generic solution, even though SWIG-Lua only has one file right now...
- */
- String *runtimeCode() {
- String *s = NewString("");
- const char *filenames[] = { "luarun.swg", 0 }; // must be 0 terminated
- emitLuaFlavor(s);
- String *sfile = 0;
- for (int i = 0; filenames[i] != 0; i++) {
- sfile = Swig_include_sys(filenames[i]);
- if (!sfile) {
- Printf(stderr, "*** Unable to open '%s'\n", filenames[i]);
- } else {
- Append(s, sfile);
- Delete(sfile);
- }
- }
- return s;
- }
- String *defaultExternalRuntimeFilename() {
- return NewString("swigluarun.h");
- }
- /* ---------------------------------------------------------------------
- * helpers
- * --------------------------------------------------------------------- */
- void emitLuaFlavor(String *s) {
- if (elua_emulate) {
- Printf(s, "/*This is only emulation!*/\n");
- Printf(s, "#define SWIG_LUA_TARGET SWIG_LUA_FLAVOR_ELUA\n");
- Printf(s, "#define SWIG_LUA_ELUA_EMULATE\n");
- } else if (elua_ltr)
- Printf(s, "#define SWIG_LUA_TARGET SWIG_LUA_FLAVOR_ELUA\n");
- else if (eluac_ltr)
- Printf(s, "#define SWIG_LUA_TARGET SWIG_LUA_FLAVOR_ELUAC\n");
- else
- Printf(s, "#define SWIG_LUA_TARGET SWIG_LUA_FLAVOR_LUA\n");
- }
- /* -----------------------------------------------------------------------------
- * escapeCode()
- *
- * This is to convert the string of Lua code into a proper string, which can then be
- * emitted into the C/C++ code.
- * Basically it is a lot of search & replacing of odd sequences
- * ---------------------------------------------------------------------------- */
- void escapeCode(String *str) {
- //Printf(f_runtime,"/* original luacode:[[[\n%s\n]]]\n*/\n",str);
- Chop(str); // trim
- Replace(str, "\\", "\\\\", DOH_REPLACE_ANY); // \ to \\ (this must be done first)
- Replace(str, "\"", "\\\"", DOH_REPLACE_ANY); // " to \"
- Replace(str, "\n", "\\n\"\n \"", DOH_REPLACE_ANY); // \n to \n"\n" (ie quoting every line)
- //Printf(f_runtime,"/* hacked luacode:[[[\n%s\n]]]\n*/\n",str);
- }
- /* -----------------------------------------------------------------------------
- * rawGetCArraysHash(String *name)
- *
- * A small helper to hide implementation of how CArrays hashes are stored
- * ---------------------------------------------------------------------------- */
- Hash *rawGetCArraysHash(const_String_or_char_ptr name) {
- Hash *scope = symbolScopeLookup( name ? name : "" );
- if(!scope)
- return 0;
- Hash *carrays_hash = Getattr(scope, "lua:cdata");
- return carrays_hash;
- }
-
- /* -----------------------------------------------------------------------------
- * getCArraysHash()
- *
- * Each namespace can be described with a hash that stores C arrays
- * where members of the namespace should be added. All these hashes are stored
- * inside the symbols table, in pseudo-symbol for every namespace.
- * nspace could be NULL (NSPACE_TODO), that means functions and variables and classes
- * that are not in any namespace (this is default for SWIG unless %nspace feature is used).
- * You can later set some attributes that will affect behaviour of functions that use this hash:
- * "lua:no_namespaces" will disable "namespaces" array.
- * "lua:no_classes" will disable "classes" array.
- * For every component ("attributes", "methods", etc) there are subcomponents:
- * XXX:name - name of the C array that stores data for component
- * XXX:decl - statement with forward declaration of this array;
- * Namespace could be automatically registered to its parent if 'reg' == true. This can only be
- * done during the first call (a.k.a when nspace is created).
- * ---------------------------------------------------------------------------- */
- Hash *getCArraysHash(String *nspace, bool reg = true) {
- Hash *scope = symbolScopeLookup(nspace ? nspace : "");
- if(!scope) {
- symbolAddScope( nspace ? nspace : "" );
- scope = symbolScopeLookup(nspace ? nspace : "");
- assert(scope);
- }
- Hash *carrays_hash = Getattr(scope, "lua:cdata");
- if (carrays_hash != 0)
- return carrays_hash;
- carrays_hash = NewHash();
- String *mangled_name = 0;
- if (nspace == 0 || Len(nspace) == 0)
- mangled_name = NewString("SwigModule");
- else
- mangled_name = Swig_name_mangle(nspace);
- String *cname = NewStringf("swig_%s", mangled_name);
- Setattr(carrays_hash, "cname", cname);
- String *attr_tab = NewString("");
- String *attr_tab_name = NewStringf("swig_%s_attributes", mangled_name);
- String *attr_tab_decl = NewString("");
- Printv(attr_tab, "static swig_lua_attribute ", NIL);
- Printv(attr_tab, attr_tab_name, "[]", NIL);
- Printv(attr_tab_decl, attr_tab, ";\n", NIL);
- Printv(attr_tab, " = {\n", NIL);
- Setattr(carrays_hash, "attributes", attr_tab);
- Setattr(carrays_hash, "attributes:name", attr_tab_name);
- Setattr(carrays_hash, "attributes:decl", attr_tab_decl);
- String *methods_tab = NewString("");
- String *methods_tab_name = NewStringf("swig_%s_methods", mangled_name);
- String *methods_tab_decl = NewString("");
- if (elua_ltr || eluac_ltr) // In this case methods array also acts as namespace rotable
- Printf(methods_tab, "const LUA_REG_TYPE ");
- else
- Printf(methods_tab, "static swig_lua_method ");
- Printv(methods_tab, methods_tab_name, "[]", NIL);
- Printv(methods_tab_decl, methods_tab, ";\n", NIL);
- Printv(methods_tab, "= {\n", NIL);
- Setattr(carrays_hash, "methods", methods_tab);
- Setattr(carrays_hash, "methods:name", methods_tab_name);
- Setattr(carrays_hash, "methods:decl", methods_tab_decl);
- String *const_tab = NewString("");
- String *const_tab_name = NewStringf("swig_%s_constants", mangled_name);
- String *const_tab_decl = NewString("");
- if (elua_ltr || eluac_ltr) // In this case const array holds rotable with namespace constants
- Printf(const_tab, "const LUA_REG_TYPE ");
- else
- Printf(const_tab, "static swig_lua_const_info ");
- Printv(const_tab, const_tab_name, "[]", NIL);
- Printv(const_tab_decl, const_tab, ";", NIL);
- Printv(const_tab, "= {\n", NIL);
- Setattr(carrays_hash, "constants", const_tab);
- Setattr(carrays_hash, "constants:name", const_tab_name);
- Setattr(carrays_hash, "constants:decl", const_tab_decl);
- String *classes_tab = NewString("");
- String *classes_tab_name = NewStringf("swig_%s_classes", mangled_name);
- String *classes_tab_decl = NewString("");
- Printf(classes_tab, "static swig_lua_class* ");
- Printv(classes_tab, classes_tab_name, "[]", NIL);
- Printv(classes_tab_decl, classes_tab, ";", NIL);
- Printv(classes_tab, "= {\n", NIL);
- Setattr(carrays_hash, "classes", classes_tab);
- Setattr(carrays_hash, "classes:name", classes_tab_name);
- Setattr(carrays_hash, "classes:decl", classes_tab_decl);
- String *namespaces_tab = NewString("");
- String *namespaces_tab_name = NewStringf("swig_%s_namespaces", mangled_name);
- String *namespaces_tab_decl = NewString("");
- Printf(namespaces_tab, "static swig_lua_namespace* ");
- Printv(namespaces_tab, namespaces_tab_name, "[]", NIL);
- Printv(namespaces_tab_decl, namespaces_tab, ";", NIL);
- Printv(namespaces_tab, " = {\n", NIL);
- Setattr(carrays_hash, "namespaces", namespaces_tab);
- Setattr(carrays_hash, "namespaces:name", namespaces_tab_name);
- Setattr(carrays_hash, "namespaces:decl", namespaces_tab_decl);
- if (elua_ltr) {
- String *get_tab = NewString("");
- String *get_tab_name = NewStringf("swig_%s_get", mangled_name);
- String *get_tab_decl = NewString("");
- Printv(get_tab, "const LUA_REG_TYPE ", get_tab_name, "[]", NIL);
- Printv(get_tab_decl, get_tab, ";", NIL);
- Printv(get_tab, " = {\n", NIL);
- Setattr(carrays_hash, "get", get_tab);
- Setattr(carrays_hash, "get:name", get_tab_name);
- Setattr(carrays_hash, "get:decl", get_tab_decl);
- String *set_tab = NewString("");
- String *set_tab_name = NewStringf("swig_%s_set", mangled_name);
- String *set_tab_decl = NewString("");
- Printv(set_tab, "const LUA_REG_TYPE ", set_tab_name, "[]", NIL);
- Printv(set_tab_decl, set_tab, ";", NIL);
- Printv(set_tab, " = {\n", NIL);
- Setattr(carrays_hash, "set", set_tab);
- Setattr(carrays_hash, "set:name", set_tab_name);
- Setattr(carrays_hash, "set:decl", set_tab_decl);
- }
- if (!eluac_ltr) {
- String *metatable_tab = NewString("");
- String *metatable_tab_name = NewStringf("swig_%s_meta", mangled_name);
- String *metatable_tab_decl = NewString("");
- if (elua_ltr) // In this case const array holds rotable with namespace constants
- Printf(metatable_tab, "const LUA_REG_TYPE ");
- else
- Printf(metatable_tab, "static swig_lua_method ");
- Printv(metatable_tab, metatable_tab_name, "[]", NIL);
- Printv(metatable_tab_decl, metatable_tab, ";", NIL);
- Printv(metatable_tab, " = {\n", NIL);
- Setattr(carrays_hash, "metatable", metatable_tab);
- Setattr(carrays_hash, "metatable:name", metatable_tab_name);
- Setattr(carrays_hash, "metatable:decl", metatable_tab_decl);
- }
- Setattr(scope, "lua:cdata", carrays_hash);
- assert(rawGetCArraysHash(nspace));
- if (reg && nspace != 0 && Len(nspace) != 0 && GetFlag(carrays_hash, "lua:no_reg") == 0) {
- // Split names into components
- List *components = Split(nspace, '.', -1);
- String *parent_path = NewString("");
- int len = Len(components);
- String *name = Copy(Getitem(components, len - 1));
- for (int i = 0; i < len - 1; i++) {
- if (i > 0)
- Printv(parent_path, NSPACE_SEPARATOR, NIL);
- String *item = Getitem(components, i);
- Printv(parent_path, item, NIL);
- }
- Hash *parent = getCArraysHash(parent_path, true);
- String *namespaces_tab = Getattr(parent, "namespaces");
- Printv(namespaces_tab, "&", cname, ",\n", NIL);
- if (elua_ltr || eluac_ltr) {
- String *methods_tab = Getattr(parent, "methods");
- Printv(methods_tab, tab4, "{LSTRKEY(\"", name, "\")", ", LROVAL(", methods_tab_name, ")", "},\n", NIL);
- }
- Setattr(carrays_hash, "name", name);
- Delete(components);
- Delete(parent_path);
- } else if (!reg) // This namespace shouldn't be registered. Lets remember it.
- SetFlag(carrays_hash, "lua:no_reg");
- Delete(mangled_name);
- mangled_name = 0;
- return carrays_hash;
- }
- /* -----------------------------------------------------------------------------
- * closeCArraysHash()
- *
- * Functions add end markers {0,0,...,0} to all arrays, prints them to
- * output and marks hash as closed (lua:closed). Consequent attempts to
- * close the same hash will result in an error.
- * closeCArraysHash DOES NOT print structure that describes namespace, it only
- * prints array. You can use printCArraysDefinition to print structure.
- * if "lua:no_namespaces" is set, then array for "namespaces" won't be printed
- * if "lua:no_classes" is set, then array for "classes" won't be printed
- * ----------------------------------------------------------------------------- */
- void closeCArraysHash(String *nspace, File *output) {
- Hash *carrays_hash = rawGetCArraysHash(nspace);
- assert(carrays_hash);
- assert(GetFlag(carrays_hash, "lua:closed") == 0);
- SetFlag(carrays_hash, "lua:closed");
- // Do arrays describe class instance part or class static part
- const int is_instance = GetFlag(carrays_hash, "lua:class_instance");
- String *attr_tab = Getattr(carrays_hash, "attributes");
- Printf(attr_tab, " {0,0,0}\n};\n");
- Printv(output, attr_tab, NIL);
- String *const_tab = Getattr(carrays_hash, "constants");
- String *const_tab_name = Getattr(carrays_hash, "constants:name");
- if (elua_ltr || eluac_ltr)
- Printv(const_tab, tab4, "{LNILKEY, LNILVAL}\n", "};\n", NIL);
- else
- Printf(const_tab, " {0,0,0,0,0,0}\n};\n");
-
- // For the sake of compiling with -Wall -Werror we print constants
- // only when necessary
- int need_constants = 0;
- if ( (elua_ltr || eluac_ltr) && (old_metatable_bindings) )
- need_constants = 1;
- else if (!is_instance) // static part need constants tab
- need_constants = 1;
- if (need_constants)
- Printv(output, const_tab, NIL);
- if (elua_ltr) {
- // Put forward declaration of metatable array
- Printv(output, "extern ", Getattr(carrays_hash, "metatable:decl"), "\n", NIL);
- }
- String *methods_tab = Getattr(carrays_hash, "methods");
- String *metatable_tab_name = Getattr(carrays_hash, "metatable:name");
- if (elua_ltr || eluac_ltr) {
- if (old_metatable_bindings)
- Printv(methods_tab, tab4, "{LSTRKEY(\"const\"), LROVAL(", const_tab_name, ")},\n", NIL);
- if (elua_ltr) {
- Printv(methods_tab, tab4, "{LSTRKEY(\"__metatable\"), LROVAL(", metatable_tab_name, ")},\n", NIL);
- }
- Printv(methods_tab, tab4, "{LSTRKEY(\"__disown\"), LFUNCVAL(SWIG_Lua_class_disown)},\n", NIL);
- Printv(methods_tab, tab4, "{LNILKEY, LNILVAL}\n};\n", NIL);
- } else
- Printf(methods_tab, " {0,0}\n};\n");
- Printv(output, methods_tab, NIL);
- if (!GetFlag(carrays_hash, "lua:no_classes")) {
- String *classes_tab = Getattr(carrays_hash, "classes");
- Printf(classes_tab, " 0\n};\n");
- Printv(output, classes_tab, NIL);
- }
- if (!GetFlag(carrays_hash, "lua:no_namespaces")) {
- String *namespaces_tab = Getattr(carrays_hash, "namespaces");
- Printf(namespaces_tab, " 0\n};\n");
- Printv(output, namespaces_tab, NIL);
- }
- if (elua_ltr) {
- String *get_tab = Getattr(carrays_hash, "get");
- String *set_tab = Getattr(carrays_hash, "set");
- Printv(get_tab, tab4, "{LNILKEY, LNILVAL}\n};\n", NIL);
- Printv(set_tab, tab4, "{LNILKEY, LNILVAL}\n};\n", NIL);
- Printv(output, get_tab, NIL);
- Printv(output, set_tab, NIL);
- }
- // Heuristic whether we need to print metatable or not.
- // For the sake of compiling with -Wall -Werror we don't print
- // metatable for static part.
- int need_metatable = 0;
- if (eluac_ltr)
- need_metatable = 0;
- else if(!is_instance)
- need_metatable = 0;
- else
- need_metatable = 1;
- if (need_metatable) {
- String *metatable_tab = Getattr(carrays_hash, "metatable");
- assert(metatable_tab);
- if (elua_ltr) {
- String *get_tab_name = Getattr(carrays_hash, "get:name");
- String *set_tab_name = Getattr(carrays_hash, "set:name");
- if (GetFlag(carrays_hash, "lua:class_instance")) {
- Printv(metatable_tab, tab4, "{LSTRKEY(\"__index\"), LFUNCVAL(SWIG_Lua_class_get)},\n", NIL);
- Printv(metatable_tab, tab4, "{LSTRKEY(\"__newindex\"), LFUNCVAL(SWIG_Lua_class_set)},\n", NIL);
- } else {
- Printv(metatable_tab, tab4, "{LSTRKEY(\"__index\"), LFUNCVAL(SWIG_Lua_namespace_get)},\n", NIL);
- Printv(metatable_tab, tab4, "{LSTRKEY(\"__newindex\"), LFUNCVAL(SWIG_Lua_namespace_set)},\n", NIL);
- }
- Printv(metatable_tab, tab4, "{LSTRKEY(\"__gc\"), LFUNCVAL(SWIG_Lua_class_destruct)},\n", NIL);
- Printv(metatable_tab, tab4, "{LSTRKEY(\".get\"), LROVAL(", get_tab_name, ")},\n", NIL);
- Printv(metatable_tab, tab4, "{LSTRKEY(\".set\"), LROVAL(", set_tab_name, ")},\n", NIL);
- Printv(metatable_tab, tab4, "{LSTRKEY(\".fn\"), LROVAL(", Getattr(carrays_hash, "methods:name"), ")},\n", NIL);
- if (GetFlag(carrays_hash, "lua:class_instance")) {
- String *static_cls = Getattr(carrays_hash, "lua:class_instance:static_hash");
- assert(static_cls);
- // static_cls is swig_lua_namespace. This structure can't be used with eLua(LTR)
- // Instead a structure describing its methods is used
- String *static_cls_cname = Getattr(static_cls, "methods:name");
- assert(static_cls_cname);
- Printv(metatable_tab, tab4, "{LSTRKEY(\".static\"), LROVAL(", static_cls_cname, ")},\n", NIL);
- // Put forward declaration of this array
- Printv(output, "extern ", Getattr(static_cls, "methods:decl"), "\n", NIL);
- } else if (GetFlag(carrays_hash, "lua:class_static")) {
- Hash *instance_cls = Getattr(carrays_hash, "lua:class_static:instance_hash");
- assert(instance_cls);
- String *instance_cls_metatable_name = Getattr(instance_cls, "metatable:name");
- assert(instance_cls_metatable_name);
- Printv(metatable_tab, tab4, "{LSTRKEY(\".instance\"), LROVAL(", instance_cls_metatable_name, ")},\n", NIL);
- }
- Printv(metatable_tab, tab4, "{LNILKEY, LNILVAL}\n};\n", NIL);
- } else {
- Printf(metatable_tab, " {0,0}\n};\n");
- }
- Printv(output, metatable_tab, NIL);
- }
- Printv(output, "\n", NIL);
- }
- /* -----------------------------------------------------------------------------
- * closeNamespaces()
- *
- * Recursively close all non-closed namespaces. Prints data to dataOutput.
- * ----------------------------------------------------------------------------- */
- void closeNamespaces(File *dataOutput) {
- // Special handling for empty module.
- if (symbolScopeLookup("") == 0 || rawGetCArraysHash("") == 0) {
- // Module is empty. Create hash for global scope in order to have swig_SwigModule
- // variable in resulting file
- getCArraysHash(0);
- }
- // Because we can't directly access 'symtabs', instead we access
- // top-level scope and look on all scope pseudo-symbols in it.
- Hash *top_scope = symbolScopeLookup("");
- assert(top_scope);
- Iterator ki = First(top_scope);
- List *to_close = NewList();
- while (ki.key) {
- assert(ki.item);
- if (Getattr(ki.item, "sym:scope")) {
- // We have a pseudo symbol. Lets get actual scope for this pseudo symbol
- Hash *carrays_hash = rawGetCArraysHash(ki.key);
- assert(carrays_hash);
- if (GetFlag(carrays_hash, "lua:closed") == 0)
- Append(to_close, ki.key);
- }
- ki = Next(ki);
- }
- SortList(to_close, &compareByLen);
- int len = Len(to_close);
- for (int i = 0; i < len; i++) {
- String *key = Getitem(to_close, i);
- closeCArraysHash(key, dataOutput);
- Hash *carrays_hash = rawGetCArraysHash(key);
- String *name = 0; // name - name of the namespace as it should be visible in Lua
- if (DohLen(key) == 0) // This is global module
- name = module;
- else
- name = Getattr(carrays_hash, "name");
- assert(name);
- printCArraysDefinition(key, name, dataOutput);
- }
- Delete(to_close);
- }
- /* -----------------------------------------------------------------------------
- * printCArraysDefinition()
- *
- * This function prints to output a definition of namespace in form
- * swig_lua_namespace $cname = { attr_array, methods_array, ... , namespaces_array };
- * You can call this function as many times as is necessary.
- * 'name' is a user-visible name that this namespace will have in Lua. It shouldn't
- * be a fully qualified name, just its own name.
- * ----------------------------------------------------------------------------- */
- void printCArraysDefinition(String *nspace, String *name, File *output) {
- Hash *carrays_hash = getCArraysHash(nspace, false);
- String *cname = Getattr(carrays_hash, "cname"); // cname - name of the C structure that describes namespace
- assert(cname);
- Printv(output, "static swig_lua_namespace ", cname, " = ", NIL);
- String *null_string = NewString("0");
- String *attr_tab_name = Getattr(carrays_hash, "attributes:name");
- String *methods_tab_name = Getattr(carrays_hash, "methods:name");
- String *const_tab_name = Getattr(carrays_hash, "constants:name");
- String *classes_tab_name = Getattr(carrays_hash, "classes:name");
- String *namespaces_tab_name = Getattr(carrays_hash, "namespaces:name");
- bool has_classes = GetFlag(carrays_hash, "lua:no_classes") == 0;
- bool has_namespaces = GetFlag(carrays_hash, "lua:no_namespaces") == 0;
- Printv(output, "{\n",
- tab4, "\"", name, "\",\n",
- tab4, methods_tab_name, ",\n",
- tab4, attr_tab_name, ",\n",
- tab4, const_tab_name, ",\n",
- tab4, (has_classes) ? classes_tab_name : null_string, ",\n",
- tab4, (has_namespaces) ? namespaces_tab_name : null_string, "\n};\n", NIL);
- Delete(null_string);
- }
- /* -----------------------------------------------------------------------------
- * luaCurrentSymbolNSpace()
- *
- * This function determines actual namespace/scope where any symbol at the
- * current moment should be placed. It looks at the 'current' array
- * and depending on where are we - static class member/function,
- * instance class member/function or just global functions decides
- * where symbol should be put.
- * The namespace/scope doesn't depend from symbol, only from 'current'
- * ----------------------------------------------------------------------------- */
- String *luaCurrentSymbolNSpace() {
- String *scope = 0;
- // If outside class, than NSpace is used.
- // If inside class, but current[NO_CPP], then this is friend function. It belongs to NSpace
- if (!getCurrentClass() || current[NO_CPP]) {
- scope = getNSpace();
- } else if (current[ENUM_CONST] && !CPlusPlus ) {
- // Enums in C mode go to NSpace
- scope = getNSpace();
- } else {
- // If inside class, then either class static namespace or class fully qualified name is used
- assert(!current[NO_CPP]);
- if (current[STATIC_FUNC] || current[STATIC_VAR] || current[STATIC_CONST]) {
- scope = class_static_nspace;
- } else if (current[MEMBER_VAR] || current[CONSTRUCTOR] || current[DESTRUCTOR]
- || current[MEMBER_FUNC]) {
- scope = full_proxy_class_name;
- } else { // Friend functions are handled this way
- scope = class_static_nspace;
- }
- assert(scope);
- }
- return scope;
- }
- /* -----------------------------------------------------------------------------
- * luaAddSymbol()
- *
- * Our implementation of addSymbol. Determines scope correctly, then
- * forwards to Language::addSymbol
- * ----------------------------------------------------------------------------- */
- int luaAddSymbol(const String *s, const Node *n) {
- String *scope = luaCurrentSymbolNSpace();
- return luaAddSymbol(s, n, scope);
- }
- /* -----------------------------------------------------------------------------
- * luaAddSymbol()
- *
- * Overload. Enforces given scope. Actually, it simply forwards call to Language::addSymbol
- * ----------------------------------------------------------------------------- */
- int luaAddSymbol(const String *s, const Node *n, const_String_or_char_ptr scope) {
- int result = Language::addSymbol(s, n, scope);
- if (!result)
- Printf(stderr, "addSymbol(%s to scope %s) failed\n", s, scope);
- return result;
- }
- };
- /* -----------------------------------------------------------------------------
- * swig_lua() - Instantiate module
- * ----------------------------------------------------------------------------- */
- extern "C" Language *swig_lua(void) {
- return new LUA();
- }
|