java.cxx 184 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979
  1. /* -----------------------------------------------------------------------------
  2. * This file is part of SWIG, which is licensed as a whole under version 3
  3. * (or any later version) of the GNU General Public License. Some additional
  4. * terms also apply to certain portions of SWIG. The full details of the SWIG
  5. * license and copyrights can be found in the LICENSE and COPYRIGHT files
  6. * included with the SWIG source code as distributed by the SWIG developers
  7. * and at https://www.swig.org/legal.html.
  8. *
  9. * java.cxx
  10. *
  11. * Java language module for SWIG.
  12. * ----------------------------------------------------------------------------- */
  13. #include "swigmod.h"
  14. #include "cparse.h"
  15. #include <limits.h> // for INT_MAX
  16. #include <ctype.h>
  17. #include "javadoc.h"
  18. /* Hash type used for upcalls from C/C++ */
  19. typedef DOH UpcallData;
  20. class JAVA:public Language {
  21. static const char *usage;
  22. const String *empty_string;
  23. const String *public_string;
  24. const String *protected_string;
  25. Hash *swig_types_hash;
  26. File *f_begin;
  27. File *f_runtime;
  28. File *f_runtime_h;
  29. File *f_header;
  30. File *f_wrappers;
  31. File *f_init;
  32. File *f_directors;
  33. File *f_directors_h;
  34. List *filenames_list;
  35. bool proxy_flag; // Flag for generating proxy classes
  36. bool nopgcpp_flag; // Flag for suppressing the premature garbage collection prevention parameter
  37. bool native_function_flag; // Flag for when wrapping a native function
  38. bool enum_constant_flag; // Flag for when wrapping an enum or constant
  39. bool static_flag; // Flag for when wrapping a static functions or member variables
  40. bool variable_wrapper_flag; // Flag for when wrapping a nonstatic member variable
  41. bool wrapping_member_flag; // Flag for when wrapping a member variable/enum/const
  42. bool global_variable_flag; // Flag for when wrapping a global variable
  43. bool old_variable_names; // Flag for old style variable names in the intermediary class
  44. bool member_func_flag; // flag set when wrapping a member function
  45. bool doxygen; //flag for converting found doxygen to javadoc
  46. bool comment_creation_chatter; //flag for getting information about where comments were created in java.cxx
  47. String *imclass_name; // intermediary class name
  48. String *module_class_name; // module class name
  49. String *constants_interface_name; // constants interface name
  50. String *imclass_class_code; // intermediary class code
  51. String *proxy_class_def;
  52. String *proxy_class_code;
  53. String *interface_class_code; // if %feature("interface") was declared for a class, here goes the interface declaration
  54. String *module_class_code;
  55. String *proxy_class_name; // proxy class name
  56. String *full_proxy_class_name;// fully qualified proxy class name when using nspace feature, otherwise same as proxy_class_name
  57. String *full_imclass_name; // fully qualified intermediary class name when using nspace feature, otherwise same as imclass_name
  58. String *variable_name; //Name of a variable being wrapped
  59. String *proxy_class_constants_code;
  60. String *module_class_constants_code;
  61. String *enum_code;
  62. String *package; // Optional package name
  63. String *jnipackage; // Package name used in the JNI code
  64. String *package_path; // Package name used internally by JNI (slashes)
  65. String *imclass_imports; //intermediary class imports from %pragma
  66. String *module_imports; //module imports from %pragma
  67. String *imclass_baseclass; //inheritance for intermediary class class from %pragma
  68. String *imclass_package; //package in which to generate the intermediary class
  69. String *module_baseclass; //inheritance for module class from %pragma
  70. String *imclass_interfaces; //interfaces for intermediary class class from %pragma
  71. String *module_interfaces; //interfaces for module class from %pragma
  72. String *imclass_class_modifiers; //class modifiers for intermediary class overridden by %pragma
  73. String *module_class_modifiers; //class modifiers for module class overridden by %pragma
  74. String *upcasts_code; //C++ casts for inheritance hierarchies C++ code
  75. String *imclass_cppcasts_code; //C++ casts up inheritance hierarchies intermediary class code
  76. String *imclass_directors; // Intermediate class director code
  77. String *destructor_call; //C++ destructor call if any
  78. String *destructor_throws_clause; //C++ destructor throws clause if any
  79. // Director method stuff:
  80. List *dmethods_seq;
  81. Hash *dmethods_table;
  82. int n_dmethods;
  83. int n_directors;
  84. int first_class_dmethod;
  85. int curr_class_dmethod;
  86. int nesting_depth;
  87. enum EnumFeature { SimpleEnum, TypeunsafeEnum, TypesafeEnum, ProperEnum };
  88. public:
  89. /* -----------------------------------------------------------------------------
  90. * JAVA()
  91. * ----------------------------------------------------------------------------- */
  92. JAVA():empty_string(NewString("")),
  93. public_string(NewString("public")),
  94. protected_string(NewString("protected")),
  95. swig_types_hash(NULL),
  96. f_begin(NULL),
  97. f_runtime(NULL),
  98. f_runtime_h(NULL),
  99. f_header(NULL),
  100. f_wrappers(NULL),
  101. f_init(NULL),
  102. f_directors(NULL),
  103. f_directors_h(NULL),
  104. filenames_list(NULL),
  105. proxy_flag(true),
  106. nopgcpp_flag(false),
  107. native_function_flag(false),
  108. enum_constant_flag(false),
  109. static_flag(false),
  110. variable_wrapper_flag(false),
  111. wrapping_member_flag(false),
  112. global_variable_flag(false),
  113. old_variable_names(false),
  114. member_func_flag(false),
  115. doxygen(false),
  116. comment_creation_chatter(false),
  117. imclass_name(NULL),
  118. module_class_name(NULL),
  119. constants_interface_name(NULL),
  120. imclass_class_code(NULL),
  121. proxy_class_def(NULL),
  122. proxy_class_code(NULL),
  123. interface_class_code(NULL),
  124. module_class_code(NULL),
  125. proxy_class_name(NULL),
  126. full_proxy_class_name(NULL),
  127. full_imclass_name(NULL),
  128. variable_name(NULL),
  129. proxy_class_constants_code(NULL),
  130. module_class_constants_code(NULL),
  131. enum_code(NULL),
  132. package(NULL),
  133. jnipackage(NULL),
  134. package_path(NULL),
  135. imclass_imports(NULL),
  136. module_imports(NULL),
  137. imclass_baseclass(NULL),
  138. imclass_package(NULL),
  139. module_baseclass(NULL),
  140. imclass_interfaces(NULL),
  141. module_interfaces(NULL),
  142. imclass_class_modifiers(NULL),
  143. module_class_modifiers(NULL),
  144. upcasts_code(NULL),
  145. imclass_cppcasts_code(NULL),
  146. imclass_directors(NULL),
  147. destructor_call(NULL),
  148. destructor_throws_clause(NULL),
  149. dmethods_seq(NULL),
  150. dmethods_table(NULL),
  151. n_dmethods(0),
  152. n_directors(0),
  153. first_class_dmethod(0),
  154. curr_class_dmethod(0),
  155. nesting_depth(0){
  156. /* for now, multiple inheritance in directors is disabled, this
  157. should be easy to implement though */
  158. director_multiple_inheritance = 0;
  159. director_language = 1;
  160. }
  161. ~JAVA() {
  162. delete doxygenTranslator;
  163. }
  164. /* -----------------------------------------------------------------------------
  165. * constructIntermediateClassName()
  166. *
  167. * Construct the fully qualified name of the intermediate class and set
  168. * the full_imclass_name attribute accordingly.
  169. * ----------------------------------------------------------------------------- */
  170. void constructIntermediateClassName(Node *n) {
  171. String *nspace = Getattr(n, "sym:nspace");
  172. if (imclass_package && package)
  173. full_imclass_name = NewStringf("%s.%s.%s", package, imclass_package, imclass_name);
  174. else if (package && nspace)
  175. full_imclass_name = NewStringf("%s.%s", package, imclass_name);
  176. else if (imclass_package)
  177. full_imclass_name = NewStringf("%s.%s", imclass_package, imclass_name);
  178. else
  179. full_imclass_name = NewStringf("%s", imclass_name);
  180. if (nspace && !package) {
  181. String *name = Getattr(n, "name") ? Getattr(n, "name") : NewString("<unnamed>");
  182. Swig_warning(WARN_JAVA_NSPACE_WITHOUT_PACKAGE, Getfile(n), Getline(n),
  183. "The nspace feature is used on '%s' without -package. "
  184. "The generated code may not compile as Java does not support types declared in a named package accessing types declared in an unnamed package.\n", SwigType_namestr(name));
  185. }
  186. }
  187. /* -----------------------------------------------------------------------------
  188. * getProxyName()
  189. *
  190. * Test to see if a type corresponds to something wrapped with a proxy class.
  191. * Return NULL if not otherwise the proxy class name, fully qualified with
  192. * package name if the nspace feature is used, unless jnidescriptor is true as
  193. * the package name is handled differently (unfortunately for legacy reasons).
  194. * ----------------------------------------------------------------------------- */
  195. String *getProxyName(SwigType *t, bool jnidescriptor = false) {
  196. String *proxyname = NULL;
  197. if (proxy_flag) {
  198. Node *n = classLookup(t);
  199. if (n) {
  200. proxyname = Getattr(n, "proxyname");
  201. if (!proxyname || jnidescriptor) {
  202. String *nspace = Getattr(n, "sym:nspace");
  203. String *symname = Copy(Getattr(n, "sym:name"));
  204. if (symname && !GetFlag(n, "feature:flatnested")) {
  205. for (Node *outer_class = Getattr(n, "nested:outer"); outer_class; outer_class = Getattr(outer_class, "nested:outer")) {
  206. if (String* name = Getattr(outer_class, "sym:name")) {
  207. Push(symname, jnidescriptor ? "$" : ".");
  208. Push(symname, name);
  209. }
  210. else
  211. return NULL;
  212. }
  213. }
  214. if (nspace) {
  215. if (package && !jnidescriptor)
  216. proxyname = NewStringf("%s.%s.%s", package, nspace, symname);
  217. else
  218. proxyname = NewStringf("%s.%s", nspace, symname);
  219. } else {
  220. proxyname = Copy(symname);
  221. }
  222. if (!jnidescriptor) {
  223. Setattr(n, "proxyname", proxyname); // Cache it
  224. Delete(proxyname);
  225. }
  226. Delete(symname);
  227. }
  228. }
  229. }
  230. return proxyname;
  231. }
  232. /* -----------------------------------------------------------------------------
  233. * makeValidJniName()
  234. * ----------------------------------------------------------------------------- */
  235. String *makeValidJniName(const String *name) {
  236. String *valid_jni_name = NewString(name);
  237. Replaceall(valid_jni_name, "_", "_1");
  238. return valid_jni_name;
  239. }
  240. /* ------------------------------------------------------------
  241. * main()
  242. * ------------------------------------------------------------ */
  243. virtual void main(int argc, char *argv[]) {
  244. SWIG_library_directory("java");
  245. int doxygen_translator_flags = 0;
  246. // Look for certain command line options
  247. for (int i = 1; i < argc; i++) {
  248. if (argv[i]) {
  249. if (strcmp(argv[i], "-package") == 0) {
  250. if (argv[i + 1]) {
  251. package = NewString("");
  252. Printf(package, argv[i + 1]);
  253. if (Len(package) == 0) {
  254. Delete(package);
  255. package = 0;
  256. }
  257. Swig_mark_arg(i);
  258. Swig_mark_arg(i + 1);
  259. i++;
  260. } else {
  261. Swig_arg_error();
  262. }
  263. } else if ((strcmp(argv[i], "-shadow") == 0) || ((strcmp(argv[i], "-proxy") == 0))) {
  264. Printf(stderr, "Deprecated command line option: %s. Proxy classes are now generated by default.\n", argv[i]);
  265. Swig_mark_arg(i);
  266. proxy_flag = true;
  267. } else if ((strcmp(argv[i], "-doxygen") == 0)) {
  268. Swig_mark_arg(i);
  269. doxygen = true;
  270. scan_doxygen_comments = true;
  271. } else if ((strcmp(argv[i], "-debug-doxygen-translator") == 0)) {
  272. Swig_mark_arg(i);
  273. doxygen_translator_flags |= DoxygenTranslator::debug_translator;
  274. } else if ((strcmp(argv[i], "-debug-doxygen-parser") == 0)) {
  275. Swig_mark_arg(i);
  276. doxygen_translator_flags |= DoxygenTranslator::debug_parser;
  277. } else if ((strcmp(argv[i], "-noproxy") == 0)) {
  278. Swig_mark_arg(i);
  279. proxy_flag = false;
  280. } else if (strcmp(argv[i], "-nopgcpp") == 0) {
  281. Swig_mark_arg(i);
  282. nopgcpp_flag = true;
  283. } else if (strcmp(argv[i], "-oldvarnames") == 0) {
  284. Swig_mark_arg(i);
  285. old_variable_names = true;
  286. } else if (strcmp(argv[i], "-jnic") == 0) {
  287. Swig_mark_arg(i);
  288. Printf(stderr, "Deprecated command line option: -jnic. C JNI calling convention now used when -c++ not specified.\n");
  289. } else if (strcmp(argv[i], "-nofinalize") == 0) {
  290. Swig_mark_arg(i);
  291. Printf(stderr, "Deprecated command line option: -nofinalize. Use the new javafinalize typemap instead.\n");
  292. } else if (strcmp(argv[i], "-jnicpp") == 0) {
  293. Swig_mark_arg(i);
  294. Printf(stderr, "Deprecated command line option: -jnicpp. C++ JNI calling convention now used when -c++ specified.\n");
  295. } else if (strcmp(argv[i], "-help") == 0) {
  296. Printf(stdout, "%s\n", usage);
  297. }
  298. }
  299. }
  300. if (doxygen)
  301. doxygenTranslator = new JavaDocConverter(doxygen_translator_flags);
  302. // Add a symbol to the parser for conditional compilation
  303. Preprocessor_define("SWIGJAVA 1", 0);
  304. // Add typemap definitions
  305. SWIG_typemap_lang("java");
  306. SWIG_config_file("java.swg");
  307. allow_overloading();
  308. Swig_interface_feature_enable();
  309. }
  310. /* ---------------------------------------------------------------------
  311. * top()
  312. * --------------------------------------------------------------------- */
  313. virtual int top(Node *n) {
  314. // Get any options set in the module directive
  315. Node *optionsnode = Getattr(Getattr(n, "module"), "options");
  316. if (optionsnode) {
  317. if (Getattr(optionsnode, "jniclassname"))
  318. imclass_name = Copy(Getattr(optionsnode, "jniclassname"));
  319. /* check if directors are enabled for this module. note: this
  320. * is a "master" switch, without which no director code will be
  321. * emitted. %feature("director") statements are also required
  322. * to enable directors for individual classes or methods.
  323. *
  324. * use %module(directors="1") modulename at the start of the
  325. * interface file to enable director generation.
  326. */
  327. if (Getattr(optionsnode, "directors")) {
  328. allow_directors();
  329. }
  330. if (Getattr(optionsnode, "dirprot")) {
  331. allow_dirprot();
  332. }
  333. allow_allprotected(GetFlag(optionsnode, "allprotected"));
  334. }
  335. /* Initialize all of the output files */
  336. String *outfile = Getattr(n, "outfile");
  337. String *outfile_h = Getattr(n, "outfile_h");
  338. if (!outfile) {
  339. Printf(stderr, "Unable to determine outfile\n");
  340. Exit(EXIT_FAILURE);
  341. }
  342. f_begin = NewFile(outfile, "w", SWIG_output_files());
  343. if (!f_begin) {
  344. FileErrorDisplay(outfile);
  345. Exit(EXIT_FAILURE);
  346. }
  347. if (directorsEnabled()) {
  348. if (!outfile_h) {
  349. Printf(stderr, "Unable to determine outfile_h\n");
  350. Exit(EXIT_FAILURE);
  351. }
  352. f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files());
  353. if (!f_runtime_h) {
  354. FileErrorDisplay(outfile_h);
  355. Exit(EXIT_FAILURE);
  356. }
  357. }
  358. f_runtime = NewString("");
  359. f_init = NewString("");
  360. f_header = NewString("");
  361. f_wrappers = NewString("");
  362. f_directors_h = NewString("");
  363. f_directors = NewString("");
  364. /* Register file targets with the SWIG file handler */
  365. Swig_register_filebyname("begin", f_begin);
  366. Swig_register_filebyname("header", f_header);
  367. Swig_register_filebyname("wrapper", f_wrappers);
  368. Swig_register_filebyname("runtime", f_runtime);
  369. Swig_register_filebyname("init", f_init);
  370. Swig_register_filebyname("director", f_directors);
  371. Swig_register_filebyname("director_h", f_directors_h);
  372. swig_types_hash = NewHash();
  373. filenames_list = NewList();
  374. // Make the intermediary class and module class names. The intermediary class name can be set in the module directive.
  375. if (!imclass_name) {
  376. imclass_name = NewStringf("%sJNI", Getattr(n, "name"));
  377. module_class_name = Copy(Getattr(n, "name"));
  378. } else {
  379. // Rename the module name if it is the same as intermediary class name - a backwards compatibility solution
  380. if (Cmp(imclass_name, Getattr(n, "name")) == 0)
  381. module_class_name = NewStringf("%sModule", Getattr(n, "name"));
  382. else
  383. module_class_name = Copy(Getattr(n, "name"));
  384. }
  385. constants_interface_name = NewStringf("%sConstants", module_class_name);
  386. // module class and intermediary classes are always created
  387. if (!addSymbol(imclass_name, n))
  388. return SWIG_ERROR;
  389. if (!addSymbol(module_class_name, n))
  390. return SWIG_ERROR;
  391. imclass_class_code = NewString("");
  392. proxy_class_def = NewString("");
  393. proxy_class_code = NewString("");
  394. module_class_constants_code = NewString("");
  395. imclass_baseclass = NewString("");
  396. imclass_package = NULL;
  397. imclass_interfaces = NewString("");
  398. imclass_class_modifiers = NewString("");
  399. module_class_code = NewString("");
  400. module_baseclass = NewString("");
  401. module_interfaces = NewString("");
  402. module_imports = NewString("");
  403. module_class_modifiers = NewString("");
  404. imclass_imports = NewString("");
  405. imclass_cppcasts_code = NewString("");
  406. imclass_directors = NewString("");
  407. upcasts_code = NewString("");
  408. dmethods_seq = NewList();
  409. dmethods_table = NewHash();
  410. n_dmethods = 0;
  411. n_directors = 0;
  412. jnipackage = NewString("");
  413. package_path = NewString("");
  414. Swig_banner(f_begin);
  415. Swig_obligatory_macros(f_runtime, "JAVA");
  416. if (directorsEnabled()) {
  417. Printf(f_runtime, "#define SWIG_DIRECTORS\n");
  418. /* Emit initial director header and director code: */
  419. Swig_banner(f_directors_h);
  420. Printf(f_directors_h, "\n");
  421. Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", module_class_name);
  422. Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", module_class_name);
  423. Printf(f_directors, "\n\n");
  424. Printf(f_directors, "/* ---------------------------------------------------\n");
  425. Printf(f_directors, " * C++ director class methods\n");
  426. Printf(f_directors, " * --------------------------------------------------- */\n\n");
  427. if (outfile_h) {
  428. String *filename = Swig_file_filename(outfile_h);
  429. Printf(f_directors, "#include \"%s\"\n\n", filename);
  430. Delete(filename);
  431. }
  432. }
  433. Printf(f_runtime, "\n");
  434. String *wrapper_name = NewString("");
  435. if (package) {
  436. String *jniname = makeValidJniName(package);
  437. Printv(jnipackage, jniname, NIL);
  438. Delete(jniname);
  439. Replaceall(jnipackage, ".", "_");
  440. Append(jnipackage, "_");
  441. Printv(package_path, package, NIL);
  442. Replaceall(package_path, ".", "/");
  443. }
  444. String *jniname = makeValidJniName(imclass_name);
  445. Printf(wrapper_name, "Java_%s%s_%%f", jnipackage, jniname);
  446. Delete(jniname);
  447. Swig_name_register("wrapper", Char(wrapper_name));
  448. if (old_variable_names) {
  449. Swig_name_register("set", "set_%n%v");
  450. Swig_name_register("get", "get_%n%v");
  451. }
  452. Delete(wrapper_name);
  453. Printf(f_wrappers, "\n#ifdef __cplusplus\n");
  454. Printf(f_wrappers, "extern \"C\" {\n");
  455. Printf(f_wrappers, "#endif\n\n");
  456. /* Emit code */
  457. Language::top(n);
  458. if (directorsEnabled()) {
  459. // Insert director runtime into the f_runtime file (make it occur before %header section)
  460. Swig_insert_file("director_common.swg", f_runtime);
  461. Swig_insert_file("director.swg", f_runtime);
  462. }
  463. // Generate the intermediary class
  464. {
  465. String *filen = NewStringf("%s%s.java", outputDirectory(imclass_package), imclass_name);
  466. File *f_im = NewFile(filen, "w", SWIG_output_files());
  467. if (!f_im) {
  468. FileErrorDisplay(filen);
  469. Exit(EXIT_FAILURE);
  470. }
  471. Append(filenames_list, Copy(filen));
  472. Delete(filen);
  473. filen = NULL;
  474. // Start writing out the intermediary class file
  475. emitBanner(f_im);
  476. if (imclass_package && package)
  477. Printf(f_im, "package %s.%s;", package, imclass_package);
  478. else if (imclass_package)
  479. Printf(f_im, "package %s;", imclass_package);
  480. else if (package)
  481. Printf(f_im, "package %s;\n", package);
  482. if (imclass_imports)
  483. Printf(f_im, "%s\n", imclass_imports);
  484. if (Len(imclass_class_modifiers) > 0)
  485. Printf(f_im, "%s ", imclass_class_modifiers);
  486. Printf(f_im, "%s ", imclass_name);
  487. if (imclass_baseclass && *Char(imclass_baseclass))
  488. Printf(f_im, "extends %s ", imclass_baseclass);
  489. if (Len(imclass_interfaces) > 0)
  490. Printv(f_im, "implements ", imclass_interfaces, " ", NIL);
  491. Printf(f_im, "{\n");
  492. // Add the intermediary class methods
  493. Replaceall(imclass_class_code, "$module", module_class_name);
  494. Replaceall(imclass_class_code, "$imclassname", imclass_name);
  495. Printv(f_im, imclass_class_code, NIL);
  496. Printv(f_im, imclass_cppcasts_code, NIL);
  497. if (Len(imclass_directors) > 0)
  498. Printv(f_im, "\n", imclass_directors, NIL);
  499. if (n_dmethods > 0) {
  500. Putc('\n', f_im);
  501. Printf(f_im, " private final static native void swig_module_init();\n");
  502. Printf(f_im, " static {\n");
  503. Printf(f_im, " swig_module_init();\n");
  504. Printf(f_im, " }\n");
  505. }
  506. // Finish off the class
  507. Printf(f_im, "}\n");
  508. Delete(f_im);
  509. }
  510. // Generate the Java module class
  511. {
  512. String *filen = NewStringf("%s%s.java", SWIG_output_directory(), module_class_name);
  513. File *f_module = NewFile(filen, "w", SWIG_output_files());
  514. if (!f_module) {
  515. FileErrorDisplay(filen);
  516. Exit(EXIT_FAILURE);
  517. }
  518. Append(filenames_list, Copy(filen));
  519. Delete(filen);
  520. filen = NULL;
  521. // Start writing out the module class file
  522. emitBanner(f_module);
  523. if (package)
  524. Printf(f_module, "package %s;\n", package);
  525. if (module_imports)
  526. Printf(f_module, "%s\n", module_imports);
  527. if (doxygen && doxygenTranslator->hasDocumentation(n)) {
  528. String *doxygen_comments = doxygenTranslator->getDocumentation(n, 0);
  529. if (comment_creation_chatter)
  530. Printf(f_module, "/* This was generated from top() */\n");
  531. Printv(f_module, Char(doxygen_comments), NIL);
  532. Delete(doxygen_comments);
  533. }
  534. if (Len(module_class_modifiers) > 0)
  535. Printf(f_module, "%s ", module_class_modifiers);
  536. Printf(f_module, "%s ", module_class_name);
  537. if (module_baseclass && *Char(module_baseclass))
  538. Printf(f_module, "extends %s ", module_baseclass);
  539. if (Len(module_interfaces) > 0) {
  540. if (Len(module_class_constants_code) != 0)
  541. Printv(f_module, "implements ", constants_interface_name, ", ", module_interfaces, " ", NIL);
  542. else
  543. Printv(f_module, "implements ", module_interfaces, " ", NIL);
  544. } else {
  545. if (Len(module_class_constants_code) != 0)
  546. Printv(f_module, "implements ", constants_interface_name, " ", NIL);
  547. }
  548. Printf(f_module, "{\n");
  549. Replaceall(module_class_code, "$module", module_class_name);
  550. Replaceall(module_class_constants_code, "$module", module_class_name);
  551. Replaceall(module_class_code, "$imclassname", imclass_name);
  552. Replaceall(module_class_constants_code, "$imclassname", imclass_name);
  553. // Add the wrapper methods
  554. Printv(f_module, module_class_code, NIL);
  555. // Finish off the class
  556. Printf(f_module, "}\n");
  557. Delete(f_module);
  558. }
  559. // Generate the Java constants interface
  560. if (Len(module_class_constants_code) != 0) {
  561. String *filen = NewStringf("%s%s.java", SWIG_output_directory(), constants_interface_name);
  562. File *f_module = NewFile(filen, "w", SWIG_output_files());
  563. if (!f_module) {
  564. FileErrorDisplay(filen);
  565. Exit(EXIT_FAILURE);
  566. }
  567. Append(filenames_list, Copy(filen));
  568. Delete(filen);
  569. filen = NULL;
  570. // Start writing out the Java constants interface file
  571. emitBanner(f_module);
  572. if (package)
  573. Printf(f_module, "package %s;\n", package);
  574. if (module_imports)
  575. Printf(f_module, "%s\n", module_imports);
  576. Printf(f_module, "public interface %s {\n", constants_interface_name);
  577. // Write out all the global constants
  578. Printv(f_module, module_class_constants_code, NIL);
  579. // Finish off the Java interface
  580. Printf(f_module, "}\n");
  581. Delete(f_module);
  582. }
  583. if (upcasts_code)
  584. Printv(f_wrappers, upcasts_code, NIL);
  585. emitDirectorUpcalls();
  586. Printf(f_wrappers, "#ifdef __cplusplus\n");
  587. Printf(f_wrappers, "}\n");
  588. Printf(f_wrappers, "#endif\n");
  589. // Output a Java type wrapper class for each SWIG type
  590. for (Iterator swig_type = First(swig_types_hash); swig_type.key; swig_type = Next(swig_type)) {
  591. emitTypeWrapperClass(swig_type.key, swig_type.item);
  592. }
  593. // Check for overwriting file problems on filesystems that are case insensitive
  594. Iterator it1;
  595. Iterator it2;
  596. for (it1 = First(filenames_list); it1.item; it1 = Next(it1)) {
  597. String *item1_lower = Swig_string_lower(it1.item);
  598. for (it2 = Next(it1); it2.item; it2 = Next(it2)) {
  599. String *item2_lower = Swig_string_lower(it2.item);
  600. if (it1.item && it2.item) {
  601. if (Strcmp(item1_lower, item2_lower) == 0) {
  602. Swig_warning(WARN_LANG_PORTABILITY_FILENAME, input_file, line_number,
  603. "Portability warning: File %s will be overwritten by %s on case insensitive filesystems such as "
  604. "Windows' FAT32 and NTFS unless the class/module name is renamed\n", it1.item, it2.item);
  605. }
  606. }
  607. Delete(item2_lower);
  608. }
  609. Delete(item1_lower);
  610. }
  611. Delete(swig_types_hash);
  612. swig_types_hash = NULL;
  613. Delete(filenames_list);
  614. filenames_list = NULL;
  615. Delete(imclass_name);
  616. imclass_name = NULL;
  617. Delete(imclass_class_code);
  618. imclass_class_code = NULL;
  619. Delete(proxy_class_def);
  620. proxy_class_def = NULL;
  621. Delete(proxy_class_code);
  622. proxy_class_code = NULL;
  623. Delete(module_class_constants_code);
  624. module_class_constants_code = NULL;
  625. Delete(imclass_baseclass);
  626. imclass_baseclass = NULL;
  627. Delete(imclass_package);
  628. imclass_package = NULL;
  629. Delete(imclass_interfaces);
  630. imclass_interfaces = NULL;
  631. Delete(imclass_class_modifiers);
  632. imclass_class_modifiers = NULL;
  633. Delete(module_class_name);
  634. module_class_name = NULL;
  635. Delete(constants_interface_name);
  636. constants_interface_name = NULL;
  637. Delete(module_class_code);
  638. module_class_code = NULL;
  639. Delete(module_baseclass);
  640. module_baseclass = NULL;
  641. Delete(module_interfaces);
  642. module_interfaces = NULL;
  643. Delete(module_imports);
  644. module_imports = NULL;
  645. Delete(module_class_modifiers);
  646. module_class_modifiers = NULL;
  647. Delete(imclass_imports);
  648. imclass_imports = NULL;
  649. Delete(imclass_cppcasts_code);
  650. imclass_cppcasts_code = NULL;
  651. Delete(imclass_directors);
  652. imclass_directors = NULL;
  653. Delete(upcasts_code);
  654. upcasts_code = NULL;
  655. Delete(package);
  656. package = NULL;
  657. Delete(jnipackage);
  658. jnipackage = NULL;
  659. Delete(package_path);
  660. package_path = NULL;
  661. Delete(dmethods_seq);
  662. dmethods_seq = NULL;
  663. Delete(dmethods_table);
  664. dmethods_table = NULL;
  665. n_dmethods = 0;
  666. /* Close all of the files */
  667. Dump(f_header, f_runtime);
  668. if (directorsEnabled()) {
  669. Dump(f_directors, f_runtime);
  670. Dump(f_directors_h, f_runtime_h);
  671. Printf(f_runtime_h, "\n");
  672. Printf(f_runtime_h, "#endif\n");
  673. Delete(f_runtime_h);
  674. f_runtime_h = NULL;
  675. Delete(f_directors);
  676. f_directors = NULL;
  677. Delete(f_directors_h);
  678. f_directors_h = NULL;
  679. }
  680. Dump(f_wrappers, f_runtime);
  681. Wrapper_pretty_print(f_init, f_runtime);
  682. Delete(f_header);
  683. Delete(f_wrappers);
  684. Delete(f_init);
  685. Dump(f_runtime, f_begin);
  686. Delete(f_runtime);
  687. Delete(f_begin);
  688. return SWIG_OK;
  689. }
  690. /* -----------------------------------------------------------------------------
  691. * emitBanner()
  692. * ----------------------------------------------------------------------------- */
  693. void emitBanner(File *f) {
  694. Printf(f, "/* ----------------------------------------------------------------------------\n");
  695. Swig_banner_target_lang(f, " *");
  696. Printf(f, " * ----------------------------------------------------------------------------- */\n\n");
  697. }
  698. /*-----------------------------------------------------------------------
  699. * Add new director upcall signature
  700. *----------------------------------------------------------------------*/
  701. UpcallData *addUpcallMethod(String *imclass_method, String *class_method, String *imclass_desc, String *class_desc, String *decl) {
  702. String *key = NewStringf("%s|%s", imclass_method, decl);
  703. ++curr_class_dmethod;
  704. String *imclass_methodidx = NewStringf("%d", n_dmethods);
  705. String *class_methodidx = NewStringf("%d", n_dmethods - first_class_dmethod);
  706. n_dmethods++;
  707. Hash *new_udata = NewHash();
  708. Append(dmethods_seq, new_udata);
  709. Setattr(dmethods_table, key, new_udata);
  710. Setattr(new_udata, "method", Copy(class_method));
  711. Setattr(new_udata, "fdesc", Copy(class_desc));
  712. Setattr(new_udata, "imclass_method", Copy(imclass_method));
  713. Setattr(new_udata, "imclass_fdesc", Copy(imclass_desc));
  714. Setattr(new_udata, "imclass_methodidx", imclass_methodidx);
  715. Setattr(new_udata, "class_methodidx", class_methodidx);
  716. Setattr(new_udata, "decl", Copy(decl));
  717. Delete(key);
  718. return new_udata;
  719. }
  720. /*-----------------------------------------------------------------------
  721. * Get director upcall signature
  722. *----------------------------------------------------------------------*/
  723. UpcallData *getUpcallMethodData(String *director_class, String *decl) {
  724. String *key = NewStringf("%s|%s", director_class, decl);
  725. UpcallData *udata = Getattr(dmethods_table, key);
  726. Delete(key);
  727. return udata;
  728. }
  729. /* ----------------------------------------------------------------------
  730. * nativeWrapper()
  731. * ---------------------------------------------------------------------- */
  732. virtual int nativeWrapper(Node *n) {
  733. String *wrapname = Getattr(n, "wrap:name");
  734. if (!addSymbol(wrapname, n, imclass_name))
  735. return SWIG_ERROR;
  736. if (Getattr(n, "type")) {
  737. Swig_save("nativeWrapper", n, "name", NIL);
  738. Setattr(n, "name", wrapname);
  739. native_function_flag = true;
  740. functionWrapper(n);
  741. Swig_restore(n);
  742. native_function_flag = false;
  743. } else {
  744. Swig_error(input_file, line_number, "No return type for %%native method %s.\n", Getattr(n, "wrap:name"));
  745. }
  746. return SWIG_OK;
  747. }
  748. /* ----------------------------------------------------------------------
  749. * functionWrapper()
  750. * ---------------------------------------------------------------------- */
  751. virtual int functionWrapper(Node *n) {
  752. String *symname = Getattr(n, "sym:name");
  753. SwigType *t = Getattr(n, "type");
  754. ParmList *l = Getattr(n, "parms");
  755. String *tm;
  756. Parm *p;
  757. int i;
  758. String *c_return_type = NewString("");
  759. String *im_return_type = NewString("");
  760. String *cleanup = NewString("");
  761. String *outarg = NewString("");
  762. String *body = NewString("");
  763. int num_arguments = 0;
  764. int gencomma = 0;
  765. bool is_void_return;
  766. String *overloaded_name = getOverloadedName(n);
  767. String *nondir_args = NewString("");
  768. bool is_destructor = (Cmp(Getattr(n, "nodeType"), "destructor") == 0);
  769. if (!Getattr(n, "sym:overloaded")) {
  770. if (!addSymbol(symname, n, imclass_name))
  771. return SWIG_ERROR;
  772. }
  773. /*
  774. The rest of this function deals with generating the intermediary class wrapper function (that wraps
  775. a c/c++ function) and generating the JNI c code. Each Java wrapper function has a
  776. matching JNI c function call.
  777. */
  778. // A new wrapper function object
  779. Wrapper *f = NewWrapper();
  780. // Make a wrapper name for this function
  781. String *jniname = makeValidJniName(overloaded_name);
  782. String *wname = Swig_name_wrapper(jniname);
  783. Delete(jniname);
  784. /* Attach the non-standard typemaps to the parameter list. */
  785. Swig_typemap_attach_parms("jni", l, f);
  786. Swig_typemap_attach_parms("jtype", l, f);
  787. Swig_typemap_attach_parms("jstype", l, f);
  788. /* Get return types */
  789. if ((tm = Swig_typemap_lookup("jni", n, "", 0))) {
  790. Printf(c_return_type, "%s", tm);
  791. } else {
  792. Swig_warning(WARN_JAVA_TYPEMAP_JNI_UNDEF, input_file, line_number, "No jni typemap defined for %s\n", SwigType_str(t, 0));
  793. }
  794. if ((tm = Swig_typemap_lookup("jtype", n, "", 0))) {
  795. Printf(im_return_type, "%s", tm);
  796. } else {
  797. Swig_warning(WARN_JAVA_TYPEMAP_JTYPE_UNDEF, input_file, line_number, "No jtype typemap defined for %s\n", SwigType_str(t, 0));
  798. }
  799. is_void_return = (Cmp(c_return_type, "void") == 0);
  800. if (!is_void_return)
  801. Wrapper_add_localv(f, "jresult", c_return_type, "jresult = 0", NIL);
  802. Printv(f->def, "SWIGEXPORT ", c_return_type, " JNICALL ", wname, "(JNIEnv *jenv, jclass jcls", NIL);
  803. // Usually these function parameters are unused - The code below ensures
  804. // that compilers do not issue such a warning if configured to do so.
  805. Printv(f->code, " (void)jenv;\n", NIL);
  806. Printv(f->code, " (void)jcls;\n", NIL);
  807. // Emit all of the local variables for holding arguments.
  808. emit_parameter_variables(l, f);
  809. /* Attach the standard typemaps */
  810. emit_attach_parmmaps(l, f);
  811. // Parameter overloading
  812. Setattr(n, "wrap:parms", l);
  813. Setattr(n, "wrap:name", wname);
  814. // Wrappers not wanted for some methods where the parameters cannot be overloaded in Java
  815. if (Getattr(n, "sym:overloaded")) {
  816. // Emit warnings for the few cases that can't be overloaded in Java and give up on generating wrapper
  817. Swig_overload_check(n);
  818. if (Getattr(n, "overload:ignore")) {
  819. DelWrapper(f);
  820. return SWIG_OK;
  821. }
  822. }
  823. Printf(imclass_class_code, " public final static native %s %s(", im_return_type, overloaded_name);
  824. num_arguments = emit_num_arguments(l);
  825. // Now walk the function parameter list and generate code to get arguments
  826. for (i = 0, p = l; i < num_arguments; i++) {
  827. while (checkAttribute(p, "tmap:in:numinputs", "0")) {
  828. p = Getattr(p, "tmap:in:next");
  829. }
  830. SwigType *pt = Getattr(p, "type");
  831. String *ln = Getattr(p, "lname");
  832. String *im_param_type = NewString("");
  833. String *c_param_type = NewString("");
  834. String *arg = NewString("");
  835. Printf(arg, "j%s", ln);
  836. /* Get the JNI C types of the parameter */
  837. if ((tm = Getattr(p, "tmap:jni"))) {
  838. Printv(c_param_type, tm, NIL);
  839. } else {
  840. Swig_warning(WARN_JAVA_TYPEMAP_JNI_UNDEF, input_file, line_number, "No jni typemap defined for %s\n", SwigType_str(pt, 0));
  841. }
  842. /* Get the intermediary class parameter types of the parameter */
  843. if ((tm = Getattr(p, "tmap:jtype"))) {
  844. Printv(im_param_type, tm, NIL);
  845. } else {
  846. Swig_warning(WARN_JAVA_TYPEMAP_JTYPE_UNDEF, input_file, line_number, "No jtype typemap defined for %s\n", SwigType_str(pt, 0));
  847. }
  848. /* Add parameter to intermediary class method */
  849. if (gencomma)
  850. Printf(imclass_class_code, ", ");
  851. Printf(imclass_class_code, "%s %s", im_param_type, arg);
  852. // Add parameter to C function
  853. Printv(f->def, ", ", c_param_type, " ", arg, NIL);
  854. ++gencomma;
  855. // Premature garbage collection prevention parameter
  856. if (!is_destructor) {
  857. String *pgc_parameter = prematureGarbageCollectionPreventionParameter(pt, p);
  858. if (pgc_parameter) {
  859. Printf(imclass_class_code, ", %s %s_", pgc_parameter, arg);
  860. Printf(f->def, ", jobject %s_", arg);
  861. Printf(f->code, " (void)%s_;\n", arg);
  862. }
  863. }
  864. // Get typemap for this argument
  865. if ((tm = Getattr(p, "tmap:in"))) {
  866. addThrows(n, "tmap:in", p);
  867. Replaceall(tm, "$arg", arg); /* deprecated? */
  868. Replaceall(tm, "$input", arg);
  869. Setattr(p, "emit:input", arg);
  870. Printf(nondir_args, "%s\n", tm);
  871. p = Getattr(p, "tmap:in:next");
  872. } else {
  873. Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
  874. p = nextSibling(p);
  875. }
  876. Delete(im_param_type);
  877. Delete(c_param_type);
  878. Delete(arg);
  879. }
  880. Printv(f->code, nondir_args, NIL);
  881. Delete(nondir_args);
  882. /* Insert constraint checking code */
  883. for (p = l; p;) {
  884. if ((tm = Getattr(p, "tmap:check"))) {
  885. addThrows(n, "tmap:check", p);
  886. Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */
  887. Replaceall(tm, "$input", Getattr(p, "emit:input"));
  888. Printv(f->code, tm, "\n", NIL);
  889. p = Getattr(p, "tmap:check:next");
  890. } else {
  891. p = nextSibling(p);
  892. }
  893. }
  894. /* Insert cleanup code */
  895. for (p = l; p;) {
  896. if ((tm = Getattr(p, "tmap:freearg"))) {
  897. addThrows(n, "tmap:freearg", p);
  898. Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */
  899. Replaceall(tm, "$input", Getattr(p, "emit:input"));
  900. Printv(cleanup, tm, "\n", NIL);
  901. p = Getattr(p, "tmap:freearg:next");
  902. } else {
  903. p = nextSibling(p);
  904. }
  905. }
  906. /* Insert argument output code */
  907. for (p = l; p;) {
  908. if ((tm = Getattr(p, "tmap:argout"))) {
  909. addThrows(n, "tmap:argout", p);
  910. Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */
  911. Replaceall(tm, "$result", "jresult");
  912. Replaceall(tm, "$input", Getattr(p, "emit:input"));
  913. Printv(outarg, tm, "\n", NIL);
  914. p = Getattr(p, "tmap:argout:next");
  915. } else {
  916. p = nextSibling(p);
  917. }
  918. }
  919. // Get any Java exception classes in the throws typemap
  920. ParmList *throw_parm_list = NULL;
  921. if ((throw_parm_list = Getattr(n, "catchlist"))) {
  922. Swig_typemap_attach_parms("throws", throw_parm_list, f);
  923. for (p = throw_parm_list; p; p = nextSibling(p)) {
  924. if (Getattr(p, "tmap:throws")) {
  925. addThrows(n, "tmap:throws", p);
  926. }
  927. }
  928. }
  929. // Now write code to make the function call
  930. if (!native_function_flag) {
  931. Swig_director_emit_dynamic_cast(n, f);
  932. String *actioncode = emit_action(n);
  933. // Handle exception classes specified in the "except" feature's "throws" attribute
  934. addThrows(n, "feature:except", n);
  935. /* Return value if necessary */
  936. if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
  937. addThrows(n, "tmap:out", n);
  938. Replaceall(tm, "$result", "jresult");
  939. if (GetFlag(n, "feature:new"))
  940. Replaceall(tm, "$owner", "1");
  941. else
  942. Replaceall(tm, "$owner", "0");
  943. Printf(f->code, "%s", tm);
  944. if (Len(tm))
  945. Printf(f->code, "\n");
  946. } else {
  947. Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(t, 0), Getattr(n, "name"));
  948. }
  949. emit_return_variable(n, t, f);
  950. }
  951. /* Output argument output code */
  952. Printv(f->code, outarg, NIL);
  953. /* Output cleanup code */
  954. Printv(f->code, cleanup, NIL);
  955. /* Look to see if there is any newfree cleanup code */
  956. if (GetFlag(n, "feature:new")) {
  957. if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
  958. addThrows(n, "tmap:newfree", n);
  959. Printf(f->code, "%s\n", tm);
  960. }
  961. }
  962. /* See if there is any return cleanup code */
  963. if (!native_function_flag) {
  964. if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
  965. addThrows(n, "tmap:ret", n);
  966. Printf(f->code, "%s\n", tm);
  967. }
  968. }
  969. /* Finish C function and intermediary class function definitions */
  970. Printf(imclass_class_code, ")");
  971. generateThrowsClause(n, imclass_class_code);
  972. Printf(imclass_class_code, ";\n");
  973. Printf(f->def, ") {");
  974. if (!is_void_return)
  975. Printv(f->code, " return jresult;\n", NIL);
  976. Printf(f->code, "}\n");
  977. /* Substitute the cleanup code */
  978. Replaceall(f->code, "$cleanup", cleanup);
  979. /* Substitute the function name */
  980. Replaceall(f->code, "$symname", symname);
  981. /* Contract macro modification */
  982. Replaceall(f->code, "SWIG_contract_assert(", "SWIG_contract_assert($null, ");
  983. if (!is_void_return)
  984. Replaceall(f->code, "$null", "0");
  985. else
  986. Replaceall(f->code, "$null", "");
  987. /* Dump the function out */
  988. if (!native_function_flag)
  989. Wrapper_print(f, f_wrappers);
  990. if (!(proxy_flag && is_wrapping_class()) && !enum_constant_flag) {
  991. moduleClassFunctionHandler(n);
  992. }
  993. /*
  994. * Generate the proxy class getters/setters for public member variables.
  995. * Not for enums and constants.
  996. */
  997. if (proxy_flag && wrapping_member_flag && !enum_constant_flag) {
  998. // Capitalize the first letter in the variable to create a JavaBean type getter/setter function name
  999. bool getter_flag = Cmp(symname, Swig_name_set(getNSpace(), Swig_name_member(0, getClassPrefix(), variable_name))) != 0;
  1000. String *getter_setter_name = NewString("");
  1001. if (!getter_flag)
  1002. Printf(getter_setter_name, "set");
  1003. else
  1004. Printf(getter_setter_name, "get");
  1005. Putc(toupper((int) *Char(variable_name)), getter_setter_name);
  1006. Printf(getter_setter_name, "%s", Char(variable_name) + 1);
  1007. Setattr(n, "proxyfuncname", getter_setter_name);
  1008. Setattr(n, "imfuncname", symname);
  1009. proxyClassFunctionHandler(n);
  1010. Delete(getter_setter_name);
  1011. }
  1012. Delete(c_return_type);
  1013. Delete(im_return_type);
  1014. Delete(cleanup);
  1015. Delete(outarg);
  1016. Delete(body);
  1017. Delete(overloaded_name);
  1018. DelWrapper(f);
  1019. return SWIG_OK;
  1020. }
  1021. /* -----------------------------------------------------------------------
  1022. * variableWrapper()
  1023. * ----------------------------------------------------------------------- */
  1024. virtual int variableWrapper(Node *n) {
  1025. variable_wrapper_flag = true;
  1026. Language::variableWrapper(n); /* Default to functions */
  1027. variable_wrapper_flag = false;
  1028. return SWIG_OK;
  1029. }
  1030. /* -----------------------------------------------------------------------
  1031. * globalvariableHandler()
  1032. * ------------------------------------------------------------------------ */
  1033. virtual int globalvariableHandler(Node *n) {
  1034. variable_name = Getattr(n, "sym:name");
  1035. global_variable_flag = true;
  1036. int ret = Language::globalvariableHandler(n);
  1037. global_variable_flag = false;
  1038. return ret;
  1039. }
  1040. String *getCurrentScopeName(String *nspace) {
  1041. String *scope = 0;
  1042. if (nspace || getCurrentClass()) {
  1043. scope = NewString("");
  1044. if (nspace)
  1045. Printf(scope, "%s", nspace);
  1046. if (Node* cls = getCurrentClass()) {
  1047. if (Node *outer = Getattr(cls, "nested:outer")) {
  1048. String *outerClassesPrefix = Copy(Getattr(outer, "sym:name"));
  1049. for (outer = Getattr(outer, "nested:outer"); outer != 0; outer = Getattr(outer, "nested:outer")) {
  1050. Push(outerClassesPrefix, ".");
  1051. Push(outerClassesPrefix, Getattr(outer, "sym:name"));
  1052. }
  1053. Printv(scope, nspace ? "." : "", outerClassesPrefix, ".", proxy_class_name, NIL);
  1054. Delete(outerClassesPrefix);
  1055. } else
  1056. Printv(scope, nspace ? "." : "", proxy_class_name, NIL);
  1057. }
  1058. }
  1059. return scope;
  1060. }
  1061. /* ----------------------------------------------------------------------
  1062. * enumDeclaration()
  1063. *
  1064. * C/C++ enums can be mapped in one of 4 ways, depending on the java:enum feature specified:
  1065. * 1) Simple enums - simple constant within the proxy class or module class
  1066. * 2) Typeunsafe enums - simple constant in a Java class (class named after the c++ enum name)
  1067. * 3) Typesafe enum - typesafe enum pattern (class named after the c++ enum name)
  1068. * 4) Proper enums - proper Java enum
  1069. * Anonymous enums always default to 1)
  1070. * ---------------------------------------------------------------------- */
  1071. virtual int enumDeclaration(Node *n) {
  1072. if (!ImportMode) {
  1073. if (getCurrentClass() && (cplus_mode != PUBLIC))
  1074. return SWIG_NOWRAP;
  1075. String *nspace = Getattr(n, "sym:nspace"); // NSpace/getNSpace() only works during Language::enumDeclaration call
  1076. if (proxy_flag && !is_wrapping_class()) {
  1077. // Global enums / enums in a namespace
  1078. assert(!full_imclass_name);
  1079. constructIntermediateClassName(n);
  1080. }
  1081. enum_code = NewString("");
  1082. String *symname = Getattr(n, "sym:name");
  1083. String *constants_code = (proxy_flag && is_wrapping_class())? proxy_class_constants_code : module_class_constants_code;
  1084. EnumFeature enum_feature = decodeEnumFeature(n);
  1085. String *typemap_lookup_type = Getattr(n, "name");
  1086. if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) {
  1087. // Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper Java enum
  1088. if (doxygen && doxygenTranslator->hasDocumentation(n)) {
  1089. String *doxygen_comments = doxygenTranslator->getDocumentation(n, 0);
  1090. if (comment_creation_chatter)
  1091. Printf(enum_code, "/* This was generated from enumDeclaration() */\n");
  1092. Printv(enum_code, Char(doxygen_comments), NIL);
  1093. Delete(doxygen_comments);
  1094. }
  1095. String *scope = getCurrentScopeName(nspace);
  1096. if (!addSymbol(symname, n, scope))
  1097. return SWIG_ERROR;
  1098. // Pure Java baseclass and interfaces
  1099. const String *pure_baseclass = typemapLookup(n, "javabase", typemap_lookup_type, WARN_NONE);
  1100. const String *pure_interfaces = typemapLookup(n, "javainterfaces", typemap_lookup_type, WARN_NONE);
  1101. // Emit the enum
  1102. Printv(enum_code, typemapLookup(n, "javaclassmodifiers", typemap_lookup_type, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers (enum modifiers really)
  1103. " ", symname, *Char(pure_baseclass) ? // Bases
  1104. " extends " : "", pure_baseclass, *Char(pure_interfaces) ? // Interfaces
  1105. " implements " : "", pure_interfaces, " {\n", NIL);
  1106. if (proxy_flag && is_wrapping_class())
  1107. Replaceall(enum_code, "$static ", "static ");
  1108. else
  1109. Replaceall(enum_code, "$static ", "");
  1110. Delete(scope);
  1111. } else {
  1112. if (symname && !Getattr(n, "unnamedinstance"))
  1113. Printf(constants_code, " // %s \n", symname);
  1114. // Translate and write javadoc comment for the enum itself if flagged
  1115. if (doxygen && doxygenTranslator->hasDocumentation(n)) {
  1116. String *doxygen_comments = doxygenTranslator->getDocumentation(n, " ");
  1117. if (comment_creation_chatter)
  1118. Printf(constants_code, "/* This was generated from enumDeclaration() */\n");
  1119. Printf(constants_code, Char(doxygen_comments));
  1120. Printf(constants_code, "\n");
  1121. Delete(doxygen_comments);
  1122. }
  1123. }
  1124. // Emit each enum item
  1125. Language::enumDeclaration(n);
  1126. if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) {
  1127. // Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper Java enum
  1128. // Finish the enum declaration
  1129. // Typemaps are used to generate the enum definition in a similar manner to proxy classes.
  1130. Printv(enum_code, (enum_feature == ProperEnum) ? ";\n" : "", typemapLookup(n, "javabody", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF), // main body of class
  1131. typemapLookup(n, "javacode", typemap_lookup_type, WARN_NONE), // extra Java code
  1132. "}", NIL);
  1133. Replaceall(enum_code, "$javaclassname", symname);
  1134. // Substitute $enumvalues - intended usage is for typesafe enums
  1135. if (Getattr(n, "enumvalues"))
  1136. Replaceall(enum_code, "$enumvalues", Getattr(n, "enumvalues"));
  1137. else
  1138. Replaceall(enum_code, "$enumvalues", "");
  1139. if (proxy_flag && is_wrapping_class()) {
  1140. // Enums defined within the C++ class are defined within the proxy class
  1141. // Add extra indentation
  1142. Replaceall(enum_code, "\n", "\n ");
  1143. Replaceall(enum_code, " \n", "\n");
  1144. Printv(proxy_class_constants_code, " ", enum_code, "\n\n", NIL);
  1145. } else {
  1146. // Global enums are defined in their own file
  1147. String *output_directory = outputDirectory(nspace);
  1148. String *filen = NewStringf("%s%s.java", output_directory, symname);
  1149. File *f_enum = NewFile(filen, "w", SWIG_output_files());
  1150. if (!f_enum) {
  1151. FileErrorDisplay(filen);
  1152. Exit(EXIT_FAILURE);
  1153. }
  1154. Append(filenames_list, Copy(filen));
  1155. Delete(filen);
  1156. filen = NULL;
  1157. // Start writing out the enum file
  1158. emitBanner(f_enum);
  1159. if (package || nspace) {
  1160. Printf(f_enum, "package ");
  1161. if (package)
  1162. Printv(f_enum, package, nspace ? "." : "", NIL);
  1163. if (nspace)
  1164. Printv(f_enum, nspace, NIL);
  1165. Printf(f_enum, ";\n");
  1166. }
  1167. Printv(f_enum, typemapLookup(n, "javaimports", typemap_lookup_type, WARN_NONE), // Import statements
  1168. "\n", enum_code, "\n", NIL);
  1169. Printf(f_enum, "\n");
  1170. Delete(f_enum);
  1171. Delete(output_directory);
  1172. }
  1173. } else {
  1174. // Wrap C++ enum with simple constant
  1175. Printf(enum_code, "\n");
  1176. if (proxy_flag && is_wrapping_class())
  1177. Printv(proxy_class_constants_code, enum_code, NIL);
  1178. else
  1179. Printv(module_class_constants_code, enum_code, NIL);
  1180. }
  1181. Delete(enum_code);
  1182. enum_code = NULL;
  1183. if (proxy_flag && !is_wrapping_class()) {
  1184. Delete(full_imclass_name);
  1185. full_imclass_name = 0;
  1186. }
  1187. }
  1188. return SWIG_OK;
  1189. }
  1190. /* ----------------------------------------------------------------------
  1191. * enumvalueDeclaration()
  1192. * ---------------------------------------------------------------------- */
  1193. virtual int enumvalueDeclaration(Node *n) {
  1194. if (getCurrentClass() && (cplus_mode != PUBLIC))
  1195. return SWIG_NOWRAP;
  1196. Swig_require("enumvalueDeclaration", n, "*name", "?value", NIL);
  1197. String *symname = Getattr(n, "sym:name");
  1198. String *value = Getattr(n, "value");
  1199. String *name = Getattr(n, "name");
  1200. Node *parent = parentNode(n);
  1201. int unnamedinstance = GetFlag(parent, "unnamedinstance");
  1202. String *parent_name = Getattr(parent, "name");
  1203. String *nspace = getNSpace();
  1204. String *newsymname = 0;
  1205. String *tmpValue;
  1206. // Strange hack from parent method
  1207. if (value)
  1208. tmpValue = NewString(value);
  1209. else
  1210. tmpValue = NewString(name);
  1211. // Note that this is used in enumValue() amongst other places
  1212. Setattr(n, "value", tmpValue);
  1213. // Deal with enum values that are not int
  1214. int swigtype = SwigType_type(Getattr(n, "type"));
  1215. if (swigtype == T_BOOL) {
  1216. const char *val = Equal(Getattr(n, "enumvalue"), "true") ? "1" : "0";
  1217. Setattr(n, "enumvalue", val);
  1218. } else if (swigtype == T_CHAR) {
  1219. String *val = NewStringf("'%(escape)s'", Getattr(n, "enumvalue"));
  1220. Setattr(n, "enumvalue", val);
  1221. Delete(val);
  1222. }
  1223. {
  1224. EnumFeature enum_feature = decodeEnumFeature(parent);
  1225. if ((enum_feature == SimpleEnum) && GetFlag(parent, "scopedenum")) {
  1226. newsymname = Swig_name_member(0, Getattr(parent, "sym:name"), symname);
  1227. symname = newsymname;
  1228. }
  1229. // Add to language symbol table
  1230. String *scope = 0;
  1231. if (unnamedinstance || !parent_name || enum_feature == SimpleEnum) {
  1232. String *enumClassPrefix = getEnumClassPrefix();
  1233. if (enumClassPrefix) {
  1234. scope = NewString("");
  1235. if (nspace)
  1236. Printf(scope, "%s.", nspace);
  1237. Printf(scope, "%s", enumClassPrefix);
  1238. } else {
  1239. scope = Copy(constants_interface_name);
  1240. }
  1241. } else {
  1242. scope = getCurrentScopeName(nspace);
  1243. if (!scope)
  1244. scope = Copy(Getattr(parent, "sym:name"));
  1245. else
  1246. Printf(scope, ".%s", Getattr(parent, "sym:name"));
  1247. }
  1248. if (!addSymbol(symname, n, scope))
  1249. return SWIG_ERROR;
  1250. if ((enum_feature == ProperEnum) && parent_name && !unnamedinstance) {
  1251. if (!GetFlag(n, "firstenumitem"))
  1252. Printf(enum_code, ",\n");
  1253. }
  1254. // Translate and write javadoc comment if flagged
  1255. if (doxygen && doxygenTranslator->hasDocumentation(n)) {
  1256. String *doxygen_comments = doxygenTranslator->getDocumentation(n, " ");
  1257. if (comment_creation_chatter)
  1258. Printf(enum_code, "/* This was generated from enumvalueDeclaration() */\n");
  1259. Printv(enum_code, Char(doxygen_comments), NIL);
  1260. Delete(doxygen_comments);
  1261. }
  1262. if ((enum_feature == ProperEnum) && parent_name && !unnamedinstance) {
  1263. // Wrap (non-anonymous) C/C++ enum with a proper Java enum
  1264. // Emit the enum item.
  1265. Printf(enum_code, " %s", symname);
  1266. if (Getattr(n, "enumvalue")) {
  1267. String *value = enumValue(n);
  1268. Printf(enum_code, "(%s)", value);
  1269. Delete(value);
  1270. }
  1271. } else {
  1272. // Wrap C/C++ enums with constant integers or use the typesafe enum pattern
  1273. SwigType *typemap_lookup_type = parent_name ? parent_name : NewString("enum ");
  1274. Setattr(n, "type", typemap_lookup_type);
  1275. const String *tm = typemapLookup(n, "jstype", typemap_lookup_type, WARN_JAVA_TYPEMAP_JSTYPE_UNDEF);
  1276. String *return_type = Copy(tm);
  1277. substituteClassname(typemap_lookup_type, return_type);
  1278. const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
  1279. methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
  1280. if ((enum_feature == TypesafeEnum) && parent_name && !unnamedinstance) {
  1281. // Wrap (non-anonymous) enum using the typesafe enum pattern
  1282. if (Getattr(n, "enumvalue")) {
  1283. String *value = enumValue(n);
  1284. Printf(enum_code, " %s final static %s %s = new %s(\"%s\", %s);\n", methodmods, return_type, symname, return_type, symname, value);
  1285. Delete(value);
  1286. } else {
  1287. Printf(enum_code, " %s final static %s %s = new %s(\"%s\");\n", methodmods, return_type, symname, return_type, symname);
  1288. }
  1289. } else {
  1290. // Simple integer constants
  1291. // Note these are always generated for anonymous enums, no matter what enum_feature is specified
  1292. // Code generated is the same for SimpleEnum and TypeunsafeEnum -> the class it is generated into is determined later
  1293. String *value = enumValue(n);
  1294. Printf(enum_code, " %s final static %s %s = %s;\n", methodmods, return_type, symname, value);
  1295. Delete(value);
  1296. }
  1297. Delete(return_type);
  1298. }
  1299. // Add the enum value to the comma separated list being constructed in the enum declaration.
  1300. String *enumvalues = Getattr(parent, "enumvalues");
  1301. if (!enumvalues)
  1302. Setattr(parent, "enumvalues", Copy(symname));
  1303. else
  1304. Printv(enumvalues, ", ", symname, NIL);
  1305. Delete(scope);
  1306. }
  1307. Delete(newsymname);
  1308. Delete(tmpValue);
  1309. Swig_restore(n);
  1310. return SWIG_OK;
  1311. }
  1312. /* -----------------------------------------------------------------------
  1313. * constantWrapper()
  1314. * Used for wrapping constants - #define or %constant.
  1315. * Also for inline initialised const static primitive type member variables (short, int, double, enums etc).
  1316. * Java static final variables are generated for these.
  1317. * If the %javaconst(1) feature is used then the C constant value is used to initialise the Java final variable.
  1318. * If not, a JNI method is generated to get the C constant value for initialisation of the Java final variable.
  1319. * However, if the %javaconstvalue feature is used, it overrides all other ways to generate the initialisation.
  1320. * Also note that this method might be called for wrapping enum items (when the enum is using %javaconst(0)).
  1321. * ------------------------------------------------------------------------ */
  1322. virtual int constantWrapper(Node *n) {
  1323. String *symname = Getattr(n, "sym:name");
  1324. SwigType *t = Getattr(n, "type");
  1325. SwigType *valuetype = Getattr(n, "valuetype");
  1326. ParmList *l = Getattr(n, "parms");
  1327. String *tm;
  1328. String *return_type = NewString("");
  1329. String *constants_code = NewString("");
  1330. Swig_save("constantWrapper", n, "value", NIL);
  1331. // Translate and write javadoc comment if flagged
  1332. if (doxygen && doxygenTranslator->hasDocumentation(n)) {
  1333. String *doxygen_comments = doxygenTranslator->getDocumentation(n, " ");
  1334. if (comment_creation_chatter)
  1335. Printf(constants_code, "/* This was generated from constantWrapper() */\n");
  1336. Printv(constants_code, Char(doxygen_comments), NIL);
  1337. Delete(doxygen_comments);
  1338. }
  1339. bool is_enum_item = (Cmp(nodeType(n), "enumitem") == 0);
  1340. const String *itemname = (proxy_flag && wrapping_member_flag) ? variable_name : symname;
  1341. if (!is_enum_item) {
  1342. String *scope = 0;
  1343. if (proxy_class_name) {
  1344. String *nspace = getNSpace();
  1345. scope = NewString("");
  1346. if (nspace)
  1347. Printf(scope, "%s.", nspace);
  1348. Printf(scope, "%s", proxy_class_name);
  1349. } else {
  1350. scope = Copy(constants_interface_name);
  1351. }
  1352. if (!addSymbol(itemname, n, scope))
  1353. return SWIG_ERROR;
  1354. Delete(scope);
  1355. }
  1356. // The %javaconst feature determines how the constant value is obtained
  1357. int const_feature_flag = GetFlag(n, "feature:java:const");
  1358. /* Adjust the enum type for the Swig_typemap_lookup.
  1359. * We want the same jstype typemap for all the enum items so we use the enum type (parent node). */
  1360. if (is_enum_item) {
  1361. t = Getattr(parentNode(n), "enumtype");
  1362. Setattr(n, "type", t);
  1363. }
  1364. /* Attach the non-standard typemaps to the parameter list. */
  1365. Swig_typemap_attach_parms("jstype", l, NULL);
  1366. /* Get Java return types */
  1367. bool classname_substituted_flag = false;
  1368. if ((tm = Swig_typemap_lookup("jstype", n, "", 0))) {
  1369. classname_substituted_flag = substituteClassname(t, tm);
  1370. Printf(return_type, "%s", tm);
  1371. } else {
  1372. Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(t, 0));
  1373. }
  1374. // Add the stripped quotes back in
  1375. String *new_value = NewString("");
  1376. if (SwigType_type(t) == T_STRING) {
  1377. Printf(new_value, "\"%s\"", Copy(Getattr(n, "value")));
  1378. Setattr(n, "value", new_value);
  1379. } else if (SwigType_type(t) == T_CHAR) {
  1380. Printf(new_value, "\'%s\'", Copy(Getattr(n, "value")));
  1381. Setattr(n, "value", new_value);
  1382. }
  1383. const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
  1384. methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
  1385. Printf(constants_code, " %s final static %s %s = ", methodmods, return_type, itemname);
  1386. // Check for the %javaconstvalue feature
  1387. String *value = Getattr(n, "feature:java:constvalue");
  1388. if (value) {
  1389. Printf(constants_code, "%s;\n", value);
  1390. } else if (!const_feature_flag) {
  1391. // Default enum and constant handling will work with any type of C constant and initialises the Java variable from C through a JNI call.
  1392. if (classname_substituted_flag) {
  1393. if (SwigType_isenum(t)) {
  1394. // This handles wrapping of inline initialised const enum static member variables (not when wrapping enum items - ignored later on)
  1395. Printf(constants_code, "%s.swigToEnum(%s.%s());\n", return_type, full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname));
  1396. } else {
  1397. // This handles function pointers using the %constant directive
  1398. Printf(constants_code, "new %s(%s.%s(), false);\n", return_type, full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname));
  1399. }
  1400. } else {
  1401. Printf(constants_code, "%s.%s();\n", full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname));
  1402. }
  1403. // Each constant and enum value is wrapped with a separate JNI function call
  1404. SetFlag(n, "feature:immutable");
  1405. enum_constant_flag = true;
  1406. variableWrapper(n);
  1407. enum_constant_flag = false;
  1408. } else {
  1409. // Alternative constant handling will use the C syntax to make a true Java constant and hope that it compiles as Java code
  1410. if (Getattr(n, "wrappedasconstant")) {
  1411. if (SwigType_type(valuetype) == T_CHAR)
  1412. Printf(constants_code, "\'%(escape)s\';\n", Getattr(n, "staticmembervariableHandler:value"));
  1413. else
  1414. Printf(constants_code, "%s;\n", Getattr(n, "staticmembervariableHandler:value"));
  1415. } else {
  1416. Printf(constants_code, "%s;\n", Getattr(n, "value"));
  1417. }
  1418. }
  1419. // Emit the generated code to appropriate place
  1420. // Enums only emit the intermediate and JNI methods, so no proxy or module class wrapper methods needed
  1421. if (!is_enum_item) {
  1422. if (proxy_flag && wrapping_member_flag)
  1423. Printv(proxy_class_constants_code, constants_code, NIL);
  1424. else
  1425. Printv(module_class_constants_code, constants_code, NIL);
  1426. }
  1427. // Cleanup
  1428. Swig_restore(n);
  1429. Delete(new_value);
  1430. Delete(return_type);
  1431. Delete(constants_code);
  1432. return SWIG_OK;
  1433. }
  1434. /* -----------------------------------------------------------------------------
  1435. * insertDirective()
  1436. * ----------------------------------------------------------------------------- */
  1437. virtual int insertDirective(Node *n) {
  1438. int ret = SWIG_OK;
  1439. String *code = Getattr(n, "code");
  1440. String *section = Getattr(n, "section");
  1441. Replaceall(code, "$module", module_class_name);
  1442. Replaceall(code, "$imclassname", imclass_name);
  1443. if (!ImportMode && (Cmp(section, "proxycode") == 0)) {
  1444. if (proxy_class_code) {
  1445. Swig_typemap_replace_embedded_typemap(code, n);
  1446. int offset = Len(code) > 0 && *Char(code) == '\n' ? 1 : 0;
  1447. Printv(proxy_class_code, Char(code) + offset, "\n", NIL);
  1448. }
  1449. } else {
  1450. ret = Language::insertDirective(n);
  1451. }
  1452. return ret;
  1453. }
  1454. /* -----------------------------------------------------------------------------
  1455. * pragmaDirective()
  1456. *
  1457. * Valid Pragmas:
  1458. * jniclassbase - base (extends) for the intermediary class
  1459. * jniclasspackage - package in which to generate the intermediary class
  1460. * jniclassclassmodifiers - class modifiers for the intermediary class
  1461. * jniclasscode - text (java code) is copied verbatim to the intermediary class
  1462. * jniclassimports - import statements for the intermediary class
  1463. * jniclassinterfaces - interface (implements) for the intermediary class
  1464. *
  1465. * modulebase - base (extends) for the module class
  1466. * moduleclassmodifiers - class modifiers for the module class
  1467. * modulecode - text (java code) is copied verbatim to the module class
  1468. * moduleimports - import statements for the module class
  1469. * moduleinterfaces - interface (implements) for the module class
  1470. *
  1471. * ----------------------------------------------------------------------------- */
  1472. virtual int pragmaDirective(Node *n) {
  1473. if (!ImportMode) {
  1474. String *lang = Getattr(n, "lang");
  1475. String *code = Getattr(n, "name");
  1476. String *value = Getattr(n, "value");
  1477. if (Strcmp(lang, "java") == 0) {
  1478. String *strvalue = NewString(value);
  1479. Replaceall(strvalue, "\\\"", "\"");
  1480. if (Strcmp(code, "jniclassbase") == 0) {
  1481. Delete(imclass_baseclass);
  1482. imclass_baseclass = Copy(strvalue);
  1483. } else if (Strcmp(code, "jniclasspackage") == 0) {
  1484. Delete(imclass_package);
  1485. imclass_package = Copy(strvalue);
  1486. String *imclass_class_package_jniname = makeValidJniName(imclass_package);
  1487. Printv(jnipackage, imclass_class_package_jniname, NIL);
  1488. Delete(imclass_class_package_jniname);
  1489. Replaceall(jnipackage, NSPACE_SEPARATOR, "_");
  1490. Append(jnipackage, "_");
  1491. String *wrapper_name = NewString("");
  1492. String *imclass_class_jniname = makeValidJniName(imclass_name);
  1493. Printf(wrapper_name, "Java_%s%s_%%f", jnipackage, imclass_class_jniname);
  1494. Delete(imclass_class_jniname);
  1495. Swig_name_unregister("wrapper");
  1496. Swig_name_register("wrapper", Char(wrapper_name));
  1497. Delete(wrapper_name);
  1498. } else if (Strcmp(code, "jniclassclassmodifiers") == 0) {
  1499. Delete(imclass_class_modifiers);
  1500. imclass_class_modifiers = Copy(strvalue);
  1501. } else if (Strcmp(code, "jniclasscode") == 0) {
  1502. Printf(imclass_class_code, "%s\n", strvalue);
  1503. } else if (Strcmp(code, "jniclassimports") == 0) {
  1504. Delete(imclass_imports);
  1505. imclass_imports = Copy(strvalue);
  1506. } else if (Strcmp(code, "jniclassinterfaces") == 0) {
  1507. Delete(imclass_interfaces);
  1508. imclass_interfaces = Copy(strvalue);
  1509. } else if (Strcmp(code, "modulebase") == 0) {
  1510. Delete(module_baseclass);
  1511. module_baseclass = Copy(strvalue);
  1512. } else if (Strcmp(code, "moduleclassmodifiers") == 0) {
  1513. Delete(module_class_modifiers);
  1514. module_class_modifiers = Copy(strvalue);
  1515. } else if (Strcmp(code, "modulecode") == 0) {
  1516. Printf(module_class_code, "%s\n", strvalue);
  1517. } else if (Strcmp(code, "moduleimports") == 0) {
  1518. Delete(module_imports);
  1519. module_imports = Copy(strvalue);
  1520. } else if (Strcmp(code, "moduleinterfaces") == 0) {
  1521. Delete(module_interfaces);
  1522. module_interfaces = Copy(strvalue);
  1523. } else if (Strcmp(code, "moduleimport") == 0) {
  1524. Swig_error(input_file, line_number, "Deprecated pragma. Please use the moduleimports pragma.\n");
  1525. } else if (Strcmp(code, "moduleinterface") == 0) {
  1526. Swig_error(input_file, line_number, "Deprecated pragma. Please use the moduleinterfaces pragma.\n");
  1527. } else if (Strcmp(code, "modulemethodmodifiers") == 0) {
  1528. Swig_error(input_file, line_number, "Deprecated pragma. Please use %%javamethodmodifiers.\n");
  1529. } else if (Strcmp(code, "allshadowimport") == 0) {
  1530. Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javaimports).\n");
  1531. } else if (Strcmp(code, "allshadowcode") == 0) {
  1532. Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javacode).\n");
  1533. } else if (Strcmp(code, "allshadowbase") == 0) {
  1534. Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javabase).\n");
  1535. } else if (Strcmp(code, "allshadowinterface") == 0) {
  1536. Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javainterfaces).\n");
  1537. } else if (Strcmp(code, "allshadowclassmodifiers") == 0) {
  1538. Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javaclassmodifiers).\n");
  1539. } else if (proxy_flag) {
  1540. if (Strcmp(code, "shadowcode") == 0) {
  1541. Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javacode).\n");
  1542. } else if (Strcmp(code, "shadowimport") == 0) {
  1543. Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javaimports).\n");
  1544. } else if (Strcmp(code, "shadowbase") == 0) {
  1545. Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javabase).\n");
  1546. } else if (Strcmp(code, "shadowinterface") == 0) {
  1547. Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javainterfaces).\n");
  1548. } else if (Strcmp(code, "shadowclassmodifiers") == 0) {
  1549. Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javaclassmodifiers).\n");
  1550. } else {
  1551. Swig_error(input_file, line_number, "Unrecognized pragma.\n");
  1552. }
  1553. } else {
  1554. Swig_error(input_file, line_number, "Unrecognized pragma.\n");
  1555. }
  1556. Delete(strvalue);
  1557. }
  1558. }
  1559. return Language::pragmaDirective(n);
  1560. }
  1561. /* -----------------------------------------------------------------------------
  1562. * getQualifiedInterfaceName()
  1563. * ----------------------------------------------------------------------------- */
  1564. String *getQualifiedInterfaceName(Node *n) {
  1565. String *ret = Getattr(n, "interface:qname");
  1566. if (!ret) {
  1567. String *nspace = Getattr(n, "sym:nspace");
  1568. String *symname = Getattr(n, "interface:name");
  1569. if (nspace) {
  1570. if (package)
  1571. ret = NewStringf("%s.%s.%s", package, nspace, symname);
  1572. else
  1573. ret = NewStringf("%s.%s", nspace, symname);
  1574. } else {
  1575. ret = Copy(symname);
  1576. }
  1577. Setattr(n, "interface:qname", ret);
  1578. }
  1579. return ret;
  1580. }
  1581. /* -----------------------------------------------------------------------------
  1582. * getInterfaceName()
  1583. * ----------------------------------------------------------------------------- */
  1584. String *getInterfaceName(SwigType *t, bool qualified) {
  1585. String *interface_name = NULL;
  1586. if (proxy_flag) {
  1587. Node *n = classLookup(t);
  1588. if (n && Getattr(n, "interface:name"))
  1589. interface_name = qualified ? getQualifiedInterfaceName(n) : Getattr(n, "interface:name");
  1590. }
  1591. return interface_name;
  1592. }
  1593. /* -----------------------------------------------------------------------------
  1594. * addInterfaceNameAndUpcasts()
  1595. * ----------------------------------------------------------------------------- */
  1596. void addInterfaceNameAndUpcasts(SwigType *smart, String *interface_list, String *interface_upcasts, List *base_list, SwigType *c_classname) {
  1597. for (Iterator it = First(base_list); it.item; it = Next(it)) {
  1598. Node *base = it.item;
  1599. SwigType *c_baseclassname = Getattr(base, "name");
  1600. String *interface_name = Getattr(base, "interface:name");
  1601. if (Len(interface_list))
  1602. Append(interface_list, ", ");
  1603. Append(interface_list, interface_name);
  1604. Node *attributes = NewHash();
  1605. String *interface_code = Copy(typemapLookup(base, "javainterfacecode", Getattr(base, "classtypeobj"), WARN_JAVA_TYPEMAP_INTERFACECODE_UNDEF, attributes));
  1606. String *cptr_method_name = 0;
  1607. if (interface_code) {
  1608. Replaceall(interface_code, "$interfacename", interface_name);
  1609. Printv(interface_upcasts, interface_code, NIL);
  1610. cptr_method_name = Copy(Getattr(attributes, "tmap:javainterfacecode:cptrmethod"));
  1611. }
  1612. if (!cptr_method_name)
  1613. cptr_method_name = NewStringf("%s_GetInterfaceCPtr", interface_name);
  1614. Replaceall(cptr_method_name, ".", "_");
  1615. Replaceall(cptr_method_name, "$interfacename", interface_name);
  1616. String *upcast_method_name = Swig_name_member(getNSpace(), getClassPrefix(), cptr_method_name);
  1617. upcastsCode(smart, upcast_method_name, c_classname, c_baseclassname);
  1618. Delete(upcast_method_name);
  1619. Delete(cptr_method_name);
  1620. Delete(interface_code);
  1621. }
  1622. }
  1623. /* -----------------------------------------------------------------------------
  1624. * upcastsCode()
  1625. *
  1626. * Add code for C++ casting to base class
  1627. * ----------------------------------------------------------------------------- */
  1628. void upcastsCode(SwigType *smart, String *upcast_method_name, SwigType *c_classname, SwigType *c_baseclassname) {
  1629. String *jniname = makeValidJniName(upcast_method_name);
  1630. String *wname = Swig_name_wrapper(jniname);
  1631. Printf(imclass_cppcasts_code, " public final static native long %s(long jarg1);\n", upcast_method_name);
  1632. String *classname = SwigType_namestr(c_classname);
  1633. String *baseclassname = SwigType_namestr(c_baseclassname);
  1634. if (smart) {
  1635. String *smartnamestr = SwigType_namestr(smart);
  1636. String *bsmartnamestr = SwigType_namestr(smart);
  1637. // TODO: SwigType_typedef_resolve_all on a String instead of SwigType is incorrect for templates
  1638. SwigType *rclassname = SwigType_typedef_resolve_all(classname);
  1639. SwigType *rbaseclassname = SwigType_typedef_resolve_all(baseclassname);
  1640. Replaceall(bsmartnamestr, rclassname, rbaseclassname);
  1641. Printv(upcasts_code,
  1642. "SWIGEXPORT jlong JNICALL ", wname, "(JNIEnv *jenv, jclass jcls, jlong jarg1) {\n",
  1643. " jlong baseptr = 0;\n"
  1644. " ", smartnamestr, " *argp1;\n"
  1645. " (void)jenv;\n"
  1646. " (void)jcls;\n"
  1647. " argp1 = *(", smartnamestr, " **)&jarg1;\n"
  1648. " *(", bsmartnamestr, " **)&baseptr = argp1 ? new ", bsmartnamestr, "(*argp1) : 0;\n"
  1649. " return baseptr;\n"
  1650. "}\n", "\n", NIL);
  1651. Delete(rbaseclassname);
  1652. Delete(rclassname);
  1653. Delete(bsmartnamestr);
  1654. Delete(smartnamestr);
  1655. } else {
  1656. Printv(upcasts_code,
  1657. "SWIGEXPORT jlong JNICALL ", wname, "(JNIEnv *jenv, jclass jcls, jlong jarg1) {\n",
  1658. " jlong baseptr = 0;\n"
  1659. " (void)jenv;\n"
  1660. " (void)jcls;\n"
  1661. " *(", baseclassname, " **)&baseptr = *(", classname, " **)&jarg1;\n"
  1662. " return baseptr;\n"
  1663. "}\n", "\n", NIL);
  1664. }
  1665. Delete(baseclassname);
  1666. Delete(classname);
  1667. Delete(wname);
  1668. Delete(jniname);
  1669. }
  1670. /* -----------------------------------------------------------------------------
  1671. * emitProxyClassDefAndCPPCasts()
  1672. * ----------------------------------------------------------------------------- */
  1673. void emitProxyClassDefAndCPPCasts(Node *n) {
  1674. SwigType *c_classname = Getattr(n, "name");
  1675. SwigType *c_baseclassname = NULL;
  1676. String *baseclass = NULL;
  1677. String *interface_list = NewStringEmpty();
  1678. String *interface_upcasts = NewStringEmpty();
  1679. SwigType *typemap_lookup_type = Getattr(n, "classtypeobj");
  1680. bool feature_director = Swig_directorclass(n) ? true : false;
  1681. bool has_outerclass = Getattr(n, "nested:outer") != 0 && !GetFlag(n, "feature:flatnested");
  1682. SwigType *smart = Swig_cparse_smartptr(n);
  1683. // Inheritance from pure Java classes
  1684. Node *attributes = NewHash();
  1685. const String *pure_baseclass = typemapLookup(n, "javabase", typemap_lookup_type, WARN_NONE, attributes);
  1686. bool purebase_replace = GetFlag(attributes, "tmap:javabase:replace") ? true : false;
  1687. bool purebase_notderived = GetFlag(attributes, "tmap:javabase:notderived") ? true : false;
  1688. Delete(attributes);
  1689. // C++ inheritance
  1690. if (!purebase_replace) {
  1691. List *baselist = Getattr(n, "bases");
  1692. if (baselist) {
  1693. Iterator base = First(baselist);
  1694. while (base.item) {
  1695. if (!(GetFlag(base.item, "feature:ignore") || GetFlag(base.item, "feature:interface"))) {
  1696. SwigType *baseclassname = Getattr(base.item, "name");
  1697. if (!c_baseclassname) {
  1698. String *name = getProxyName(baseclassname);
  1699. if (name) {
  1700. c_baseclassname = baseclassname;
  1701. baseclass = name;
  1702. }
  1703. } else {
  1704. /* Warn about multiple inheritance for additional base class(es) */
  1705. String *proxyclassname = Getattr(n, "classtypeobj");
  1706. Swig_warning(WARN_JAVA_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
  1707. "Warning for %s, base %s ignored. Multiple inheritance is not supported in Java.\n", SwigType_namestr(proxyclassname), SwigType_namestr(baseclassname));
  1708. }
  1709. }
  1710. base = Next(base);
  1711. }
  1712. }
  1713. }
  1714. List *interface_bases = Getattr(n, "interface:bases");
  1715. if (interface_bases)
  1716. addInterfaceNameAndUpcasts(smart, interface_list, interface_upcasts, interface_bases, c_classname);
  1717. bool derived = baseclass != 0;
  1718. if (derived && purebase_notderived)
  1719. pure_baseclass = empty_string;
  1720. const String *wanted_base = baseclass ? baseclass : pure_baseclass;
  1721. if (purebase_replace) {
  1722. wanted_base = pure_baseclass;
  1723. derived = false;
  1724. baseclass = NULL;
  1725. if (purebase_notderived)
  1726. Swig_error(Getfile(n), Getline(n), "The javabase typemap for proxy %s must contain just one of the 'replace' or 'notderived' attributes.\n", typemap_lookup_type);
  1727. } else if (Len(pure_baseclass) > 0 && Len(baseclass) > 0) {
  1728. Swig_warning(WARN_JAVA_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
  1729. "Warning for %s, base %s ignored. Multiple inheritance is not supported in Java. "
  1730. "Perhaps you need one of the 'replace' or 'notderived' attributes in the javabase typemap?\n", typemap_lookup_type, pure_baseclass);
  1731. }
  1732. // Pure Java interfaces
  1733. const String *pure_interfaces = typemapLookup(n, "javainterfaces", typemap_lookup_type, WARN_NONE);
  1734. if (*Char(interface_list) && *Char(pure_interfaces))
  1735. Append(interface_list, ", ");
  1736. Append(interface_list, pure_interfaces);
  1737. // Start writing the proxy class
  1738. if (!has_outerclass) // Import statements
  1739. Printv(proxy_class_def, typemapLookup(n, "javaimports", typemap_lookup_type, WARN_NONE),"\n", NIL);
  1740. // Translate and write javadoc comment if flagged
  1741. if (doxygen && doxygenTranslator->hasDocumentation(n)) {
  1742. String *doxygen_comments = doxygenTranslator->getDocumentation(n, 0);
  1743. if (comment_creation_chatter)
  1744. Printf(proxy_class_def, "/* This was generated from emitProxyClassDefAndCPPCasts() */\n");
  1745. Printv(proxy_class_def, Char(doxygen_comments), NIL);
  1746. Delete(doxygen_comments);
  1747. }
  1748. if (has_outerclass)
  1749. Printv(proxy_class_def, "static ", NIL); // C++ nested classes correspond to static java classes
  1750. Printv(proxy_class_def, typemapLookup(n, "javaclassmodifiers", typemap_lookup_type, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers
  1751. " $javaclassname", // Class name and bases
  1752. (*Char(wanted_base)) ? " extends " : "", wanted_base, *Char(interface_list) ? // Pure Java interfaces
  1753. " implements " : "", interface_list, " {", derived ? typemapLookup(n, "javabody_derived", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF) : // main body of class
  1754. typemapLookup(n, "javabody", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF), // main body of class
  1755. NIL);
  1756. // C++ destructor is wrapped by the delete method
  1757. // Note that the method name is specified in a typemap attribute called methodname
  1758. String *destruct = NewString("");
  1759. const String *tm = NULL;
  1760. attributes = NewHash();
  1761. const String *destruct_methodname = NULL;
  1762. const String *destruct_methodmodifiers = NULL;
  1763. const String *destruct_parameters = NULL;
  1764. if (derived) {
  1765. tm = typemapLookup(n, "javadestruct_derived", typemap_lookup_type, WARN_NONE, attributes);
  1766. destruct_methodname = Getattr(attributes, "tmap:javadestruct_derived:methodname");
  1767. destruct_methodmodifiers = Getattr(attributes, "tmap:javadestruct_derived:methodmodifiers");
  1768. destruct_parameters = Getattr(attributes, "tmap:javadestruct_derived:parameters");
  1769. } else {
  1770. tm = typemapLookup(n, "javadestruct", typemap_lookup_type, WARN_NONE, attributes);
  1771. destruct_methodname = Getattr(attributes, "tmap:javadestruct:methodname");
  1772. destruct_methodmodifiers = Getattr(attributes, "tmap:javadestruct:methodmodifiers");
  1773. destruct_parameters = Getattr(attributes, "tmap:javadestruct:parameters");
  1774. }
  1775. if (tm && *Char(tm)) {
  1776. if (!destruct_methodname) {
  1777. Swig_error(Getfile(n), Getline(n), "No methodname attribute defined in javadestruct%s typemap for %s\n", (derived ? "_derived" : ""), proxy_class_name);
  1778. }
  1779. if (!destruct_methodmodifiers) {
  1780. Swig_error(Getfile(n), Getline(n), "No methodmodifiers attribute defined in javadestruct%s typemap for %s.\n", (derived ? "_derived" : ""), proxy_class_name);
  1781. }
  1782. if (!destruct_parameters)
  1783. destruct_parameters = empty_string;
  1784. }
  1785. // Emit the finalize and delete methods
  1786. if (tm) {
  1787. // Finalize method
  1788. if (*Char(destructor_call)) {
  1789. Printv(proxy_class_def, typemapLookup(n, "javafinalize", typemap_lookup_type, WARN_NONE), NIL);
  1790. }
  1791. // delete method
  1792. Printv(destruct, tm, NIL);
  1793. if (*Char(destructor_call))
  1794. Replaceall(destruct, "$jnicall", destructor_call);
  1795. else
  1796. Replaceall(destruct, "$jnicall", "throw new UnsupportedOperationException(\"C++ destructor does not have public access\")");
  1797. if (*Char(destruct)) {
  1798. Printv(proxy_class_def, "\n ", NIL);
  1799. const String *methodmods = Getattr(n, "destructmethodmodifiers");
  1800. if (methodmods)
  1801. Printv(proxy_class_def, methodmods, NIL);
  1802. else
  1803. Printv(proxy_class_def, destruct_methodmodifiers, NIL);
  1804. Printv(proxy_class_def, " void ", destruct_methodname, "(", destruct_parameters, ")", destructor_throws_clause, " ", destruct, "\n", NIL);
  1805. }
  1806. }
  1807. if (*Char(interface_upcasts))
  1808. Printv(proxy_class_def, interface_upcasts, NIL);
  1809. /* Insert directordisconnect typemap, if this class has directors enabled */
  1810. /* Also insert the swigTakeOwnership and swigReleaseOwnership methods */
  1811. if (feature_director) {
  1812. String *destruct_jnicall, *release_jnicall, *take_jnicall;
  1813. String *changeown_method_name = Swig_name_member(getNSpace(), getClassPrefix(), "change_ownership");
  1814. destruct_jnicall = NewStringf("%s()", destruct_methodname);
  1815. release_jnicall = NewStringf("%s.%s(this, swigCPtr, false)", full_imclass_name, changeown_method_name);
  1816. take_jnicall = NewStringf("%s.%s(this, swigCPtr, true)", full_imclass_name, changeown_method_name);
  1817. emitCodeTypemap(n, false, typemap_lookup_type, "directordisconnect", "methodname", destruct_jnicall);
  1818. emitCodeTypemap(n, false, typemap_lookup_type, "directorowner_release", "methodname", release_jnicall);
  1819. emitCodeTypemap(n, false, typemap_lookup_type, "directorowner_take", "methodname", take_jnicall);
  1820. Delete(destruct_jnicall);
  1821. Delete(changeown_method_name);
  1822. Delete(release_jnicall);
  1823. Delete(take_jnicall);
  1824. }
  1825. Delete(interface_upcasts);
  1826. Delete(interface_list);
  1827. Delete(attributes);
  1828. Delete(destruct);
  1829. // Emit extra user code
  1830. Printv(proxy_class_def, typemapLookup(n, "javacode", typemap_lookup_type, WARN_NONE), // extra Java code
  1831. "\n", NIL);
  1832. if (derived) {
  1833. String *upcast_method_name = Swig_name_member(getNSpace(), getClassPrefix(), smart != 0 ? "SWIGSmartPtrUpcast" : "SWIGUpcast");
  1834. upcastsCode(smart, upcast_method_name, c_classname, c_baseclassname);
  1835. Delete(upcast_method_name);
  1836. }
  1837. Delete(smart);
  1838. }
  1839. /* ----------------------------------------------------------------------
  1840. * emitInterfaceDeclaration()
  1841. * ---------------------------------------------------------------------- */
  1842. void emitInterfaceDeclaration(Node *n, String *interface_name, File *f_interface, String *nspace) {
  1843. if (package || nspace) {
  1844. Printf(f_interface, "package ");
  1845. if (package)
  1846. Printv(f_interface, package, nspace ? "." : "", NIL);
  1847. if (nspace)
  1848. Printv(f_interface, nspace, NIL);
  1849. Printf(f_interface, ";\n");
  1850. }
  1851. Printv(f_interface, typemapLookup(n, "javaimports", Getattr(n, "classtypeobj"), WARN_NONE), "\n", NIL);
  1852. Printv(f_interface, typemapLookup(n, "javainterfacemodifiers", Getattr(n, "classtypeobj"), WARN_JAVA_TYPEMAP_INTERFACEMODIFIERS_UNDEF), NIL);
  1853. Printf(f_interface, " %s", interface_name);
  1854. if (List *baselist = Getattr(n, "bases")) {
  1855. String *bases = 0;
  1856. for (Iterator base = First(baselist); base.item; base = Next(base)) {
  1857. if (GetFlag(base.item, "feature:ignore") || !GetFlag(base.item, "feature:interface"))
  1858. continue; // TODO: warn about skipped non-interface bases
  1859. String *base_iname = Getattr(base.item, "interface:name");
  1860. if (!bases)
  1861. bases = Copy(base_iname);
  1862. else {
  1863. Append(bases, ", ");
  1864. Append(bases, base_iname);
  1865. }
  1866. }
  1867. if (bases) {
  1868. Printv(f_interface, " extends ", bases, NIL);
  1869. Delete(bases);
  1870. }
  1871. }
  1872. Printf(f_interface, " {\n");
  1873. Node *attributes = NewHash();
  1874. String *interface_code = Copy(typemapLookup(n, "javainterfacecode", Getattr(n, "classtypeobj"), WARN_JAVA_TYPEMAP_INTERFACECODE_UNDEF, attributes));
  1875. if (interface_code) {
  1876. String *interface_declaration = Copy(Getattr(attributes, "tmap:javainterfacecode:declaration"));
  1877. if (interface_declaration) {
  1878. Replaceall(interface_declaration, "$interfacename", interface_name);
  1879. Printv(f_interface, interface_declaration, NIL);
  1880. Delete(interface_declaration);
  1881. }
  1882. Delete(interface_code);
  1883. }
  1884. }
  1885. /* ----------------------------------------------------------------------
  1886. * classDeclaration()
  1887. * ---------------------------------------------------------------------- */
  1888. int classDeclaration(Node *n) {
  1889. return Language::classDeclaration(n);
  1890. }
  1891. /* ----------------------------------------------------------------------
  1892. * classHandler()
  1893. * ---------------------------------------------------------------------- */
  1894. virtual int classHandler(Node *n) {
  1895. File *f_proxy = NULL;
  1896. File *f_interface = NULL;
  1897. String *old_proxy_class_name = proxy_class_name;
  1898. String *old_full_proxy_class_name = full_proxy_class_name;
  1899. String *old_full_imclass_name = full_imclass_name;
  1900. String *old_destructor_call = destructor_call;
  1901. String *old_destructor_throws_clause = destructor_throws_clause;
  1902. String *old_proxy_class_constants_code = proxy_class_constants_code;
  1903. String *old_proxy_class_def = proxy_class_def;
  1904. String *old_proxy_class_code = proxy_class_code;
  1905. bool has_outerclass = Getattr(n, "nested:outer") && !GetFlag(n, "feature:flatnested");
  1906. String *old_interface_class_code = interface_class_code;
  1907. interface_class_code = 0;
  1908. if (proxy_flag) {
  1909. proxy_class_name = NewString(Getattr(n, "sym:name"));
  1910. String *nspace = getNSpace();
  1911. constructIntermediateClassName(n);
  1912. String *outerClassesPrefix = 0;
  1913. if (Node *outer = Getattr(n, "nested:outer")) {
  1914. outerClassesPrefix = Copy(Getattr(outer, "sym:name"));
  1915. for (outer = Getattr(outer, "nested:outer"); outer != 0; outer = Getattr(outer, "nested:outer")) {
  1916. Push(outerClassesPrefix, ".");
  1917. Push(outerClassesPrefix, Getattr(outer, "sym:name"));
  1918. }
  1919. }
  1920. if (!nspace) {
  1921. full_proxy_class_name = outerClassesPrefix ? NewStringf("%s.%s", outerClassesPrefix, proxy_class_name) : NewStringf("%s", proxy_class_name);
  1922. if (Cmp(proxy_class_name, imclass_name) == 0) {
  1923. Printf(stderr, "Class name cannot be equal to intermediary class name: %s\n", proxy_class_name);
  1924. Exit(EXIT_FAILURE);
  1925. }
  1926. if (Cmp(proxy_class_name, module_class_name) == 0) {
  1927. Printf(stderr, "Class name cannot be equal to module class name: %s\n", proxy_class_name);
  1928. Exit(EXIT_FAILURE);
  1929. }
  1930. } else {
  1931. if (outerClassesPrefix) {
  1932. if (package)
  1933. full_proxy_class_name = NewStringf("%s.%s.%s.%s", package, nspace, outerClassesPrefix, proxy_class_name);
  1934. else
  1935. full_proxy_class_name = NewStringf("%s.%s.%s", nspace, outerClassesPrefix, proxy_class_name);
  1936. } else {
  1937. if (package)
  1938. full_proxy_class_name = NewStringf("%s.%s.%s", package, nspace, proxy_class_name);
  1939. else
  1940. full_proxy_class_name = NewStringf("%s.%s", nspace, proxy_class_name);
  1941. }
  1942. }
  1943. String *interface_name = GetFlag(n, "feature:interface") ? Getattr(n, "interface:name") : 0;
  1944. if (outerClassesPrefix) {
  1945. String *fnspace = nspace ? NewStringf("%s.%s", nspace, outerClassesPrefix) : outerClassesPrefix;
  1946. if (!addSymbol(proxy_class_name, n, fnspace))
  1947. return SWIG_ERROR;
  1948. if (interface_name && !addInterfaceSymbol(interface_name, n, fnspace))
  1949. return SWIG_ERROR;
  1950. if (nspace)
  1951. Delete(fnspace);
  1952. Delete(outerClassesPrefix);
  1953. } else {
  1954. if (!addSymbol(proxy_class_name, n, nspace))
  1955. return SWIG_ERROR;
  1956. if (interface_name && !addInterfaceSymbol(interface_name, n, nspace))
  1957. return SWIG_ERROR;
  1958. }
  1959. // Each outer proxy class goes into a separate file
  1960. if (!has_outerclass) {
  1961. String *output_directory = outputDirectory(nspace);
  1962. String *filen = NewStringf("%s%s.java", output_directory, proxy_class_name);
  1963. f_proxy = NewFile(filen, "w", SWIG_output_files());
  1964. if (!f_proxy) {
  1965. FileErrorDisplay(filen);
  1966. Exit(EXIT_FAILURE);
  1967. }
  1968. Append(filenames_list, Copy(filen));
  1969. Delete(filen);
  1970. Delete(output_directory);
  1971. // Start writing out the proxy class file
  1972. emitBanner(f_proxy);
  1973. if (package || nspace) {
  1974. Printf(f_proxy, "package ");
  1975. if (package)
  1976. Printv(f_proxy, package, nspace ? "." : "", NIL);
  1977. if (nspace)
  1978. Printv(f_proxy, nspace, NIL);
  1979. Printf(f_proxy, ";\n");
  1980. }
  1981. }
  1982. else
  1983. ++nesting_depth;
  1984. proxy_class_def = NewString("");
  1985. proxy_class_code = NewString("");
  1986. destructor_call = NewString("");
  1987. destructor_throws_clause = NewString("");
  1988. proxy_class_constants_code = NewString("");
  1989. if (GetFlag(n, "feature:interface")) {
  1990. interface_class_code = NewString("");
  1991. String *output_directory = outputDirectory(nspace);
  1992. String *filen = NewStringf("%s%s.java", output_directory, interface_name);
  1993. f_interface = NewFile(filen, "w", SWIG_output_files());
  1994. if (!f_interface) {
  1995. FileErrorDisplay(filen);
  1996. Exit(EXIT_FAILURE);
  1997. }
  1998. Append(filenames_list, filen); // file name ownership goes to the list
  1999. emitBanner(f_interface);
  2000. emitInterfaceDeclaration(n, interface_name, interface_class_code, nspace);
  2001. Delete(filen);
  2002. Delete(output_directory);
  2003. }
  2004. }
  2005. Language::classHandler(n);
  2006. if (proxy_flag) {
  2007. emitProxyClassDefAndCPPCasts(n);
  2008. String *javaclazzname = Swig_name_member(getNSpace(), getClassPrefix(), ""); // mangled full proxy class name
  2009. Replaceall(proxy_class_def, "$javaclassname", proxy_class_name);
  2010. Replaceall(proxy_class_code, "$javaclassname", proxy_class_name);
  2011. Replaceall(proxy_class_constants_code, "$javaclassname", proxy_class_name);
  2012. Replaceall(interface_class_code, "$javaclassname", proxy_class_name);
  2013. Replaceall(proxy_class_def, "$javaclazzname", javaclazzname);
  2014. Replaceall(proxy_class_code, "$javaclazzname", javaclazzname);
  2015. Replaceall(proxy_class_constants_code, "$javaclazzname", javaclazzname);
  2016. Replaceall(interface_class_code, "$javaclazzname", javaclazzname);
  2017. Replaceall(proxy_class_def, "$module", module_class_name);
  2018. Replaceall(proxy_class_code, "$module", module_class_name);
  2019. Replaceall(proxy_class_constants_code, "$module", module_class_name);
  2020. Replaceall(interface_class_code, "$module", module_class_name);
  2021. Replaceall(proxy_class_def, "$imclassname", full_imclass_name);
  2022. Replaceall(proxy_class_code, "$imclassname", full_imclass_name);
  2023. Replaceall(proxy_class_constants_code, "$imclassname", full_imclass_name);
  2024. Replaceall(interface_class_code, "$imclassname", full_imclass_name);
  2025. if (!has_outerclass)
  2026. Printv(f_proxy, proxy_class_def, proxy_class_code, NIL);
  2027. else {
  2028. Swig_offset_string(proxy_class_def, nesting_depth);
  2029. Append(old_proxy_class_code, proxy_class_def);
  2030. Swig_offset_string(proxy_class_code, nesting_depth);
  2031. Append(old_proxy_class_code, proxy_class_code);
  2032. }
  2033. // Write out all the constants
  2034. if (Len(proxy_class_constants_code) != 0) {
  2035. if (!has_outerclass)
  2036. Printv(f_proxy, proxy_class_constants_code, NIL);
  2037. else {
  2038. Swig_offset_string(proxy_class_constants_code, nesting_depth);
  2039. Append(old_proxy_class_code, proxy_class_constants_code);
  2040. }
  2041. }
  2042. if (!has_outerclass) {
  2043. Printf(f_proxy, "}\n");
  2044. Delete(f_proxy);
  2045. f_proxy = NULL;
  2046. } else {
  2047. for (int i = 0; i < nesting_depth; ++i)
  2048. Append(old_proxy_class_code, " ");
  2049. Append(old_proxy_class_code, "}\n\n");
  2050. --nesting_depth;
  2051. }
  2052. if (f_interface) {
  2053. Printv(f_interface, interface_class_code, "}\n", NIL);
  2054. Delete(f_interface);
  2055. f_interface = 0;
  2056. }
  2057. emitDirectorExtraMethods(n);
  2058. Delete(interface_class_code);
  2059. interface_class_code = old_interface_class_code;
  2060. Delete(javaclazzname);
  2061. Delete(proxy_class_name);
  2062. proxy_class_name = old_proxy_class_name;
  2063. Delete(full_proxy_class_name);
  2064. full_proxy_class_name = old_full_proxy_class_name;
  2065. Delete(full_imclass_name);
  2066. full_imclass_name = old_full_imclass_name;
  2067. Delete(destructor_call);
  2068. destructor_call = old_destructor_call;
  2069. Delete(destructor_throws_clause);
  2070. destructor_throws_clause = old_destructor_throws_clause;
  2071. Delete(proxy_class_constants_code);
  2072. proxy_class_constants_code = old_proxy_class_constants_code;
  2073. Delete(proxy_class_def);
  2074. proxy_class_def = old_proxy_class_def;
  2075. Delete(proxy_class_code);
  2076. proxy_class_code = old_proxy_class_code;
  2077. }
  2078. return SWIG_OK;
  2079. }
  2080. /* ----------------------------------------------------------------------
  2081. * memberfunctionHandler()
  2082. * ---------------------------------------------------------------------- */
  2083. virtual int memberfunctionHandler(Node *n) {
  2084. member_func_flag = true;
  2085. Language::memberfunctionHandler(n);
  2086. if (proxy_flag) {
  2087. String *overloaded_name = getOverloadedName(n);
  2088. String *intermediary_function_name = Swig_name_member(getNSpace(), getClassPrefix(), overloaded_name);
  2089. Setattr(n, "proxyfuncname", Getattr(n, "sym:name"));
  2090. Setattr(n, "imfuncname", intermediary_function_name);
  2091. proxyClassFunctionHandler(n);
  2092. Delete(overloaded_name);
  2093. }
  2094. member_func_flag = false;
  2095. return SWIG_OK;
  2096. }
  2097. /* ----------------------------------------------------------------------
  2098. * staticmemberfunctionHandler()
  2099. * ---------------------------------------------------------------------- */
  2100. virtual int staticmemberfunctionHandler(Node *n) {
  2101. static_flag = true;
  2102. member_func_flag = true;
  2103. Language::staticmemberfunctionHandler(n);
  2104. if (proxy_flag) {
  2105. String *overloaded_name = getOverloadedName(n);
  2106. String *intermediary_function_name = Swig_name_member(getNSpace(), getClassPrefix(), overloaded_name);
  2107. Setattr(n, "proxyfuncname", Getattr(n, "sym:name"));
  2108. Setattr(n, "imfuncname", intermediary_function_name);
  2109. proxyClassFunctionHandler(n);
  2110. Delete(overloaded_name);
  2111. }
  2112. static_flag = false;
  2113. member_func_flag = false;
  2114. return SWIG_OK;
  2115. }
  2116. /* -----------------------------------------------------------------------------
  2117. * proxyClassFunctionHandler()
  2118. *
  2119. * Function called for creating a Java wrapper function around a c++ function in the
  2120. * proxy class. Used for both static and non-static C++ class functions.
  2121. * C++ class static functions map to Java static functions.
  2122. * Two extra attributes in the Node must be available. These are "proxyfuncname" -
  2123. * the name of the Java class proxy function, which in turn will call "imfuncname" -
  2124. * the intermediary (JNI) function name in the intermediary class.
  2125. * ----------------------------------------------------------------------------- */
  2126. void proxyClassFunctionHandler(Node *n) {
  2127. SwigType *t = Getattr(n, "type");
  2128. ParmList *l = Getattr(n, "parms");
  2129. String *intermediary_function_name = Getattr(n, "imfuncname");
  2130. String *proxy_function_name = Getattr(n, "proxyfuncname");
  2131. String *tm;
  2132. Parm *p;
  2133. int i;
  2134. String *imcall = NewString("");
  2135. String *return_type = NewString("");
  2136. String *function_code = NewString("");
  2137. bool setter_flag = false;
  2138. String *pre_code = NewString("");
  2139. String *post_code = NewString("");
  2140. bool is_interface = GetFlag(parentNode(n), "feature:interface") && !checkAttribute(n, "kind", "variable")
  2141. && !static_flag && Getattr(n, "interface:owner") == 0;
  2142. if (!proxy_flag)
  2143. return;
  2144. // Wrappers not wanted for some methods where the parameters cannot be overloaded in Java
  2145. if (Getattr(n, "overload:ignore"))
  2146. return;
  2147. // Don't generate proxy method for additional explicitcall method used in directors
  2148. if (GetFlag(n, "explicitcall"))
  2149. return;
  2150. if (l) {
  2151. if (SwigType_type(Getattr(l, "type")) == T_VOID) {
  2152. l = nextSibling(l);
  2153. }
  2154. }
  2155. /* Attach the non-standard typemaps to the parameter list */
  2156. Swig_typemap_attach_parms("in", l, NULL);
  2157. Swig_typemap_attach_parms("jtype", l, NULL);
  2158. Swig_typemap_attach_parms("jstype", l, NULL);
  2159. Swig_typemap_attach_parms("javain", l, NULL);
  2160. /* Get return types */
  2161. if ((tm = Swig_typemap_lookup("jstype", n, "", 0))) {
  2162. // Note that in the case of polymorphic (covariant) return types, the method's return type is changed to be the base of the C++ return type
  2163. SwigType *covariant = Getattr(n, "covariant");
  2164. substituteClassname(covariant ? covariant : t, tm);
  2165. Printf(return_type, "%s", tm);
  2166. if (covariant)
  2167. Swig_warning(WARN_JAVA_COVARIANT_RET, input_file, line_number,
  2168. "Covariant return types not supported in Java. Proxy method will return %s.\n", SwigType_str(covariant, 0));
  2169. } else {
  2170. Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(t, 0));
  2171. }
  2172. if (wrapping_member_flag && !enum_constant_flag) {
  2173. // For wrapping member variables (Javabean setter)
  2174. setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(getNSpace(), Swig_name_member(0, getClassPrefix(), variable_name))) == 0);
  2175. }
  2176. // Translate and write javadoc comment if flagged
  2177. if (doxygen && doxygenTranslator->hasDocumentation(n)) {
  2178. String *doxygen_comments = doxygenTranslator->getDocumentation(n, " ");
  2179. if (comment_creation_chatter)
  2180. Printf(function_code, "/* This was generated from proxyclassfunctionhandler() */\n");
  2181. Printv(function_code, Char(doxygen_comments), NIL);
  2182. Delete(doxygen_comments);
  2183. }
  2184. /* Start generating the proxy function */
  2185. const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
  2186. methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
  2187. Printf(function_code, " %s ", methodmods);
  2188. if (static_flag)
  2189. Printf(function_code, "static ");
  2190. Printf(function_code, "%s %s(", return_type, proxy_function_name);
  2191. if (is_interface)
  2192. Printf(interface_class_code, " %s %s(", return_type, proxy_function_name);
  2193. Printv(imcall, full_imclass_name, ".$imfuncname(", NIL);
  2194. if (!static_flag) {
  2195. Printf(imcall, "swigCPtr");
  2196. String *this_type = Copy(getClassType());
  2197. String *name = NewString("jself");
  2198. String *qualifier = Getattr(n, "qualifier");
  2199. if (qualifier)
  2200. SwigType_push(this_type, qualifier);
  2201. SwigType_add_pointer(this_type);
  2202. Parm *this_parm = NewParm(this_type, name, n);
  2203. Swig_typemap_attach_parms("jtype", this_parm, NULL);
  2204. Swig_typemap_attach_parms("jstype", this_parm, NULL);
  2205. if (prematureGarbageCollectionPreventionParameter(this_type, this_parm))
  2206. Printf(imcall, ", this");
  2207. Delete(this_parm);
  2208. Delete(name);
  2209. Delete(this_type);
  2210. }
  2211. emit_mark_varargs(l);
  2212. int gencomma = !static_flag;
  2213. /* Output each parameter */
  2214. for (i = 0, p = l; p; i++) {
  2215. /* Ignored varargs */
  2216. if (checkAttribute(p, "varargs:ignore", "1")) {
  2217. p = nextSibling(p);
  2218. continue;
  2219. }
  2220. /* Ignored parameters */
  2221. if (checkAttribute(p, "tmap:in:numinputs", "0")) {
  2222. p = Getattr(p, "tmap:in:next");
  2223. continue;
  2224. }
  2225. /* Ignore the 'this' argument for variable wrappers */
  2226. if (!(variable_wrapper_flag && i == 0) || static_flag) {
  2227. SwigType *pt = Getattr(p, "type");
  2228. String *param_type = NewString("");
  2229. /* Get the Java parameter type */
  2230. if ((tm = Getattr(p, "tmap:jstype"))) {
  2231. substituteClassname(pt, tm);
  2232. Printf(param_type, "%s", tm);
  2233. } else {
  2234. Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(pt, 0));
  2235. }
  2236. if (gencomma)
  2237. Printf(imcall, ", ");
  2238. String *arg = makeParameterName(n, p, i, setter_flag);
  2239. // Use typemaps to transform type used in Java proxy wrapper (in proxy class) to type used in JNI function (in intermediary class)
  2240. if ((tm = Getattr(p, "tmap:javain"))) {
  2241. addThrows(n, "tmap:javain", p);
  2242. substituteClassname(pt, tm);
  2243. Replaceall(tm, "$javainput", arg);
  2244. String *pre = Getattr(p, "tmap:javain:pre");
  2245. if (pre) {
  2246. substituteClassname(pt, pre);
  2247. Replaceall(pre, "$javainput", arg);
  2248. if (Len(pre_code) > 0)
  2249. Printf(pre_code, "\n");
  2250. Printv(pre_code, pre, NIL);
  2251. }
  2252. String *post = Getattr(p, "tmap:javain:post");
  2253. if (post) {
  2254. substituteClassname(pt, post);
  2255. Replaceall(post, "$javainput", arg);
  2256. if (Len(post_code) > 0)
  2257. Printf(post_code, "\n");
  2258. Printv(post_code, post, NIL);
  2259. }
  2260. Printv(imcall, tm, NIL);
  2261. } else {
  2262. Swig_warning(WARN_JAVA_TYPEMAP_JAVAIN_UNDEF, input_file, line_number, "No javain typemap defined for %s\n", SwigType_str(pt, 0));
  2263. }
  2264. /* Add parameter to proxy function */
  2265. if (gencomma >= 2) {
  2266. Printf(function_code, ", ");
  2267. if (is_interface)
  2268. Printf(interface_class_code, ", ");
  2269. }
  2270. gencomma = 2;
  2271. Printf(function_code, "%s %s", param_type, arg);
  2272. if (is_interface)
  2273. Printf(interface_class_code, "%s %s", param_type, arg);
  2274. if (prematureGarbageCollectionPreventionParameter(pt, p)) {
  2275. String *pgcppname = Getattr(p, "tmap:javain:pgcppname");
  2276. if (pgcppname) {
  2277. String *argname = Copy(pgcppname);
  2278. Replaceall(argname, "$javainput", arg);
  2279. Printf(imcall, ", %s", argname);
  2280. Delete(argname);
  2281. } else {
  2282. Printf(imcall, ", %s", arg);
  2283. }
  2284. }
  2285. Delete(arg);
  2286. Delete(param_type);
  2287. }
  2288. p = Getattr(p, "tmap:in:next");
  2289. }
  2290. Printf(imcall, ")");
  2291. Printf(function_code, ")");
  2292. // Transform return type used in JNI function (in intermediary class) to type used in Java wrapper function (in proxy class)
  2293. if ((tm = Swig_typemap_lookup("javaout", n, "", 0))) {
  2294. addThrows(n, "tmap:javaout", n);
  2295. bool is_pre_code = Len(pre_code) > 0;
  2296. bool is_post_code = Len(post_code) > 0;
  2297. if (is_pre_code || is_post_code) {
  2298. Replaceall(tm, "\n ", "\n "); // add extra indentation to code in typemap
  2299. if (is_post_code) {
  2300. Insert(tm, 0, "\n try ");
  2301. Printv(tm, " finally {\n", post_code, "\n }", NIL);
  2302. } else {
  2303. Insert(tm, 0, "\n ");
  2304. }
  2305. if (is_pre_code) {
  2306. Insert(tm, 0, pre_code);
  2307. Insert(tm, 0, "\n");
  2308. }
  2309. Insert(tm, 0, "{");
  2310. Printf(tm, "\n }");
  2311. }
  2312. if (GetFlag(n, "feature:new"))
  2313. Replaceall(tm, "$owner", "true");
  2314. else
  2315. Replaceall(tm, "$owner", "false");
  2316. substituteClassname(t, tm);
  2317. // For director methods: generate code to selectively make a normal polymorphic call or
  2318. // an explicit method call - needed to prevent infinite recursion calls in director methods.
  2319. Node *explicit_n = Getattr(n, "explicitcallnode");
  2320. if (explicit_n) {
  2321. String *ex_overloaded_name = getOverloadedName(explicit_n);
  2322. String *ex_intermediary_function_name = Swig_name_member(getNSpace(), getClassPrefix(), ex_overloaded_name);
  2323. String *ex_imcall = Copy(imcall);
  2324. Replaceall(ex_imcall, "$imfuncname", ex_intermediary_function_name);
  2325. Replaceall(imcall, "$imfuncname", intermediary_function_name);
  2326. String *excode = NewString("");
  2327. if (!Cmp(return_type, "void"))
  2328. Printf(excode, "if (getClass() == %s.class) %s; else %s", proxy_class_name, imcall, ex_imcall);
  2329. else
  2330. Printf(excode, "(getClass() == %s.class) ? %s : %s", proxy_class_name, imcall, ex_imcall);
  2331. Clear(imcall);
  2332. Printv(imcall, excode, NIL);
  2333. Delete(ex_overloaded_name);
  2334. Delete(excode);
  2335. } else {
  2336. Replaceall(imcall, "$imfuncname", intermediary_function_name);
  2337. }
  2338. Replaceall(tm, "$imfuncname", intermediary_function_name);
  2339. Replaceall(tm, "$jnicall", imcall);
  2340. } else {
  2341. Swig_warning(WARN_JAVA_TYPEMAP_JAVAOUT_UNDEF, input_file, line_number, "No javaout typemap defined for %s\n", SwigType_str(t, 0));
  2342. }
  2343. if (is_interface) {
  2344. Printf(interface_class_code, ")");
  2345. generateThrowsClause(n, interface_class_code);
  2346. Printf(interface_class_code, ";\n");
  2347. }
  2348. generateThrowsClause(n, function_code);
  2349. Printf(function_code, " %s\n\n", tm ? tm : empty_string);
  2350. Printv(proxy_class_code, function_code, NIL);
  2351. Delete(pre_code);
  2352. Delete(post_code);
  2353. Delete(function_code);
  2354. Delete(return_type);
  2355. Delete(imcall);
  2356. }
  2357. /* ----------------------------------------------------------------------
  2358. * constructorHandler()
  2359. * ---------------------------------------------------------------------- */
  2360. virtual int constructorHandler(Node *n) {
  2361. ParmList *l = Getattr(n, "parms");
  2362. String *tm;
  2363. Parm *p;
  2364. int i;
  2365. String *function_code = NewString("");
  2366. String *helper_code = NewString(""); // Holds code for the constructor helper method generated only when the javain typemap has code in the pre or post attributes
  2367. String *helper_args = NewString("");
  2368. String *pre_code = NewString("");
  2369. String *post_code = NewString("");
  2370. String *im_return_type = NewString("");
  2371. bool feature_director = (parentNode(n) && Swig_directorclass(n));
  2372. Language::constructorHandler(n);
  2373. // Wrappers not wanted for some methods where the parameters cannot be overloaded in Java
  2374. if (Getattr(n, "overload:ignore"))
  2375. return SWIG_OK;
  2376. if (proxy_flag) {
  2377. String *overloaded_name = getOverloadedName(n);
  2378. String *mangled_overname = Swig_name_construct(getNSpace(), overloaded_name);
  2379. String *imcall = NewString("");
  2380. const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
  2381. methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
  2382. tm = Getattr(n, "tmap:jtype"); // typemaps were attached earlier to the node
  2383. Printf(im_return_type, "%s", tm);
  2384. // Translate and write javadoc comment if flagged
  2385. if (doxygen && doxygenTranslator->hasDocumentation(n)) {
  2386. String *doxygen_comments = doxygenTranslator->getDocumentation(n, " ");
  2387. if (comment_creation_chatter)
  2388. Printf(function_code, "/* This was generated from constructionhandler() */\n");
  2389. Printv(function_code, Char(doxygen_comments), NIL);
  2390. Delete(doxygen_comments);
  2391. }
  2392. Printf(function_code, " %s %s(", methodmods, proxy_class_name);
  2393. Printf(helper_code, " static private %s SwigConstruct%s(", im_return_type, proxy_class_name);
  2394. Printv(imcall, full_imclass_name, ".", mangled_overname, "(", NIL);
  2395. /* Attach the non-standard typemaps to the parameter list */
  2396. Swig_typemap_attach_parms("in", l, NULL);
  2397. Swig_typemap_attach_parms("jtype", l, NULL);
  2398. Swig_typemap_attach_parms("jstype", l, NULL);
  2399. Swig_typemap_attach_parms("javain", l, NULL);
  2400. emit_mark_varargs(l);
  2401. int gencomma = 0;
  2402. /* Output each parameter */
  2403. for (i = 0, p = l; p; i++) {
  2404. /* Ignored varargs */
  2405. if (checkAttribute(p, "varargs:ignore", "1")) {
  2406. p = nextSibling(p);
  2407. continue;
  2408. }
  2409. /* Ignored parameters */
  2410. if (checkAttribute(p, "tmap:in:numinputs", "0")) {
  2411. p = Getattr(p, "tmap:in:next");
  2412. continue;
  2413. }
  2414. SwigType *pt = Getattr(p, "type");
  2415. String *param_type = NewString("");
  2416. /* Get the Java parameter type */
  2417. if ((tm = Getattr(p, "tmap:jstype"))) {
  2418. substituteClassname(pt, tm);
  2419. Printf(param_type, "%s", tm);
  2420. } else {
  2421. Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(pt, 0));
  2422. }
  2423. if (gencomma)
  2424. Printf(imcall, ", ");
  2425. String *arg = makeParameterName(n, p, i, false);
  2426. // Use typemaps to transform type used in Java wrapper function (in proxy class) to type used in JNI function (in intermediary class)
  2427. if ((tm = Getattr(p, "tmap:javain"))) {
  2428. addThrows(n, "tmap:javain", p);
  2429. substituteClassname(pt, tm);
  2430. Replaceall(tm, "$javainput", arg);
  2431. String *pre = Getattr(p, "tmap:javain:pre");
  2432. if (pre) {
  2433. substituteClassname(pt, pre);
  2434. Replaceall(pre, "$javainput", arg);
  2435. if (Len(pre_code) > 0)
  2436. Printf(pre_code, "\n");
  2437. Printv(pre_code, pre, NIL);
  2438. }
  2439. String *post = Getattr(p, "tmap:javain:post");
  2440. if (post) {
  2441. substituteClassname(pt, post);
  2442. Replaceall(post, "$javainput", arg);
  2443. if (Len(post_code) > 0)
  2444. Printf(post_code, "\n");
  2445. Printv(post_code, post, NIL);
  2446. }
  2447. Printv(imcall, tm, NIL);
  2448. } else {
  2449. Swig_warning(WARN_JAVA_TYPEMAP_JAVAIN_UNDEF, input_file, line_number, "No javain typemap defined for %s\n", SwigType_str(pt, 0));
  2450. }
  2451. /* Add parameter to proxy function */
  2452. if (gencomma) {
  2453. Printf(function_code, ", ");
  2454. Printf(helper_code, ", ");
  2455. Printf(helper_args, ", ");
  2456. }
  2457. Printf(function_code, "%s %s", param_type, arg);
  2458. Printf(helper_code, "%s %s", param_type, arg);
  2459. Printf(helper_args, "%s", arg);
  2460. ++gencomma;
  2461. if (prematureGarbageCollectionPreventionParameter(pt, p)) {
  2462. String *pgcppname = Getattr(p, "tmap:javain:pgcppname");
  2463. if (pgcppname) {
  2464. String *argname = Copy(pgcppname);
  2465. Replaceall(argname, "$javainput", arg);
  2466. Printf(imcall, ", %s", argname);
  2467. Delete(argname);
  2468. } else {
  2469. Printf(imcall, ", %s", arg);
  2470. }
  2471. }
  2472. Delete(arg);
  2473. Delete(param_type);
  2474. p = Getattr(p, "tmap:in:next");
  2475. }
  2476. Printf(imcall, ")");
  2477. Printf(function_code, ")");
  2478. Printf(helper_code, ")");
  2479. generateThrowsClause(n, function_code);
  2480. /* Insert the javaconstruct typemap, doing the replacement for $directorconnect, as needed */
  2481. Hash *attributes = NewHash();
  2482. String *typemap_lookup_type = Getattr(getCurrentClass(), "classtypeobj");
  2483. String *construct_tm = Copy(typemapLookup(n, "javaconstruct", typemap_lookup_type,
  2484. WARN_JAVA_TYPEMAP_JAVACONSTRUCT_UNDEF, attributes));
  2485. if (construct_tm) {
  2486. if (!feature_director) {
  2487. Replaceall(construct_tm, "$directorconnect", "");
  2488. } else {
  2489. String *connect_attr = Getattr(attributes, "tmap:javaconstruct:directorconnect");
  2490. if (connect_attr) {
  2491. Replaceall(construct_tm, "$directorconnect", connect_attr);
  2492. } else {
  2493. Swig_warning(WARN_JAVA_NO_DIRECTORCONNECT_ATTR, input_file, line_number, "\"directorconnect\" attribute missing in %s \"javaconstruct\" typemap.\n",
  2494. Getattr(n, "name"));
  2495. Replaceall(construct_tm, "$directorconnect", "");
  2496. }
  2497. }
  2498. Printv(function_code, " ", construct_tm, "\n", NIL);
  2499. }
  2500. bool is_pre_code = Len(pre_code) > 0;
  2501. bool is_post_code = Len(post_code) > 0;
  2502. if (is_pre_code || is_post_code) {
  2503. generateThrowsClause(n, helper_code);
  2504. Printf(helper_code, " {\n");
  2505. if (is_pre_code) {
  2506. Printv(helper_code, pre_code, "\n", NIL);
  2507. }
  2508. if (is_post_code) {
  2509. Printf(helper_code, " try {\n");
  2510. Printv(helper_code, " return ", imcall, ";\n", NIL);
  2511. Printv(helper_code, " } finally {\n", post_code, "\n }", NIL);
  2512. } else {
  2513. Printv(helper_code, " return ", imcall, ";", NIL);
  2514. }
  2515. Printf(helper_code, "\n }\n");
  2516. String *helper_name = NewStringf("%s.SwigConstruct%s(%s)", proxy_class_name, proxy_class_name, helper_args);
  2517. Printv(proxy_class_code, helper_code, "\n", NIL);
  2518. Replaceall(function_code, "$imcall", helper_name);
  2519. Delete(helper_name);
  2520. } else {
  2521. Replaceall(function_code, "$imcall", imcall);
  2522. }
  2523. Printv(proxy_class_code, function_code, "\n", NIL);
  2524. Delete(helper_args);
  2525. Delete(im_return_type);
  2526. Delete(pre_code);
  2527. Delete(post_code);
  2528. Delete(construct_tm);
  2529. Delete(attributes);
  2530. Delete(overloaded_name);
  2531. Delete(imcall);
  2532. }
  2533. return SWIG_OK;
  2534. }
  2535. /* ----------------------------------------------------------------------
  2536. * destructorHandler()
  2537. * ---------------------------------------------------------------------- */
  2538. virtual int destructorHandler(Node *n) {
  2539. Language::destructorHandler(n);
  2540. String *symname = Getattr(n, "sym:name");
  2541. if (proxy_flag) {
  2542. Printv(destructor_call, full_imclass_name, ".", Swig_name_destroy(getNSpace(), symname), "(swigCPtr)", NIL);
  2543. generateThrowsClause(n, destructor_throws_clause);
  2544. const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
  2545. if (methodmods)
  2546. Setattr(getCurrentClass(), "destructmethodmodifiers", methodmods);
  2547. }
  2548. return SWIG_OK;
  2549. }
  2550. /* ----------------------------------------------------------------------
  2551. * membervariableHandler()
  2552. * ---------------------------------------------------------------------- */
  2553. virtual int membervariableHandler(Node *n) {
  2554. variable_name = Getattr(n, "sym:name");
  2555. wrapping_member_flag = true;
  2556. variable_wrapper_flag = true;
  2557. Language::membervariableHandler(n);
  2558. wrapping_member_flag = false;
  2559. variable_wrapper_flag = false;
  2560. return SWIG_OK;
  2561. }
  2562. /* ----------------------------------------------------------------------
  2563. * staticmembervariableHandler()
  2564. * ---------------------------------------------------------------------- */
  2565. virtual int staticmembervariableHandler(Node *n) {
  2566. variable_name = Getattr(n, "sym:name");
  2567. wrapping_member_flag = true;
  2568. static_flag = true;
  2569. Language::staticmembervariableHandler(n);
  2570. wrapping_member_flag = false;
  2571. static_flag = false;
  2572. return SWIG_OK;
  2573. }
  2574. /* ----------------------------------------------------------------------
  2575. * memberconstantHandler()
  2576. * ---------------------------------------------------------------------- */
  2577. virtual int memberconstantHandler(Node *n) {
  2578. variable_name = Getattr(n, "sym:name");
  2579. wrapping_member_flag = true;
  2580. Language::memberconstantHandler(n);
  2581. wrapping_member_flag = false;
  2582. return SWIG_OK;
  2583. }
  2584. /* -----------------------------------------------------------------------------
  2585. * getOverloadedName()
  2586. * ----------------------------------------------------------------------------- */
  2587. String *getOverloadedName(Node *n) {
  2588. /* Although JNI functions are designed to handle overloaded Java functions,
  2589. * a Java long is used for all classes in the SWIG intermediary class.
  2590. * The intermediary class methods are thus mangled when overloaded to give
  2591. * a unique name. */
  2592. String *overloaded_name = NewStringf("%s", Getattr(n, "sym:name"));
  2593. if (Getattr(n, "sym:overloaded")) {
  2594. Printv(overloaded_name, Getattr(n, "sym:overname"), NIL);
  2595. }
  2596. return overloaded_name;
  2597. }
  2598. /* -----------------------------------------------------------------------------
  2599. * moduleClassFunctionHandler()
  2600. * ----------------------------------------------------------------------------- */
  2601. void moduleClassFunctionHandler(Node *n) {
  2602. SwigType *t = Getattr(n, "type");
  2603. ParmList *l = Getattr(n, "parms");
  2604. String *tm;
  2605. Parm *p;
  2606. int i;
  2607. String *imcall = NewString("");
  2608. String *return_type = NewString("");
  2609. String *function_code = NewString("");
  2610. int num_arguments = 0;
  2611. String *overloaded_name = getOverloadedName(n);
  2612. String *func_name = NULL;
  2613. bool setter_flag = false;
  2614. String *pre_code = NewString("");
  2615. String *post_code = NewString("");
  2616. // Translate and write javadoc comment if flagged
  2617. if (doxygen && doxygenTranslator->hasDocumentation(n)) {
  2618. String *doxygen_comments = doxygenTranslator->getDocumentation(n, " ");
  2619. if (comment_creation_chatter)
  2620. Printf(function_code, "/* This was generated from moduleClassFunctionHandler() */\n");
  2621. Printv(function_code, doxygen_comments, NIL);
  2622. Delete(doxygen_comments);
  2623. }
  2624. if (l) {
  2625. if (SwigType_type(Getattr(l, "type")) == T_VOID) {
  2626. l = nextSibling(l);
  2627. }
  2628. }
  2629. /* Attach the non-standard typemaps to the parameter list */
  2630. Swig_typemap_attach_parms("jstype", l, NULL);
  2631. Swig_typemap_attach_parms("javain", l, NULL);
  2632. /* Get return types */
  2633. if ((tm = Swig_typemap_lookup("jstype", n, "", 0))) {
  2634. substituteClassname(t, tm);
  2635. Printf(return_type, "%s", tm);
  2636. } else {
  2637. Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(t, 0));
  2638. }
  2639. /* Change function name for global variables */
  2640. if (proxy_flag && global_variable_flag) {
  2641. // Capitalize the first letter in the variable to create a JavaBean type getter/setter function name
  2642. func_name = NewString("");
  2643. setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(getNSpace(), variable_name)) == 0);
  2644. if (setter_flag)
  2645. Printf(func_name, "set");
  2646. else
  2647. Printf(func_name, "get");
  2648. Putc(toupper((int) *Char(variable_name)), func_name);
  2649. Printf(func_name, "%s", Char(variable_name) + 1);
  2650. } else {
  2651. func_name = Copy(Getattr(n, "sym:name"));
  2652. }
  2653. /* Start generating the function */
  2654. const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
  2655. methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
  2656. Printf(function_code, " %s static %s %s(", methodmods, return_type, func_name);
  2657. Printv(imcall, imclass_name, ".", overloaded_name, "(", NIL);
  2658. /* Get number of required and total arguments */
  2659. num_arguments = emit_num_arguments(l);
  2660. bool global_or_member_variable = global_variable_flag || (wrapping_member_flag && !enum_constant_flag);
  2661. int gencomma = 0;
  2662. /* Output each parameter */
  2663. for (i = 0, p = l; i < num_arguments; i++) {
  2664. /* Ignored parameters */
  2665. while (checkAttribute(p, "tmap:in:numinputs", "0")) {
  2666. p = Getattr(p, "tmap:in:next");
  2667. }
  2668. SwigType *pt = Getattr(p, "type");
  2669. String *param_type = NewString("");
  2670. /* Get the Java parameter type */
  2671. if ((tm = Getattr(p, "tmap:jstype"))) {
  2672. substituteClassname(pt, tm);
  2673. Printf(param_type, "%s", tm);
  2674. } else {
  2675. Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(pt, 0));
  2676. }
  2677. if (gencomma)
  2678. Printf(imcall, ", ");
  2679. String *arg = makeParameterName(n, p, i, global_or_member_variable);
  2680. // Use typemaps to transform type used in Java wrapper function (in proxy class) to type used in JNI function (in intermediary class)
  2681. if ((tm = Getattr(p, "tmap:javain"))) {
  2682. addThrows(n, "tmap:javain", p);
  2683. substituteClassname(pt, tm);
  2684. Replaceall(tm, "$javainput", arg);
  2685. String *pre = Getattr(p, "tmap:javain:pre");
  2686. if (pre) {
  2687. substituteClassname(pt, pre);
  2688. Replaceall(pre, "$javainput", arg);
  2689. if (Len(pre_code) > 0)
  2690. Printf(pre_code, "\n");
  2691. Printv(pre_code, pre, NIL);
  2692. }
  2693. String *post = Getattr(p, "tmap:javain:post");
  2694. if (post) {
  2695. substituteClassname(pt, post);
  2696. Replaceall(post, "$javainput", arg);
  2697. if (Len(post_code) > 0)
  2698. Printf(post_code, "\n");
  2699. Printv(post_code, post, NIL);
  2700. }
  2701. Printv(imcall, tm, NIL);
  2702. } else {
  2703. Swig_warning(WARN_JAVA_TYPEMAP_JAVAIN_UNDEF, input_file, line_number, "No javain typemap defined for %s\n", SwigType_str(pt, 0));
  2704. }
  2705. /* Add parameter to module class function */
  2706. if (gencomma >= 2)
  2707. Printf(function_code, ", ");
  2708. gencomma = 2;
  2709. Printf(function_code, "%s %s", param_type, arg);
  2710. if (prematureGarbageCollectionPreventionParameter(pt, p)) {
  2711. String *pgcppname = Getattr(p, "tmap:javain:pgcppname");
  2712. if (pgcppname) {
  2713. String *argname = Copy(pgcppname);
  2714. Replaceall(argname, "$javainput", arg);
  2715. Printf(imcall, ", %s", argname);
  2716. Delete(argname);
  2717. } else {
  2718. Printf(imcall, ", %s", arg);
  2719. }
  2720. }
  2721. p = Getattr(p, "tmap:in:next");
  2722. Delete(arg);
  2723. Delete(param_type);
  2724. }
  2725. Printf(imcall, ")");
  2726. Printf(function_code, ")");
  2727. // Transform return type used in JNI function (in intermediary class) to type used in Java wrapper function (in module class)
  2728. if ((tm = Swig_typemap_lookup("javaout", n, "", 0))) {
  2729. addThrows(n, "tmap:javaout", n);
  2730. bool is_pre_code = Len(pre_code) > 0;
  2731. bool is_post_code = Len(post_code) > 0;
  2732. if (is_pre_code || is_post_code) {
  2733. Replaceall(tm, "\n ", "\n "); // add extra indentation to code in typemap
  2734. if (is_post_code) {
  2735. Insert(tm, 0, "\n try ");
  2736. Printv(tm, " finally {\n", post_code, "\n }", NIL);
  2737. } else {
  2738. Insert(tm, 0, "\n ");
  2739. }
  2740. if (is_pre_code) {
  2741. Insert(tm, 0, pre_code);
  2742. Insert(tm, 0, "\n");
  2743. }
  2744. Insert(tm, 0, "{");
  2745. Printf(tm, "\n }");
  2746. }
  2747. if (GetFlag(n, "feature:new"))
  2748. Replaceall(tm, "$owner", "true");
  2749. else
  2750. Replaceall(tm, "$owner", "false");
  2751. substituteClassname(t, tm);
  2752. Replaceall(tm, "$imfuncname", overloaded_name);
  2753. Replaceall(tm, "$jnicall", imcall);
  2754. } else {
  2755. Swig_warning(WARN_JAVA_TYPEMAP_JAVAOUT_UNDEF, input_file, line_number, "No javaout typemap defined for %s\n", SwigType_str(t, 0));
  2756. }
  2757. generateThrowsClause(n, function_code);
  2758. Printf(function_code, " %s\n\n", tm ? tm : empty_string);
  2759. Printv(module_class_code, function_code, NIL);
  2760. Delete(pre_code);
  2761. Delete(post_code);
  2762. Delete(function_code);
  2763. Delete(return_type);
  2764. Delete(imcall);
  2765. Delete(func_name);
  2766. }
  2767. /*----------------------------------------------------------------------
  2768. * replaceSpecialVariables()
  2769. *--------------------------------------------------------------------*/
  2770. virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm) {
  2771. (void)method;
  2772. SwigType *type = Getattr(parm, "type");
  2773. substituteClassname(type, tm);
  2774. }
  2775. /*----------------------------------------------------------------------
  2776. * decodeEnumFeature()
  2777. * Decode the possible enum features, which are one of:
  2778. * %javaenum(simple)
  2779. * %javaenum(typeunsafe) - default
  2780. * %javaenum(typesafe)
  2781. * %javaenum(proper)
  2782. *--------------------------------------------------------------------*/
  2783. EnumFeature decodeEnumFeature(Node *n) {
  2784. EnumFeature enum_feature = TypeunsafeEnum;
  2785. String *feature = Getattr(n, "feature:java:enum");
  2786. if (feature) {
  2787. if (Cmp(feature, "simple") == 0)
  2788. enum_feature = SimpleEnum;
  2789. else if (Cmp(feature, "typesafe") == 0)
  2790. enum_feature = TypesafeEnum;
  2791. else if (Cmp(feature, "proper") == 0)
  2792. enum_feature = ProperEnum;
  2793. }
  2794. return enum_feature;
  2795. }
  2796. /* -----------------------------------------------------------------------
  2797. * enumValue()
  2798. * This method will return a string with an enum value to use in Java generated
  2799. * code. If the %javaconst feature is not used, the string will contain the intermediary
  2800. * class call to obtain the enum value. The intermediary class and JNI methods to obtain
  2801. * the enum value will be generated. Otherwise the C/C++ enum value will be used if there
  2802. * is one and hopefully it will compile as Java code - e.g. 20 as in: enum E{e=20};
  2803. * The %javaconstvalue feature overrides all other ways to generate the constant value.
  2804. * The caller must delete memory allocated for the returned string.
  2805. * ------------------------------------------------------------------------ */
  2806. String *enumValue(Node *n) {
  2807. String *symname = Getattr(n, "sym:name");
  2808. // Check for the %javaconstvalue feature
  2809. String *value = Getattr(n, "feature:java:constvalue");
  2810. if (!value) {
  2811. // The %javaconst feature determines how the constant value is obtained
  2812. int const_feature_flag = GetFlag(n, "feature:java:const");
  2813. if (const_feature_flag) {
  2814. // Use the C syntax to make a true Java constant and hope that it compiles as Java code
  2815. value = Getattr(n, "enumvalue") ? Copy(Getattr(n, "enumvalue")) : Copy(Getattr(n, "enumvalueex"));
  2816. } else {
  2817. String *newsymname = 0;
  2818. if (!getCurrentClass() || !proxy_flag) {
  2819. String *enumClassPrefix = getEnumClassPrefix();
  2820. if (enumClassPrefix) {
  2821. // A global scoped enum
  2822. newsymname = Swig_name_member(0, enumClassPrefix, symname);
  2823. symname = newsymname;
  2824. }
  2825. }
  2826. // Get the enumvalue from a JNI call
  2827. if (!getCurrentClass() || !cparse_cplusplus || !proxy_flag) {
  2828. // Strange hack to change the name
  2829. Setattr(n, "name", Getattr(n, "value")); /* for wrapping of enums in a namespace when emit_action is used */
  2830. constantWrapper(n);
  2831. value = NewStringf("%s.%s()", full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname));
  2832. } else {
  2833. memberconstantHandler(n);
  2834. value = NewStringf("%s.%s()", full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), Swig_name_member(0, getEnumClassPrefix(), symname)));
  2835. }
  2836. Delete(newsymname);
  2837. }
  2838. }
  2839. return value;
  2840. }
  2841. /* -----------------------------------------------------------------------------
  2842. * getEnumName()
  2843. *
  2844. * If jnidescriptor is set, inner class names are separated with '$' otherwise a '.'
  2845. * and the package is also not added to the name.
  2846. * ----------------------------------------------------------------------------- */
  2847. String *getEnumName(SwigType *t, bool jnidescriptor) {
  2848. Node *enumname = NULL;
  2849. Node *n = enumLookup(t);
  2850. if (n) {
  2851. enumname = Getattr(n, "enumname");
  2852. if (!enumname || jnidescriptor) {
  2853. String *symname = Getattr(n, "sym:name");
  2854. if (symname) {
  2855. // Add in class scope when referencing enum if not a global enum
  2856. String *scopename_prefix = Swig_scopename_prefix(Getattr(n, "name"));
  2857. String *proxyname = 0;
  2858. if (scopename_prefix) {
  2859. proxyname = getProxyName(scopename_prefix, jnidescriptor);
  2860. }
  2861. if (proxyname) {
  2862. const char *class_separator = jnidescriptor ? "$" : ".";
  2863. enumname = NewStringf("%s%s%s", proxyname, class_separator, symname);
  2864. } else {
  2865. // global enum or enum in a namespace
  2866. String *nspace = Getattr(n, "sym:nspace");
  2867. if (nspace) {
  2868. if (package && !jnidescriptor)
  2869. enumname = NewStringf("%s.%s.%s", package, nspace, symname);
  2870. else
  2871. enumname = NewStringf("%s.%s", nspace, symname);
  2872. } else {
  2873. enumname = Copy(symname);
  2874. }
  2875. }
  2876. if (!jnidescriptor) {
  2877. Setattr(n, "enumname", enumname); // Cache it
  2878. Delete(enumname);
  2879. }
  2880. Delete(scopename_prefix);
  2881. }
  2882. }
  2883. }
  2884. return enumname;
  2885. }
  2886. /* -----------------------------------------------------------------------------
  2887. * substituteClassname()
  2888. *
  2889. * Substitute the special variable $javaclassname with the proxy class name for classes/structs/unions
  2890. * that SWIG knows about. Also substitutes enums with enum name.
  2891. * Otherwise use the $descriptor name for the Java class name. Note that the $&javaclassname substitution
  2892. * is the same as a $&descriptor substitution, ie one pointer added to descriptor name.
  2893. * Note that the path separator is a '.' unless jnidescriptor is set.
  2894. * Inputs:
  2895. * pt - parameter type
  2896. * tm - typemap contents that might contain the special variable to be replaced
  2897. * jnidescriptor - if set, inner class names are separated with '$' otherwise a '/' is used for the path separator
  2898. * Outputs:
  2899. * tm - typemap contents complete with the special variable substitution
  2900. * Return:
  2901. * substitution_performed - flag indicating if a substitution was performed
  2902. * ----------------------------------------------------------------------------- */
  2903. bool substituteClassname(SwigType *pt, String *tm, bool jnidescriptor = false) {
  2904. bool substitution_performed = false;
  2905. SwigType *type = Copy(SwigType_typedef_resolve_all(pt));
  2906. SwigType *strippedtype = SwigType_strip_qualifiers(type);
  2907. if (Strstr(tm, "$javaclassname")) {
  2908. SwigType *classnametype = Copy(strippedtype);
  2909. substituteClassnameSpecialVariable(classnametype, tm, "$javaclassname", jnidescriptor);
  2910. substitution_performed = true;
  2911. Delete(classnametype);
  2912. }
  2913. if (Strstr(tm, "$*javaclassname")) {
  2914. SwigType *classnametype = Copy(strippedtype);
  2915. Delete(SwigType_pop(classnametype));
  2916. if (Len(classnametype) > 0) {
  2917. substituteClassnameSpecialVariable(classnametype, tm, "$*javaclassname", jnidescriptor);
  2918. substitution_performed = true;
  2919. }
  2920. Delete(classnametype);
  2921. }
  2922. if (Strstr(tm, "$&javaclassname")) {
  2923. SwigType *classnametype = Copy(strippedtype);
  2924. SwigType_add_pointer(classnametype);
  2925. substituteClassnameSpecialVariable(classnametype, tm, "$&javaclassname", jnidescriptor);
  2926. substitution_performed = true;
  2927. Delete(classnametype);
  2928. }
  2929. if (Strstr(tm, "$javainterfacename")) {
  2930. SwigType *interfacenametype = Copy(strippedtype);
  2931. substituteInterfacenameSpecialVariable(interfacenametype, tm, "$javainterfacename", jnidescriptor, true);
  2932. substitution_performed = true;
  2933. Delete(interfacenametype);
  2934. }
  2935. if (Strstr(tm, "$*javainterfacename")) {
  2936. SwigType *interfacenametype = Copy(strippedtype);
  2937. Delete(SwigType_pop(interfacenametype));
  2938. if (Len(interfacenametype) > 0) {
  2939. substituteInterfacenameSpecialVariable(interfacenametype, tm, "$*javainterfacename", jnidescriptor, true);
  2940. substitution_performed = true;
  2941. }
  2942. Delete(interfacenametype);
  2943. }
  2944. if (Strstr(tm, "$&javainterfacename")) {
  2945. SwigType *interfacenametype = Copy(strippedtype);
  2946. SwigType_add_pointer(interfacenametype);
  2947. substituteInterfacenameSpecialVariable(interfacenametype, tm, "$&javainterfacename", jnidescriptor, true);
  2948. substitution_performed = true;
  2949. Delete(interfacenametype);
  2950. }
  2951. if (Strstr(tm, "$interfacename")) {
  2952. SwigType *interfacenametype = Copy(strippedtype);
  2953. substituteInterfacenameSpecialVariable(interfacenametype, tm, "$interfacename", jnidescriptor, false);
  2954. substitution_performed = true;
  2955. Delete(interfacenametype);
  2956. }
  2957. if (Strstr(tm, "$*interfacename")) {
  2958. SwigType *interfacenametype = Copy(strippedtype);
  2959. Delete(SwigType_pop(interfacenametype));
  2960. if (Len(interfacenametype) > 0) {
  2961. substituteInterfacenameSpecialVariable(interfacenametype, tm, "$*interfacename", jnidescriptor, false);
  2962. substitution_performed = true;
  2963. }
  2964. Delete(interfacenametype);
  2965. }
  2966. if (Strstr(tm, "$&interfacename")) {
  2967. SwigType *interfacenametype = Copy(strippedtype);
  2968. SwigType_add_pointer(interfacenametype);
  2969. substituteInterfacenameSpecialVariable(interfacenametype, tm, "$&interfacename", jnidescriptor, false);
  2970. substitution_performed = true;
  2971. Delete(interfacenametype);
  2972. }
  2973. Delete(strippedtype);
  2974. Delete(type);
  2975. return substitution_performed;
  2976. }
  2977. /* -----------------------------------------------------------------------------
  2978. * substituteClassnameSpecialVariable()
  2979. * ----------------------------------------------------------------------------- */
  2980. void substituteClassnameSpecialVariable(SwigType *classnametype, String *tm, const char *classnamespecialvariable, bool jnidescriptor) {
  2981. String *replacementname;
  2982. if (SwigType_isenum(classnametype)) {
  2983. String *enumname = getEnumName(classnametype, jnidescriptor);
  2984. if (enumname) {
  2985. replacementname = Copy(enumname);
  2986. } else {
  2987. bool anonymous_enum = (Cmp(classnametype, "enum ") == 0);
  2988. if (anonymous_enum) {
  2989. replacementname = NewString("int");
  2990. } else {
  2991. // An unknown enum - one that has not been parsed (neither a C enum forward reference nor a definition) or an ignored enum
  2992. replacementname = NewStringf("SWIGTYPE%s", SwigType_manglestr(classnametype));
  2993. Replace(replacementname, "enum ", "", DOH_REPLACE_ANY);
  2994. Setattr(swig_types_hash, replacementname, classnametype);
  2995. }
  2996. }
  2997. } else {
  2998. String *classname = getProxyName(classnametype, jnidescriptor); // getProxyName() works for pointers to classes too
  2999. if (classname) {
  3000. replacementname = Copy(classname);
  3001. } else {
  3002. // use $descriptor if SWIG does not know anything about this type. Note that any typedefs are resolved.
  3003. replacementname = NewStringf("SWIGTYPE%s", SwigType_manglestr(classnametype));
  3004. // Add to hash table so that the type wrapper classes can be created later
  3005. Setattr(swig_types_hash, replacementname, classnametype);
  3006. }
  3007. }
  3008. if (jnidescriptor)
  3009. Replaceall(replacementname,".","/");
  3010. Replaceall(tm, classnamespecialvariable, replacementname);
  3011. Delete(replacementname);
  3012. }
  3013. /* -----------------------------------------------------------------------------
  3014. * substituteInterfacenameSpecialVariable()
  3015. * ----------------------------------------------------------------------------- */
  3016. void substituteInterfacenameSpecialVariable(SwigType *interfacenametype, String *tm, const char *interfacenamespecialvariable, bool jnidescriptor, bool qualified) {
  3017. String *interfacename = getInterfaceName(interfacenametype/*, jnidescriptor*/, qualified);
  3018. if (interfacename) {
  3019. String *replacementname = Copy(interfacename);
  3020. if (jnidescriptor)
  3021. Replaceall(replacementname,".","/");
  3022. Replaceall(tm, interfacenamespecialvariable, replacementname);
  3023. Delete(replacementname);
  3024. }
  3025. }
  3026. /* -----------------------------------------------------------------------------
  3027. * emitTypeWrapperClass()
  3028. * ----------------------------------------------------------------------------- */
  3029. void emitTypeWrapperClass(String *classname, SwigType *type) {
  3030. Node *n = NewHash();
  3031. Setfile(n, input_file);
  3032. Setline(n, line_number);
  3033. String *swigtype = NewString("");
  3034. String *filen = NewStringf("%s%s.java", SWIG_output_directory(), classname);
  3035. File *f_swigtype = NewFile(filen, "w", SWIG_output_files());
  3036. if (!f_swigtype) {
  3037. FileErrorDisplay(filen);
  3038. Exit(EXIT_FAILURE);
  3039. }
  3040. Append(filenames_list, Copy(filen));
  3041. Delete(filen);
  3042. filen = NULL;
  3043. // Start writing out the type wrapper class file
  3044. emitBanner(f_swigtype);
  3045. if (package)
  3046. Printf(f_swigtype, "package %s;\n", package);
  3047. // Pure Java baseclass and interfaces
  3048. const String *pure_baseclass = typemapLookup(n, "javabase", type, WARN_NONE);
  3049. const String *pure_interfaces = typemapLookup(n, "javainterfaces", type, WARN_NONE);
  3050. // Emit the class
  3051. Printv(swigtype, typemapLookup(n, "javaimports", type, WARN_NONE), // Import statements
  3052. "\n", typemapLookup(n, "javaclassmodifiers", type, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers
  3053. " $javaclassname", // Class name and bases
  3054. *Char(pure_baseclass) ? " extends " : "", pure_baseclass, *Char(pure_interfaces) ? // Interfaces
  3055. " implements " : "", pure_interfaces, " {", typemapLookup(n, "javabody", type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF), // main body of class
  3056. typemapLookup(n, "javacode", type, WARN_NONE), // extra Java code
  3057. "}\n", "\n", NIL);
  3058. Replaceall(swigtype, "$javaclassname", classname);
  3059. Replaceall(swigtype, "$module", module_class_name);
  3060. Replaceall(swigtype, "$imclassname", imclass_name);
  3061. // For unknown enums
  3062. Replaceall(swigtype, "$static ", "");
  3063. Replaceall(swigtype, "$enumvalues", "");
  3064. Printv(f_swigtype, swigtype, NIL);
  3065. Delete(f_swigtype);
  3066. Delete(swigtype);
  3067. Delete(n);
  3068. }
  3069. /* -----------------------------------------------------------------------------
  3070. * typemapLookup()
  3071. * n - for input only and must contain info for Getfile(n) and Getline(n) to work
  3072. * tmap_method - typemap method name
  3073. * type - typemap type to lookup
  3074. * warning - warning number to issue if no typemaps found
  3075. * typemap_attributes - the typemap attributes are attached to this node and will
  3076. * also be used for temporary storage if non null
  3077. * return is never NULL, unlike Swig_typemap_lookup()
  3078. * ----------------------------------------------------------------------------- */
  3079. const String *typemapLookup(Node *n, const_String_or_char_ptr tmap_method, SwigType *type, int warning, Node *typemap_attributes = 0) {
  3080. Node *node = !typemap_attributes ? NewHash() : typemap_attributes;
  3081. Setattr(node, "type", type);
  3082. Setfile(node, Getfile(n));
  3083. Setline(node, Getline(n));
  3084. const String *tm = Swig_typemap_lookup(tmap_method, node, "", 0);
  3085. if (!tm) {
  3086. tm = empty_string;
  3087. if (warning != WARN_NONE)
  3088. Swig_warning(warning, Getfile(n), Getline(n), "No %s typemap defined for %s\n", tmap_method, SwigType_str(type, 0));
  3089. }
  3090. if (!typemap_attributes)
  3091. Delete(node);
  3092. return tm;
  3093. }
  3094. /* -----------------------------------------------------------------------------
  3095. * addThrows()
  3096. *
  3097. * Adds exception classes to a throws list. The throws list is the list of classes
  3098. * that will form the Java throws clause. Mainly for checked exceptions.
  3099. * ----------------------------------------------------------------------------- */
  3100. void addThrows(Node *n, const String *attribute, Node *parameter) {
  3101. // Get the comma separated exception classes for the throws clause - held in typemap/feature's "throws" attribute
  3102. String *throws_attribute = NewStringf("%s:throws", attribute);
  3103. String *throws = Getattr(parameter, throws_attribute);
  3104. if (throws && Len(throws) > 0) {
  3105. String *throws_list = Getattr(n, "java:throwslist");
  3106. if (!throws_list) {
  3107. throws_list = NewList();
  3108. Setattr(n, "java:throwslist", throws_list);
  3109. }
  3110. // Put the exception classes in the throws clause into a temporary List
  3111. List *temp_classes_list = Split(throws, ',', INT_MAX);
  3112. // Add the exception classes to the node throws list, but don't duplicate if already in list
  3113. if (temp_classes_list && Len(temp_classes_list) > 0) {
  3114. for (Iterator cls = First(temp_classes_list); cls.item; cls = Next(cls)) {
  3115. String *exception_class = NewString(cls.item);
  3116. Replaceall(exception_class, " ", ""); // remove spaces
  3117. Replaceall(exception_class, "\t", ""); // remove tabs
  3118. if (Len(exception_class) > 0) {
  3119. // $javaclassname substitution
  3120. SwigType *pt = Getattr(parameter, "type");
  3121. substituteClassname(pt, exception_class);
  3122. // Don't duplicate the Java exception class in the throws clause
  3123. bool found_flag = false;
  3124. for (Iterator item = First(throws_list); item.item; item = Next(item)) {
  3125. if (Strcmp(item.item, exception_class) == 0)
  3126. found_flag = true;
  3127. }
  3128. if (!found_flag)
  3129. Append(throws_list, exception_class);
  3130. }
  3131. Delete(exception_class);
  3132. }
  3133. }
  3134. Delete(temp_classes_list);
  3135. }
  3136. Delete(throws_attribute);
  3137. }
  3138. /* -----------------------------------------------------------------------------
  3139. * generateThrowsClause()
  3140. *
  3141. * Generates throws clause for checked exception
  3142. * ----------------------------------------------------------------------------- */
  3143. void generateThrowsClause(Node *n, String *code) {
  3144. // Add the throws clause into code
  3145. List *throws_list = Getattr(n, "java:throwslist");
  3146. if (throws_list) {
  3147. Iterator cls = First(throws_list);
  3148. Printf(code, " throws %s", cls.item);
  3149. while ((cls = Next(cls)).item)
  3150. Printf(code, ", %s", cls.item);
  3151. }
  3152. }
  3153. /* -----------------------------------------------------------------------------
  3154. * prematureGarbageCollectionPreventionParameter()
  3155. *
  3156. * Get the proxy class name for use in an additional generated parameter. The
  3157. * additional parameter is added to a native method call purely to prevent
  3158. * premature garbage collection of proxy classes which pass their C++ class pointer
  3159. * in a Java long to the JNI layer.
  3160. * ----------------------------------------------------------------------------- */
  3161. String *prematureGarbageCollectionPreventionParameter(SwigType *t, Parm *p) {
  3162. String *pgcpp_java_type = 0;
  3163. String *jtype = NewString(Getattr(p, "tmap:jtype"));
  3164. // Strip C comments
  3165. String *stripped_jtype = Swig_strip_c_comments(jtype);
  3166. if (stripped_jtype) {
  3167. Delete(jtype);
  3168. jtype = stripped_jtype;
  3169. }
  3170. // Remove whitespace
  3171. Replaceall(jtype, " ", "");
  3172. Replaceall(jtype, "\t", "");
  3173. if (Cmp(jtype, "long") == 0) {
  3174. if (proxy_flag) {
  3175. if (!GetFlag(p, "tmap:jtype:nopgcpp") && !nopgcpp_flag) {
  3176. String *interface_name = getInterfaceName(t, true);
  3177. pgcpp_java_type = interface_name ? interface_name : getProxyName(t);
  3178. if (!pgcpp_java_type) {
  3179. // Look for proxy class parameters passed to C++ layer using non-default typemaps, ie not one of above types
  3180. String *jstype = NewString(Getattr(p, "tmap:jstype"));
  3181. if (jstype) {
  3182. Hash *classes = getClassHash();
  3183. if (classes) {
  3184. // Strip C comments
  3185. String *stripped_jstype = Swig_strip_c_comments(jstype);
  3186. if (stripped_jstype) {
  3187. Delete(jstype);
  3188. jstype = stripped_jstype;
  3189. }
  3190. // Remove whitespace
  3191. Replaceall(jstype, " ", "");
  3192. Replaceall(jstype, "\t", "");
  3193. Iterator ki;
  3194. for (ki = First(classes); ki.key; ki = Next(ki)) {
  3195. Node *cls = ki.item;
  3196. if (cls && !Getattr(cls, "feature:ignore")) {
  3197. String *symname = Getattr(cls, "sym:name");
  3198. if (symname && Strcmp(symname, jstype) == 0) {
  3199. pgcpp_java_type = symname;
  3200. }
  3201. }
  3202. }
  3203. }
  3204. }
  3205. Delete(jstype);
  3206. }
  3207. }
  3208. }
  3209. }
  3210. Delete(jtype);
  3211. return pgcpp_java_type;
  3212. }
  3213. /* -----------------------------------------------------------------------------
  3214. * outputDirectory()
  3215. *
  3216. * Return the directory to use for generating Java classes/enums and create the
  3217. * subdirectory (does not create if language specific outdir does not exist).
  3218. * ----------------------------------------------------------------------------- */
  3219. String *outputDirectory(String *nspace) {
  3220. String *output_directory = Copy(SWIG_output_directory());
  3221. if (nspace) {
  3222. String *nspace_subdirectory = Copy(nspace);
  3223. Replaceall(nspace_subdirectory, ".", SWIG_FILE_DELIMITER);
  3224. String *newdir_error = Swig_new_subdirectory(output_directory, nspace_subdirectory);
  3225. if (newdir_error) {
  3226. Printf(stderr, "%s\n", newdir_error);
  3227. Delete(newdir_error);
  3228. Exit(EXIT_FAILURE);
  3229. }
  3230. Printv(output_directory, nspace_subdirectory, SWIG_FILE_DELIMITER, 0);
  3231. Delete(nspace_subdirectory);
  3232. }
  3233. return output_directory;
  3234. }
  3235. /*----------------------------------------------------------------------
  3236. * Start of director methods
  3237. *--------------------------------------------------------------------*/
  3238. /*----------------------------------------------------------------------
  3239. * getUpcallJNIMethod()
  3240. *--------------------------------------------------------------------*/
  3241. String *getUpcallJNIMethod(String *descrip) {
  3242. static struct {
  3243. char code;
  3244. const char *method;
  3245. } upcall_methods[] = {
  3246. {
  3247. 'B', "CallStaticByteMethod"}, {
  3248. 'C', "CallStaticCharMethod"}, {
  3249. 'D', "CallStaticDoubleMethod"}, {
  3250. 'F', "CallStaticFloatMethod"}, {
  3251. 'I', "CallStaticIntMethod"}, {
  3252. 'J', "CallStaticLongMethod"}, {
  3253. 'L', "CallStaticObjectMethod"}, {
  3254. 'S', "CallStaticShortMethod"}, {
  3255. 'V', "CallStaticVoidMethod"}, {
  3256. 'Z', "CallStaticBooleanMethod"}, {
  3257. '[', "CallStaticObjectMethod"}
  3258. };
  3259. char code;
  3260. int i;
  3261. code = *Char(descrip);
  3262. for (i = 0; i < (int) (sizeof(upcall_methods) / sizeof(upcall_methods[0])); ++i)
  3263. if (code == upcall_methods[i].code)
  3264. return NewString(upcall_methods[i].method);
  3265. return NULL;
  3266. }
  3267. /*----------------------------------------------------------------------
  3268. * emitDirectorUpcalls()
  3269. *--------------------------------------------------------------------*/
  3270. void emitDirectorUpcalls() {
  3271. if (n_dmethods) {
  3272. Wrapper *w = NewWrapper();
  3273. String *jni_imclass_name = makeValidJniName(imclass_name);
  3274. String *swig_module_init = NewString("swig_module_init");
  3275. String *swig_module_init_jni = makeValidJniName(swig_module_init);
  3276. String *dmethod_data = NewString("");
  3277. int n_methods = 0;
  3278. Iterator udata_iter;
  3279. udata_iter = First(dmethods_seq);
  3280. while (udata_iter.item) {
  3281. UpcallData *udata = udata_iter.item;
  3282. Printf(dmethod_data, " { \"%s\", \"%s\" }", Getattr(udata, "imclass_method"), Getattr(udata, "imclass_fdesc"));
  3283. ++n_methods;
  3284. udata_iter = Next(udata_iter);
  3285. if (udata_iter.item)
  3286. Putc(',', dmethod_data);
  3287. Putc('\n', dmethod_data);
  3288. }
  3289. Printf(f_runtime, "namespace Swig {\n");
  3290. Printf(f_runtime, " namespace {\n");
  3291. Printf(f_runtime, " jclass jclass_%s = NULL;\n", imclass_name);
  3292. Printf(f_runtime, " jmethodID director_method_ids[%d];\n", n_methods);
  3293. Printf(f_runtime, " }\n");
  3294. Printf(f_runtime, "}\n");
  3295. Printf(w->def, "SWIGEXPORT void JNICALL Java_%s%s_%s(JNIEnv *jenv, jclass jcls) {", jnipackage, jni_imclass_name, swig_module_init_jni);
  3296. Printf(w->code, "static struct {\n");
  3297. Printf(w->code, " const char *method;\n");
  3298. Printf(w->code, " const char *signature;\n");
  3299. Printf(w->code, "} methods[%d] = {\n", n_methods);
  3300. Printv(w->code, dmethod_data, NIL);
  3301. Printf(w->code, "};\n");
  3302. Wrapper_add_local(w, "i", "int i");
  3303. Printf(w->code, "Swig::jclass_%s = (jclass) jenv->NewGlobalRef(jcls);\n", imclass_name);
  3304. Printf(w->code, "if (!Swig::jclass_%s) return;\n", imclass_name);
  3305. Printf(w->code, "for (i = 0; i < (int) (sizeof(methods)/sizeof(methods[0])); ++i) {\n");
  3306. Printf(w->code, " Swig::director_method_ids[i] = jenv->GetStaticMethodID(jcls, methods[i].method, methods[i].signature);\n");
  3307. Printf(w->code, " if (!Swig::director_method_ids[i]) return;\n");
  3308. Printf(w->code, "}\n");
  3309. Printf(w->code, "}\n");
  3310. Wrapper_print(w, f_wrappers);
  3311. Delete(dmethod_data);
  3312. Delete(swig_module_init_jni);
  3313. Delete(swig_module_init);
  3314. Delete(jni_imclass_name);
  3315. DelWrapper(w);
  3316. }
  3317. }
  3318. /*----------------------------------------------------------------------
  3319. * emitDirectorExtraMethods()
  3320. *
  3321. * This is where the director connect method is generated.
  3322. *--------------------------------------------------------------------*/
  3323. void emitDirectorExtraMethods(Node *n) {
  3324. if (!Swig_directorclass(n))
  3325. return;
  3326. // Output the director connect method:
  3327. String *jni_imclass_name = makeValidJniName(imclass_name);
  3328. String *norm_name = SwigType_namestr(Getattr(n, "name"));
  3329. String *swig_director_connect = Swig_name_member(getNSpace(), getClassPrefix(), "director_connect");
  3330. String *swig_director_connect_jni = makeValidJniName(swig_director_connect);
  3331. String *smartptr = Getattr(n, "feature:smartptr");
  3332. String *dirClassName = directorClassName(n);
  3333. Wrapper *code_wrap;
  3334. Printf(imclass_class_code, " public final static native void %s(%s obj, long cptr, boolean mem_own, boolean weak_global);\n",
  3335. swig_director_connect, full_proxy_class_name);
  3336. code_wrap = NewWrapper();
  3337. Printf(code_wrap->def,
  3338. "SWIGEXPORT void JNICALL Java_%s%s_%s(JNIEnv *jenv, jclass jcls, jobject jself, jlong objarg, jboolean jswig_mem_own, "
  3339. "jboolean jweak_global) {\n", jnipackage, jni_imclass_name, swig_director_connect_jni);
  3340. if (smartptr) {
  3341. Printf(code_wrap->code, " %s *obj = *((%s **)&objarg);\n", smartptr, smartptr);
  3342. Printf(code_wrap->code, " (void)jcls;\n");
  3343. Printf(code_wrap->code, " // Keep a local instance of the smart pointer around while we are using the raw pointer\n");
  3344. Printf(code_wrap->code, " // Avoids using smart pointer specific API.\n");
  3345. Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj->operator->());\n", dirClassName, dirClassName);
  3346. }
  3347. else {
  3348. Printf(code_wrap->code, " %s *obj = *((%s **)&objarg);\n", norm_name, norm_name);
  3349. Printf(code_wrap->code, " (void)jcls;\n");
  3350. Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj);\n", dirClassName, dirClassName);
  3351. }
  3352. Printf(code_wrap->code, " director->swig_connect_director(jenv, jself, jenv->GetObjectClass(jself), "
  3353. "(jswig_mem_own == JNI_TRUE), (jweak_global == JNI_TRUE));\n");
  3354. Printf(code_wrap->code, "}\n");
  3355. Wrapper_print(code_wrap, f_wrappers);
  3356. DelWrapper(code_wrap);
  3357. Delete(swig_director_connect_jni);
  3358. Delete(swig_director_connect);
  3359. // Output the swigReleaseOwnership, swigTakeOwnership methods:
  3360. String *changeown_method_name = Swig_name_member(getNSpace(), getClassPrefix(), "change_ownership");
  3361. String *changeown_jnimethod_name = makeValidJniName(changeown_method_name);
  3362. Printf(imclass_class_code, " public final static native void %s(%s obj, long cptr, boolean take_or_release);\n", changeown_method_name, full_proxy_class_name);
  3363. code_wrap = NewWrapper();
  3364. Printf(code_wrap->def,
  3365. "SWIGEXPORT void JNICALL Java_%s%s_%s(JNIEnv *jenv, jclass jcls, jobject jself, jlong objarg, jboolean jtake_or_release) {\n",
  3366. jnipackage, jni_imclass_name, changeown_jnimethod_name);
  3367. if (Len(smartptr)) {
  3368. Printf(code_wrap->code, " %s *obj = *((%s **)&objarg);\n", smartptr, smartptr);
  3369. Printf(code_wrap->code, " // Keep a local instance of the smart pointer around while we are using the raw pointer\n");
  3370. Printf(code_wrap->code, " // Avoids using smart pointer specific API.\n");
  3371. Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj->operator->());\n", dirClassName, dirClassName);
  3372. } else {
  3373. Printf(code_wrap->code, " %s *obj = *((%s **)&objarg);\n", norm_name, norm_name);
  3374. Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj);\n", dirClassName, dirClassName);
  3375. }
  3376. Printf(code_wrap->code, " (void)jcls;\n");
  3377. Printf(code_wrap->code, " if (director) {\n");
  3378. Printf(code_wrap->code, " director->swig_java_change_ownership(jenv, jself, jtake_or_release ? true : false);\n");
  3379. Printf(code_wrap->code, " }\n");
  3380. Printf(code_wrap->code, "}\n");
  3381. Wrapper_print(code_wrap, f_wrappers);
  3382. DelWrapper(code_wrap);
  3383. Delete(changeown_method_name);
  3384. Delete(changeown_jnimethod_name);
  3385. Delete(norm_name);
  3386. Delete(dirClassName);
  3387. Delete(jni_imclass_name);
  3388. }
  3389. /*----------------------------------------------------------------------
  3390. * emitCodeTypemap()
  3391. *
  3392. * Output a code typemap that uses $methodname and $jnicall, as used
  3393. * in the directordisconnect, director_release and director_take
  3394. * typemaps.
  3395. *--------------------------------------------------------------------*/
  3396. void emitCodeTypemap(Node *n, bool derived, SwigType *lookup_type, const String *typemap, const String *methodname, const String *jnicall) {
  3397. const String *tm = NULL;
  3398. Node *tmattrs = NewHash();
  3399. String *lookup_tmname = NewString(typemap);
  3400. String *method_attr_name;
  3401. String *method_attr;
  3402. if (derived) {
  3403. Append(lookup_tmname, "_derived");
  3404. }
  3405. tm = typemapLookup(n, lookup_tmname, lookup_type, WARN_NONE, tmattrs);
  3406. method_attr_name = NewStringf("tmap:%s:%s", lookup_tmname, methodname);
  3407. method_attr = Getattr(tmattrs, method_attr_name);
  3408. if (*Char(tm)) {
  3409. if (method_attr) {
  3410. String *codebody = Copy(tm);
  3411. Replaceall(codebody, "$methodname", method_attr);
  3412. Replaceall(codebody, "$jnicall", jnicall);
  3413. Append(proxy_class_def, codebody);
  3414. Delete(codebody);
  3415. } else {
  3416. Swig_error(input_file, line_number, "No %s method name attribute for %s\n", lookup_tmname, proxy_class_name);
  3417. }
  3418. } else {
  3419. Swig_error(input_file, line_number, "No %s typemap for %s\n", lookup_tmname, proxy_class_name);
  3420. }
  3421. Delete(tmattrs);
  3422. Delete(lookup_tmname);
  3423. // Delete(method_attr);
  3424. }
  3425. /* -----------------------------------------------------------------------------
  3426. * substitutePackagePath()
  3427. *
  3428. * Replace $packagepath using the javapackage typemap associated with passed
  3429. * parm or global package if p is 0. "$packagepath/" is replaced with "" if
  3430. * no package is set. Note that the path separator is a '/'.
  3431. * ----------------------------------------------------------------------------- */
  3432. void substitutePackagePath(String *text, Parm *p) {
  3433. String *pkg_path= 0;
  3434. if (p)
  3435. pkg_path = Swig_typemap_lookup("javapackage", p, "", 0);
  3436. if (!pkg_path || Len(pkg_path) == 0)
  3437. pkg_path = Copy(package_path);
  3438. if (Len(pkg_path) > 0) {
  3439. Replaceall(pkg_path, ".", "/");
  3440. Replaceall(text, "$packagepath", pkg_path);
  3441. } else {
  3442. Replaceall(text, "$packagepath/", empty_string);
  3443. Replaceall(text, "$packagepath", empty_string);
  3444. }
  3445. Delete(pkg_path);
  3446. }
  3447. /* ---------------------------------------------------------------
  3448. * Canonicalize the JNI field descriptor
  3449. *
  3450. * Replace the $packagepath and $javaclassname family of special
  3451. * variables with the desired package and Java proxy name as
  3452. * required in the JNI field descriptors.
  3453. *
  3454. * !!SFM!! If $packagepath occurs in the field descriptor, but
  3455. * package_path isn't set (length == 0), then strip it and the
  3456. * optional trailing '/' from the resulting name.
  3457. *
  3458. * --------------------------------------------------------------- */
  3459. String *canonicalizeJNIDescriptor(String *descriptor_in, Parm *p) {
  3460. SwigType *type = Getattr(p, "type");
  3461. String *descriptor_out = Copy(descriptor_in);
  3462. substituteClassname(type, descriptor_out, true);
  3463. substitutePackagePath(descriptor_out, p);
  3464. return descriptor_out;
  3465. }
  3466. /* ---------------------------------------------------------------
  3467. * classDirectorMethod()
  3468. *
  3469. * Emit a virtual director method to pass a method call on to the
  3470. * underlying Java object.
  3471. *
  3472. * --------------------------------------------------------------- */
  3473. int classDirectorMethod(Node *n, Node *parent, String *super) {
  3474. String *c_classname = Getattr(parent, "name");
  3475. String *name = Getattr(n, "name");
  3476. String *symname = Getattr(n, "sym:name");
  3477. SwigType *returntype = Getattr(n, "type");
  3478. String *overloaded_name = getOverloadedName(n);
  3479. String *storage = Getattr(n, "storage");
  3480. String *value = Getattr(n, "value");
  3481. String *decl = Getattr(n, "decl");
  3482. String *declaration = NewString("");
  3483. String *tm;
  3484. Parm *p;
  3485. int i;
  3486. Wrapper *w = NewWrapper();
  3487. ParmList *l = Getattr(n, "parms");
  3488. bool is_void = !(Cmp(returntype, "void"));
  3489. String *qualified_return = 0;
  3490. bool pure_virtual = (!(Cmp(storage, "virtual")) && !(Cmp(value, "0")));
  3491. int status = SWIG_OK;
  3492. bool output_director = true;
  3493. String *dirclassname = directorClassName(parent);
  3494. String *qualified_name = NewStringf("%s::%s", dirclassname, name);
  3495. String *jnidesc = NewString("");
  3496. String *classdesc = NewString("");
  3497. String *jniret_desc = NewString("");
  3498. String *classret_desc = NewString("");
  3499. SwigType *c_ret_type = NULL;
  3500. String *jupcall_args = NewString("swigjobj");
  3501. String *imclass_dmethod;
  3502. String *callback_def = NewString("");
  3503. String *callback_code = NewString("");
  3504. String *imcall_args = NewString("");
  3505. int classmeth_off = curr_class_dmethod - first_class_dmethod;
  3506. bool ignored_method = GetFlag(n, "feature:ignore") ? true : false;
  3507. String *qualified_classname = getProxyName(getClassName());
  3508. // Kludge Alert: functionWrapper sets sym:overload properly, but it
  3509. // isn't at this point, so we have to manufacture it ourselves. At least
  3510. // we're consistent with the sym:overload name in functionWrapper. (?? when
  3511. // does the overloaded method name get set?)
  3512. imclass_dmethod = NewStringf("%s", Swig_name_member(getNSpace(), dirclassname, overloaded_name));
  3513. qualified_return = SwigType_rcaststr(returntype, "c_result");
  3514. if (!is_void && (!ignored_method || pure_virtual)) {
  3515. if (!SwigType_isclass(returntype)) {
  3516. if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
  3517. String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
  3518. Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL);
  3519. Delete(construct_result);
  3520. } else {
  3521. String *base_typename = SwigType_base(returntype);
  3522. String *resolved_typename = SwigType_typedef_resolve_all(base_typename);
  3523. Symtab *symtab = Getattr(n, "sym:symtab");
  3524. Node *typenode = Swig_symbol_clookup(resolved_typename, symtab);
  3525. if (SwigType_ispointer(returntype) || (typenode && Getattr(typenode, "abstracts"))) {
  3526. /* initialize pointers to something sane. Same for abstract
  3527. classes when a reference is returned. */
  3528. Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL);
  3529. } else {
  3530. /* If returning a reference, initialize the pointer to a sane
  3531. default - if a Java exception occurs, then the pointer returns
  3532. something other than a NULL-initialized reference. */
  3533. SwigType *noref_type = SwigType_del_reference(Copy(returntype));
  3534. String *noref_ltype = SwigType_lstr(noref_type, 0);
  3535. String *return_ltype = SwigType_lstr(returntype, 0);
  3536. Wrapper_add_localv(w, "result_default", "static", noref_ltype, "result_default", NIL);
  3537. Wrapper_add_localv(w, "c_result", return_ltype, "c_result", NIL);
  3538. Printf(w->code, "result_default = SwigValueInit< %s >();\n", noref_ltype);
  3539. Printf(w->code, "c_result = &result_default;\n");
  3540. Delete(return_ltype);
  3541. Delete(noref_ltype);
  3542. Delete(noref_type);
  3543. }
  3544. Delete(base_typename);
  3545. Delete(resolved_typename);
  3546. }
  3547. } else {
  3548. SwigType *vt;
  3549. vt = cplus_value_type(returntype);
  3550. if (!vt) {
  3551. Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), NIL);
  3552. } else {
  3553. Wrapper_add_localv(w, "c_result", SwigType_lstr(vt, "c_result"), NIL);
  3554. Delete(vt);
  3555. }
  3556. }
  3557. }
  3558. /* Create the intermediate class wrapper */
  3559. tm = Swig_typemap_lookup("jtype", n, "", 0);
  3560. if (tm) {
  3561. Printf(callback_def, " public static %s %s(%s jself", tm, imclass_dmethod, qualified_classname);
  3562. } else {
  3563. Swig_warning(WARN_JAVA_TYPEMAP_JTYPE_UNDEF, input_file, line_number, "No jtype typemap defined for %s\n", SwigType_str(returntype, 0));
  3564. }
  3565. String *cdesc = NULL;
  3566. SwigType *covariant = Getattr(n, "covariant");
  3567. SwigType *adjustedreturntype = covariant ? covariant : returntype;
  3568. Parm *adjustedreturntypeparm = NewParmNode(adjustedreturntype, n);
  3569. if (Swig_typemap_lookup("directorin", adjustedreturntypeparm, "", 0)
  3570. && (cdesc = Getattr(adjustedreturntypeparm, "tmap:directorin:descriptor"))) {
  3571. // Note that in the case of polymorphic (covariant) return types, the
  3572. // method's return type is changed to be the base of the C++ return
  3573. // type
  3574. String *jnidesc_canon = canonicalizeJNIDescriptor(cdesc, adjustedreturntypeparm);
  3575. Append(classret_desc, jnidesc_canon);
  3576. Delete(jnidesc_canon);
  3577. } else {
  3578. Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number, "No or improper directorin typemap defined for %s for use in %s::%s (skipping director method)\n",
  3579. SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
  3580. output_director = false;
  3581. }
  3582. /* Get the JNI field descriptor for this return type, add the JNI field descriptor
  3583. to jniret_desc */
  3584. if ((c_ret_type = Swig_typemap_lookup("jni", n, "", 0))) {
  3585. Parm *tp = NewParmNode(c_ret_type, n);
  3586. if (!is_void && !ignored_method) {
  3587. String *jretval_decl = NewStringf("%s jresult", c_ret_type);
  3588. Wrapper_add_localv(w, "jresult", jretval_decl, "= 0", NIL);
  3589. Delete(jretval_decl);
  3590. }
  3591. String *jdesc = NULL;
  3592. if (Swig_typemap_lookup("directorin", tp, "", 0)
  3593. && (jdesc = Getattr(tp, "tmap:directorin:descriptor"))) {
  3594. // Objects marshalled passing a Java class across JNI boundary use jobject - the nouse flag indicates this
  3595. // We need the specific Java class name instead of the generic 'Ljava/lang/Object;'
  3596. if (GetFlag(tp, "tmap:directorin:nouse"))
  3597. jdesc = cdesc;
  3598. String *jnidesc_canon = canonicalizeJNIDescriptor(jdesc, tp);
  3599. Append(jniret_desc, jnidesc_canon);
  3600. Delete(jnidesc_canon);
  3601. } else {
  3602. Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number,
  3603. "No or improper directorin typemap defined for %s for use in %s::%s (skipping director method)\n",
  3604. SwigType_str(c_ret_type, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
  3605. output_director = false;
  3606. }
  3607. Delete(tp);
  3608. } else {
  3609. Swig_warning(WARN_JAVA_TYPEMAP_JNI_UNDEF, input_file, line_number, "No jni typemap defined for %s for use in %s::%s (skipping director method)\n",
  3610. SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
  3611. output_director = false;
  3612. }
  3613. Delete(adjustedreturntypeparm);
  3614. Swig_director_parms_fixup(l);
  3615. /* Attach the standard typemaps */
  3616. Swig_typemap_attach_parms("out", l, 0);
  3617. Swig_typemap_attach_parms("jni", l, 0);
  3618. Swig_typemap_attach_parms("jtype", l, 0);
  3619. Swig_typemap_attach_parms("directorin", l, w);
  3620. Swig_typemap_attach_parms("javadirectorin", l, 0);
  3621. Swig_typemap_attach_parms("directorargout", l, w);
  3622. if (!ignored_method) {
  3623. /* Add Java environment pointer to wrapper */
  3624. String *jenvstr = NewString("jenv");
  3625. String *jobjstr = NewString("swigjobj");
  3626. Wrapper_add_localv(w, "swigjnienv", "JNIEnvWrapper", "swigjnienv(this)", NIL, NIL);
  3627. Wrapper_add_localv(w, jenvstr, "JNIEnv *", jenvstr, "= swigjnienv.getJNIEnv()", NIL);
  3628. Wrapper_add_localv(w, jobjstr, "jobject", jobjstr, "= (jobject) NULL", NIL);
  3629. Delete(jenvstr);
  3630. Delete(jobjstr);
  3631. /* Preamble code */
  3632. Printf(w->code, "if (!swig_override[%d]) {\n", classmeth_off);
  3633. }
  3634. if (!pure_virtual) {
  3635. String *super_call = Swig_method_call(super, l);
  3636. if (is_void) {
  3637. Printf(w->code, "%s;\n", super_call);
  3638. if (!ignored_method)
  3639. Printf(w->code, "return;\n");
  3640. } else {
  3641. Printf(w->code, "return %s;\n", super_call);
  3642. }
  3643. Delete(super_call);
  3644. } else {
  3645. Printf(w->code, "SWIG_JavaThrowException(JNIEnvWrapper(this).getJNIEnv(), SWIG_JavaDirectorPureVirtual, ");
  3646. Printf(w->code, "\"Attempted to invoke pure virtual method %s::%s.\");\n", SwigType_namestr(c_classname), SwigType_namestr(name));
  3647. /* Make sure that we return something in the case of a pure
  3648. * virtual method call for syntactical reasons. */
  3649. if (!is_void)
  3650. Printf(w->code, "return %s;", qualified_return);
  3651. else if (!ignored_method)
  3652. Printf(w->code, "return;\n");
  3653. }
  3654. if (!ignored_method) {
  3655. Printf(w->code, "}\n");
  3656. Printf(w->code, "swigjobj = swig_get_self(jenv);\n");
  3657. Printf(w->code, "if (swigjobj && jenv->IsSameObject(swigjobj, NULL) == JNI_FALSE) {\n");
  3658. }
  3659. /* Start the Java field descriptor for the intermediate class's upcall (insert jself object) */
  3660. Parm *tp = NewParmNode(c_classname, n);
  3661. String *jdesc;
  3662. if ((tm = Swig_typemap_lookup("directorin", tp, "", 0))
  3663. && (jdesc = Getattr(tp, "tmap:directorin:descriptor"))) {
  3664. String *jni_canon = canonicalizeJNIDescriptor(jdesc, tp);
  3665. Append(jnidesc, jni_canon);
  3666. Delete(jni_canon);
  3667. Delete(tm);
  3668. } else {
  3669. Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number,
  3670. "No or improper directorin typemap for type %s for use in %s::%s (skipping director method)\n",
  3671. SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
  3672. output_director = false;
  3673. }
  3674. Delete(tp);
  3675. /* Go through argument list, convert from native to Java */
  3676. for (i = 0, p = l; p; ++i) {
  3677. /* Is this superfluous? */
  3678. while (checkAttribute(p, "tmap:directorin:numinputs", "0")) {
  3679. p = Getattr(p, "tmap:directorin:next");
  3680. }
  3681. SwigType *pt = Getattr(p, "type");
  3682. String *ln = makeParameterName(n, p, i, false);
  3683. String *c_param_type = NULL;
  3684. String *c_decl = NewString("");
  3685. String *arg = NewString("");
  3686. Printf(arg, "j%s", ln);
  3687. /* Add various typemap's 'throws' clauses */
  3688. addThrows(n, "tmap:directorin", p);
  3689. addThrows(n, "tmap:out", p);
  3690. /* And add to the upcall args */
  3691. Printf(jupcall_args, ", %s", arg);
  3692. /* Get parameter's intermediary C type */
  3693. if ((c_param_type = Getattr(p, "tmap:jni"))) {
  3694. Parm *tp = NewParm(c_param_type, Getattr(p, "name"), n);
  3695. String *desc_tm = NULL, *jdesc = NULL, *cdesc = NULL;
  3696. /* Add to local variables */
  3697. Printf(c_decl, "%s %s", c_param_type, arg);
  3698. if (!ignored_method)
  3699. Wrapper_add_localv(w, arg, c_decl, (!(SwigType_ispointer(pt) || SwigType_isreference(pt)) ? "" : "= 0"), NIL);
  3700. /* Add input marshalling code and update JNI field descriptor */
  3701. if ((desc_tm = Swig_typemap_lookup("directorin", tp, "", 0))
  3702. && (jdesc = Getattr(tp, "tmap:directorin:descriptor"))
  3703. && (tm = Getattr(p, "tmap:directorin"))
  3704. && (cdesc = Getattr(p, "tmap:directorin:descriptor"))) {
  3705. // Objects marshalled by passing a Java class across the JNI boundary use jobject as the JNI type -
  3706. // the nouse flag indicates this. We need the specific Java class name instead of the generic 'Ljava/lang/Object;'
  3707. if (GetFlag(tp, "tmap:directorin:nouse"))
  3708. jdesc = cdesc;
  3709. String *jni_canon = canonicalizeJNIDescriptor(jdesc, tp);
  3710. Append(jnidesc, jni_canon);
  3711. Delete(jni_canon);
  3712. Setattr(p, "emit:directorinput", arg);
  3713. Replaceall(tm, "$input", arg);
  3714. Replaceall(tm, "$owner", "0");
  3715. if (Len(tm))
  3716. if (!ignored_method)
  3717. Printf(w->code, "%s\n", tm);
  3718. /* Add parameter to the intermediate class code if generating the
  3719. * intermediate's upcall code */
  3720. if ((tm = Getattr(p, "tmap:jtype"))) {
  3721. String *din = Copy(Getattr(p, "tmap:javadirectorin"));
  3722. addThrows(n, "tmap:javadirectorin", p);
  3723. if (din) {
  3724. Replaceall(din, "$module", module_class_name);
  3725. Replaceall(din, "$imclassname", imclass_name);
  3726. substituteClassname(pt, din);
  3727. Replaceall(din, "$jniinput", ln);
  3728. if (i > 0)
  3729. Printf(imcall_args, ", ");
  3730. Printf(callback_def, ", %s %s", tm, ln);
  3731. if (Cmp(din, ln)) {
  3732. Printv(imcall_args, din, NIL);
  3733. } else
  3734. Printv(imcall_args, ln, NIL);
  3735. jni_canon = canonicalizeJNIDescriptor(cdesc, p);
  3736. Append(classdesc, jni_canon);
  3737. Delete(jni_canon);
  3738. } else {
  3739. Swig_warning(WARN_JAVA_TYPEMAP_JAVADIRECTORIN_UNDEF, input_file, line_number, "No javadirectorin typemap defined for %s for use in %s::%s (skipping director method)\n",
  3740. SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
  3741. output_director = false;
  3742. }
  3743. } else {
  3744. Swig_warning(WARN_JAVA_TYPEMAP_JTYPE_UNDEF, input_file, line_number, "No jtype typemap defined for %s for use in %s::%s (skipping director method)\n",
  3745. SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
  3746. output_director = false;
  3747. }
  3748. p = Getattr(p, "tmap:directorin:next");
  3749. Delete(desc_tm);
  3750. } else {
  3751. if (!desc_tm) {
  3752. Swig_warning(WARN_JAVA_TYPEMAP_JAVADIRECTORIN_UNDEF, input_file, line_number,
  3753. "No or improper directorin typemap defined for %s for use in %s::%s (skipping director method)\n",
  3754. SwigType_str(c_param_type, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
  3755. p = nextSibling(p);
  3756. } else if (!jdesc) {
  3757. Swig_warning(WARN_JAVA_TYPEMAP_DIRECTORIN_NODESC, input_file, line_number,
  3758. "Missing JNI descriptor in directorin typemap defined for %s for use in %s::%s (skipping director method)\n",
  3759. SwigType_str(c_param_type, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
  3760. p = Getattr(p, "tmap:directorin:next");
  3761. } else if (!tm) {
  3762. Swig_warning(WARN_JAVA_TYPEMAP_JAVADIRECTORIN_UNDEF, input_file, line_number,
  3763. "No or improper directorin typemap defined for argument %s for use in %s::%s (skipping director method)\n",
  3764. SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
  3765. p = nextSibling(p);
  3766. } else if (!cdesc) {
  3767. Swig_warning(WARN_JAVA_TYPEMAP_DIRECTORIN_NODESC, input_file, line_number,
  3768. "Missing JNI descriptor in directorin typemap defined for %s for use in %s::%s (skipping director method)\n",
  3769. SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
  3770. p = Getattr(p, "tmap:directorin:next");
  3771. }
  3772. output_director = false;
  3773. }
  3774. } else {
  3775. Swig_warning(WARN_JAVA_TYPEMAP_JNI_UNDEF, input_file, line_number, "No jni typemap defined for %s for use in %s::%s (skipping director method)\n",
  3776. SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
  3777. output_director = false;
  3778. p = nextSibling(p);
  3779. }
  3780. Delete(arg);
  3781. Delete(c_decl);
  3782. Delete(ln);
  3783. }
  3784. /* header declaration, start wrapper definition */
  3785. String *target;
  3786. SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type");
  3787. target = Swig_method_decl(rtype, decl, qualified_name, l, 0);
  3788. Printf(w->def, "%s", target);
  3789. Delete(qualified_name);
  3790. Delete(target);
  3791. target = Swig_method_decl(rtype, decl, name, l, 1);
  3792. Printf(declaration, " virtual %s", target);
  3793. Delete(target);
  3794. // Add any exception specifications to the methods in the director class
  3795. // Get any Java exception classes in the throws typemap
  3796. ParmList *throw_parm_list = NULL;
  3797. // May need to add Java throws clause to director methods if %catches defined
  3798. // Get any Java exception classes in the throws typemap
  3799. ParmList *catches_list = Getattr(n, "catchlist");
  3800. if (catches_list) {
  3801. Swig_typemap_attach_parms("throws", catches_list, 0);
  3802. Swig_typemap_attach_parms("directorthrows", catches_list, 0);
  3803. for (p = catches_list; p; p = nextSibling(p)) {
  3804. addThrows(n, "tmap:throws", p);
  3805. }
  3806. }
  3807. if (Getattr(n, "noexcept")) {
  3808. Append(w->def, " noexcept");
  3809. Append(declaration, " noexcept");
  3810. }
  3811. if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
  3812. int gencomma = 0;
  3813. Append(w->def, " throw(");
  3814. Append(declaration, " throw(");
  3815. if (throw_parm_list) {
  3816. Swig_typemap_attach_parms("throws", throw_parm_list, 0);
  3817. Swig_typemap_attach_parms("directorthrows", throw_parm_list, 0);
  3818. }
  3819. for (p = throw_parm_list; p; p = nextSibling(p)) {
  3820. if (Getattr(p, "tmap:throws")) {
  3821. // %catches replaces the specified exception specification
  3822. if (!catches_list) {
  3823. addThrows(n, "tmap:throws", p);
  3824. }
  3825. if (gencomma++) {
  3826. Append(w->def, ", ");
  3827. Append(declaration, ", ");
  3828. }
  3829. Printf(w->def, "%s", SwigType_str(Getattr(p, "type"), 0));
  3830. Printf(declaration, "%s", SwigType_str(Getattr(p, "type"), 0));
  3831. }
  3832. }
  3833. Append(w->def, ")");
  3834. Append(declaration, ")");
  3835. }
  3836. Append(w->def, " {");
  3837. Append(declaration, ";\n");
  3838. /* Emit the intermediate class's upcall to the actual class */
  3839. String *upcall = NewStringf("jself.%s(%s)", symname, imcall_args);
  3840. // Handle exception classes specified in the "except" feature's "throws" attribute
  3841. addThrows(n, "feature:except", n);
  3842. if (!is_void) {
  3843. if ((tm = Swig_typemap_lookup("javadirectorout", n, "", 0))) {
  3844. addThrows(n, "tmap:javadirectorout", n);
  3845. substituteClassname(returntype, tm);
  3846. Replaceall(tm, "$javacall", upcall);
  3847. Printf(callback_code, " return %s;\n", tm);
  3848. }
  3849. if ((tm = Swig_typemap_lookup("out", n, "", 0)))
  3850. addThrows(n, "tmap:out", n);
  3851. Delete(tm);
  3852. } else
  3853. Printf(callback_code, " %s;\n", upcall);
  3854. Printf(callback_code, " }\n");
  3855. Delete(upcall);
  3856. /* Finish off the inherited upcall's definition */
  3857. Putc(')', callback_def);
  3858. generateThrowsClause(n, callback_def);
  3859. Printf(callback_def, " {\n");
  3860. if (!ignored_method) {
  3861. /* Emit the actual upcall through */
  3862. String *imclass_desc = NewStringf("(%s)%s", jnidesc, jniret_desc);
  3863. String *class_desc = NewStringf("(%s)%s", classdesc, classret_desc);
  3864. UpcallData *udata = addUpcallMethod(imclass_dmethod, symname, imclass_desc, class_desc, decl);
  3865. String *methid = Getattr(udata, "imclass_methodidx");
  3866. String *methop = getUpcallJNIMethod(jniret_desc);
  3867. if (!is_void)
  3868. Printf(w->code, "jresult = (%s) ", c_ret_type);
  3869. Printf(w->code, "jenv->%s(Swig::jclass_%s, Swig::director_method_ids[%s], %s);\n", methop, imclass_name, methid, jupcall_args);
  3870. // Generate code to handle any Java exception thrown by director delegation
  3871. directorExceptHandler(n, catches_list ? catches_list : throw_parm_list, w);
  3872. if (!is_void) {
  3873. String *jresult_str = NewString("jresult");
  3874. String *result_str = NewString("c_result");
  3875. /* Copy jresult into c_result... */
  3876. if ((tm = Swig_typemap_lookup("directorout", n, result_str, w))) {
  3877. addThrows(n, "tmap:directorout", n);
  3878. Replaceall(tm, "$input", jresult_str);
  3879. Replaceall(tm, "$result", result_str);
  3880. Printf(w->code, "%s\n", tm);
  3881. } else {
  3882. Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number,
  3883. "Unable to use return type %s used in %s::%s (skipping director method)\n",
  3884. SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
  3885. output_director = false;
  3886. }
  3887. Delete(jresult_str);
  3888. Delete(result_str);
  3889. }
  3890. /* Marshal outputs */
  3891. for (p = l; p;) {
  3892. if ((tm = Getattr(p, "tmap:directorargout"))) {
  3893. addThrows(n, "tmap:directorargout", p);
  3894. Replaceall(tm, "$result", makeParameterName(n, p, i, false));
  3895. Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
  3896. Printv(w->code, tm, "\n", NIL);
  3897. p = Getattr(p, "tmap:directorargout:next");
  3898. } else {
  3899. p = nextSibling(p);
  3900. }
  3901. }
  3902. Delete(imclass_desc);
  3903. Delete(class_desc);
  3904. /* Terminate wrapper code */
  3905. Printf(w->code, "} else {\n");
  3906. Printf(w->code, "SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, \"null upcall object in %s::%s \");\n",
  3907. SwigType_namestr(c_classname), SwigType_namestr(name));
  3908. Printf(w->code, "}\n");
  3909. Printf(w->code, "if (swigjobj) jenv->DeleteLocalRef(swigjobj);\n");
  3910. if (!is_void)
  3911. Printf(w->code, "return %s;", qualified_return);
  3912. }
  3913. Printf(w->code, "}");
  3914. // We expose virtual protected methods via an extra public inline method which makes a straight call to the wrapped class' method
  3915. String *inline_extra_method = NewString("");
  3916. if (dirprot_mode() && !is_public(n) && !pure_virtual) {
  3917. Printv(inline_extra_method, declaration, NIL);
  3918. String *extra_method_name = NewStringf("%sSwigPublic", name);
  3919. Replaceall(inline_extra_method, name, extra_method_name);
  3920. Replaceall(inline_extra_method, ";\n", " {\n ");
  3921. if (!is_void)
  3922. Printf(inline_extra_method, "return ");
  3923. String *methodcall = Swig_method_call(super, l);
  3924. Printv(inline_extra_method, methodcall, ";\n }\n", NIL);
  3925. Delete(methodcall);
  3926. Delete(extra_method_name);
  3927. }
  3928. /* emit the director method */
  3929. if (status == SWIG_OK && output_director) {
  3930. if (!is_void) {
  3931. Replaceall(w->code, "$null", qualified_return);
  3932. } else {
  3933. Replaceall(w->code, "$null", "");
  3934. }
  3935. if (!GetFlag(n, "feature:ignore"))
  3936. Printv(imclass_directors, callback_def, callback_code, NIL);
  3937. if (!Getattr(n, "defaultargs")) {
  3938. Replaceall(w->code, "$symname", symname);
  3939. Wrapper_print(w, f_directors);
  3940. Printv(f_directors_h, declaration, NIL);
  3941. Printv(f_directors_h, inline_extra_method, NIL);
  3942. }
  3943. }
  3944. Delete(inline_extra_method);
  3945. Delete(qualified_return);
  3946. Delete(jnidesc);
  3947. Delete(c_ret_type);
  3948. Delete(jniret_desc);
  3949. Delete(declaration);
  3950. Delete(callback_def);
  3951. Delete(callback_code);
  3952. DelWrapper(w);
  3953. return status;
  3954. }
  3955. /* ------------------------------------------------------------
  3956. * directorExceptHandler()
  3957. *
  3958. * Emit code to map Java exceptions back to C++ exceptions when
  3959. * feature("director:except") is applied to a method node.
  3960. * This is generated after the Java method upcall.
  3961. * ------------------------------------------------------------ */
  3962. void directorExceptHandler(Node *n, ParmList *throw_parm_list, Wrapper *w) {
  3963. String *directorexcept = Getattr(n, "feature:director:except");
  3964. if (!directorexcept) {
  3965. directorexcept = NewString("");
  3966. Printf(directorexcept, "jthrowable $error = jenv->ExceptionOccurred();\n");
  3967. Printf(directorexcept, "if ($error) {");
  3968. Printf(directorexcept, "$directorthrowshandlers\n");
  3969. Printf(directorexcept, " Swig::DirectorException::raise(jenv, $error);\n");
  3970. Printf(directorexcept, "}\n");
  3971. } else {
  3972. directorexcept = Copy(directorexcept);
  3973. }
  3974. // Can explicitly disable director:except by setting to "" or "0"
  3975. if (Len(directorexcept) > 0 && Cmp(directorexcept, "0") != 0) {
  3976. // Replace $packagepath
  3977. substitutePackagePath(directorexcept, 0);
  3978. // Replace $directorthrowshandlers with any defined typemap handlers (or nothing)
  3979. if (Strstr(directorexcept, "$directorthrowshandlers")) {
  3980. String *directorthrowshandlers_code = NewString("");
  3981. for (Parm *p = throw_parm_list; p; p = nextSibling(p)) {
  3982. String *tm = Getattr(p, "tmap:directorthrows");
  3983. if (tm) {
  3984. // replace $packagepath/$javaclassname
  3985. String *directorthrows = canonicalizeJNIDescriptor(tm, p);
  3986. Printv(directorthrowshandlers_code, directorthrows, NIL);
  3987. Delete(directorthrows);
  3988. } else {
  3989. String *t = Getattr(p,"type");
  3990. Swig_warning(WARN_TYPEMAP_DIRECTORTHROWS_UNDEF, Getfile(n), Getline(n), "No directorthrows typemap defined for %s\n", SwigType_str(t, 0));
  3991. }
  3992. }
  3993. Replaceall(directorexcept, "$directorthrowshandlers", directorthrowshandlers_code);
  3994. Delete(directorthrowshandlers_code);
  3995. }
  3996. Replaceall(directorexcept, "$error", "swigerror");
  3997. Printf(w->code, " %s\n", directorexcept);
  3998. }
  3999. Delete(directorexcept);
  4000. }
  4001. /* ------------------------------------------------------------
  4002. * directorPrefixArgs()
  4003. * ------------------------------------------------------------ */
  4004. void directorPrefixArgs(Node *n) {
  4005. Parm *p;
  4006. /* Need to prepend 'jenv' to the director constructor's argument list */
  4007. String *jenv_type = NewString("JNIEnv");
  4008. SwigType_add_pointer(jenv_type);
  4009. p = NewParm(jenv_type, NewString("jenv"), n);
  4010. Setattr(p, "arg:byname", "1");
  4011. set_nextSibling(p, NULL);
  4012. Setattr(n, "director:prefix_args", p);
  4013. }
  4014. /* ------------------------------------------------------------
  4015. * classDirectorConstructor()
  4016. * ------------------------------------------------------------ */
  4017. int classDirectorConstructor(Node *n) {
  4018. Node *parent = parentNode(n);
  4019. String *decl = Getattr(n, "decl");
  4020. String *supername = Swig_class_name(parent);
  4021. String *dirclassname = directorClassName(parent);
  4022. String *sub = NewString("");
  4023. Parm *p;
  4024. ParmList *superparms = Getattr(n, "parms");
  4025. ParmList *parms;
  4026. int argidx = 0;
  4027. /* Assign arguments to superclass's parameters, if not already done */
  4028. for (p = superparms; p; p = nextSibling(p)) {
  4029. String *pname = Getattr(p, "name");
  4030. if (!pname) {
  4031. pname = NewStringf("arg%d", argidx++);
  4032. Setattr(p, "name", pname);
  4033. }
  4034. }
  4035. /* insert jenv prefix argument */
  4036. parms = CopyParmList(superparms);
  4037. String *jenv_type = NewString("JNIEnv");
  4038. SwigType_add_pointer(jenv_type);
  4039. p = NewParm(jenv_type, NewString("jenv"), n);
  4040. set_nextSibling(p, parms);
  4041. parms = p;
  4042. directorPrefixArgs(n);
  4043. if (!Getattr(n, "defaultargs")) {
  4044. /* constructor */
  4045. {
  4046. String *basetype = Getattr(parent, "classtype");
  4047. String *target = Swig_method_decl(0, decl, dirclassname, parms, 0);
  4048. String *call = Swig_csuperclass_call(0, basetype, superparms);
  4049. String *classtype = SwigType_namestr(Getattr(n, "name"));
  4050. Printf(f_directors, "%s::%s : %s, %s {\n", dirclassname, target, call, Getattr(parent, "director:ctor"));
  4051. Printf(f_directors, "}\n\n");
  4052. Delete(classtype);
  4053. Delete(target);
  4054. Delete(call);
  4055. }
  4056. /* constructor header */
  4057. {
  4058. String *target = Swig_method_decl(0, decl, dirclassname, parms, 1);
  4059. Printf(f_directors_h, " %s;\n", target);
  4060. Delete(target);
  4061. }
  4062. }
  4063. Delete(sub);
  4064. Delete(supername);
  4065. Delete(jenv_type);
  4066. Delete(parms);
  4067. Delete(dirclassname);
  4068. return Language::classDirectorConstructor(n);
  4069. }
  4070. /* ------------------------------------------------------------
  4071. * classDirectorDefaultConstructor()
  4072. * ------------------------------------------------------------ */
  4073. int classDirectorDefaultConstructor(Node *n) {
  4074. String *classname = Swig_class_name(n);
  4075. String *classtype = SwigType_namestr(Getattr(n, "name"));
  4076. String *dirClassName = directorClassName(n);
  4077. Wrapper *w = NewWrapper();
  4078. Printf(w->def, "%s::%s(JNIEnv *jenv) : %s {", dirClassName, dirClassName, Getattr(n, "director:ctor"));
  4079. Printf(w->code, "}\n");
  4080. Wrapper_print(w, f_directors);
  4081. Printf(f_directors_h, " %s(JNIEnv *jenv);\n", dirClassName);
  4082. DelWrapper(w);
  4083. Delete(classtype);
  4084. Delete(classname);
  4085. Delete(dirClassName);
  4086. directorPrefixArgs(n);
  4087. return Language::classDirectorDefaultConstructor(n);
  4088. }
  4089. /* ------------------------------------------------------------
  4090. * classDirectorInit()
  4091. * ------------------------------------------------------------ */
  4092. int classDirectorInit(Node *n) {
  4093. Delete(none_comparison);
  4094. none_comparison = NewString(""); // not used
  4095. Delete(director_ctor_code);
  4096. director_ctor_code = NewString("$director_new");
  4097. directorDeclaration(n);
  4098. Printf(f_directors_h, "%s {\n", Getattr(n, "director:decl"));
  4099. Printf(f_directors_h, "\npublic:\n");
  4100. Printf(f_directors_h, " void swig_connect_director(JNIEnv *jenv, jobject jself, jclass jcls, bool swig_mem_own, bool weak_global);\n");
  4101. /* Keep track of the director methods for this class */
  4102. first_class_dmethod = curr_class_dmethod = n_dmethods;
  4103. return Language::classDirectorInit(n);
  4104. }
  4105. /* ----------------------------------------------------------------------
  4106. * classDirectorDestructor()
  4107. * ---------------------------------------------------------------------- */
  4108. int classDirectorDestructor(Node *n) {
  4109. Node *current_class = getCurrentClass();
  4110. String *full_classname = Getattr(current_class, "name");
  4111. String *classname = Swig_class_name(current_class);
  4112. String *dirClassName = directorClassName(current_class);
  4113. Wrapper *w = NewWrapper();
  4114. if (Getattr(n, "noexcept")) {
  4115. Printf(f_directors_h, " virtual ~%s() noexcept;\n", dirClassName);
  4116. Printf(w->def, "%s::~%s() noexcept {\n", dirClassName, dirClassName);
  4117. } else if (Getattr(n, "throw")) {
  4118. Printf(f_directors_h, " virtual ~%s() throw();\n", dirClassName);
  4119. Printf(w->def, "%s::~%s() throw() {\n", dirClassName, dirClassName);
  4120. } else {
  4121. Printf(f_directors_h, " virtual ~%s();\n", dirClassName);
  4122. Printf(w->def, "%s::~%s() {\n", dirClassName, dirClassName);
  4123. }
  4124. /* Ensure that correct directordisconnect typemap's method name is called
  4125. * here: */
  4126. Node *disconn_attr = NewHash();
  4127. String *disconn_methodname = NULL;
  4128. typemapLookup(n, "directordisconnect", full_classname, WARN_NONE, disconn_attr);
  4129. disconn_methodname = Getattr(disconn_attr, "tmap:directordisconnect:methodname");
  4130. Printv(w->code, " swig_disconnect_director_self(\"", disconn_methodname, "\");\n", "}\n", NIL);
  4131. Wrapper_print(w, f_directors);
  4132. DelWrapper(w);
  4133. Delete(disconn_attr);
  4134. Delete(classname);
  4135. Delete(dirClassName);
  4136. return SWIG_OK;
  4137. }
  4138. /* ------------------------------------------------------------
  4139. * classDirectorEnd()
  4140. * ------------------------------------------------------------ */
  4141. int classDirectorEnd(Node *n) {
  4142. String *full_classname = Getattr(n, "name");
  4143. String *classname = getProxyName(full_classname, true);
  4144. String *director_classname = directorClassName(n);
  4145. String *internal_classname;
  4146. Wrapper *w = NewWrapper();
  4147. if (Len(package_path) > 0)
  4148. internal_classname = NewStringf("%s/%s", package_path, classname);
  4149. else
  4150. internal_classname = NewStringf("%s", classname);
  4151. // If the namespace is multiple levels, the result of getNSpace() will have inserted
  4152. // .'s to delimit namespaces, so we need to replace those with /'s
  4153. Replace(internal_classname, NSPACE_SEPARATOR, "/", DOH_REPLACE_ANY);
  4154. Printf(w->def, "void %s::swig_connect_director(JNIEnv *jenv, jobject jself, jclass jcls, bool swig_mem_own, bool weak_global) {", director_classname);
  4155. Printf(w->def, "static jclass baseclass = swig_new_global_ref(jenv, \"%s\");\n", internal_classname);
  4156. Printf(w->def, "if (!baseclass) return;\n");
  4157. if (first_class_dmethod != curr_class_dmethod) {
  4158. Printf(w->def, "static SwigDirectorMethod methods[] = {\n");
  4159. for (int i = first_class_dmethod; i < curr_class_dmethod; ++i) {
  4160. UpcallData *udata = Getitem(dmethods_seq, i);
  4161. Printf(w->def, "SwigDirectorMethod(jenv, baseclass, \"%s\", \"%s\")", Getattr(udata, "method"), Getattr(udata, "fdesc"));
  4162. if (i != curr_class_dmethod - 1)
  4163. Putc(',', w->def);
  4164. Putc('\n', w->def);
  4165. }
  4166. Printf(w->def, "};");
  4167. }
  4168. Printf(w->code, "if (swig_set_self(jenv, jself, swig_mem_own, weak_global)) {\n");
  4169. int n_methods = curr_class_dmethod - first_class_dmethod;
  4170. if (n_methods) {
  4171. /* Emit the swig_overrides() method and the swig_override array */
  4172. Printf(f_directors_h, "public:\n");
  4173. Printf(f_directors_h, " bool swig_overrides(int n) {\n");
  4174. Printf(f_directors_h, " return (n < %d ? swig_override[n] : false);\n", n_methods);
  4175. Printf(f_directors_h, " }\n");
  4176. Printf(f_directors_h, "protected:\n");
  4177. Printf(f_directors_h, " Swig::BoolArray<%d> swig_override;\n", n_methods);
  4178. /* Emit the code to look up the class's methods, initialize the override array */
  4179. Printf(w->code, " bool derived = (jenv->IsSameObject(baseclass, jcls) ? false : true);\n");
  4180. Printf(w->code, " for (int i = 0; i < %d; ++i) {\n", n_methods);
  4181. // Generally, derived classes have a mix of overridden and
  4182. // non-overridden methods and it is worth making a GetMethodID
  4183. // check during initialization to determine if each method is
  4184. // overridden, thus avoiding unnecessary calls into Java.
  4185. //
  4186. // On the other hand, when derived classes are
  4187. // expected to override all director methods then the
  4188. // GetMethodID calls are inefficient, and it is better to let
  4189. // the director unconditionally call up into Java. The resulting code
  4190. // will still behave correctly (though less efficiently) when Java
  4191. // code doesn't override a given method.
  4192. //
  4193. // The assumeoverride feature on a director controls whether or not
  4194. // overrides are assumed.
  4195. if (GetFlag(n, "feature:director:assumeoverride")) {
  4196. Printf(w->code, " swig_override[i] = derived;\n");
  4197. } else {
  4198. Printf(w->code, " swig_override[i] = false;\n");
  4199. Printf(w->code, " if (derived) {\n");
  4200. Printf(w->code, " jmethodID methid = jenv->GetMethodID(jcls, methods[i].name, methods[i].desc);\n");
  4201. Printf(w->code, " swig_override[i] = methods[i].methid && (methid != methods[i].methid);\n");
  4202. Printf(w->code, " jenv->ExceptionClear();\n");
  4203. Printf(w->code, " }\n");
  4204. }
  4205. Printf(w->code, "}\n");
  4206. } else {
  4207. Printf(f_directors_h, "public:\n");
  4208. Printf(f_directors_h, " bool swig_overrides(int n) {\n");
  4209. Printf(f_directors_h, " return false;\n");
  4210. Printf(f_directors_h, " }\n");
  4211. }
  4212. Printf(f_directors_h, "};\n\n");
  4213. Printf(w->code, "}\n");
  4214. Printf(w->code, "}\n");
  4215. Wrapper_print(w, f_directors);
  4216. DelWrapper(w);
  4217. Delete(internal_classname);
  4218. return Language::classDirectorEnd(n);
  4219. }
  4220. /* --------------------------------------------------------------------
  4221. * classDirectorDisown()
  4222. * ------------------------------------------------------------------*/
  4223. virtual int classDirectorDisown(Node *n) {
  4224. (void) n;
  4225. return SWIG_OK;
  4226. }
  4227. /*----------------------------------------------------------------------
  4228. * extraDirectorProtectedCPPMethodsRequired()
  4229. *--------------------------------------------------------------------*/
  4230. bool extraDirectorProtectedCPPMethodsRequired() const {
  4231. return false;
  4232. }
  4233. /*----------------------------------------------------------------------
  4234. * directorDeclaration()
  4235. *
  4236. * Generate the director class's declaration
  4237. * e.g. "class SwigDirector_myclass : public myclass, public Swig::Director {"
  4238. *--------------------------------------------------------------------*/
  4239. void directorDeclaration(Node *n) {
  4240. String *base = Getattr(n, "classtype");
  4241. String *class_ctor = NewString("Swig::Director(jenv)");
  4242. String *directorname = directorClassName(n);
  4243. String *declaration = Swig_class_declaration(n, directorname);
  4244. Printf(declaration, " : public %s, public Swig::Director", base);
  4245. // Stash stuff for later.
  4246. Setattr(n, "director:decl", declaration);
  4247. Setattr(n, "director:ctor", class_ctor);
  4248. }
  4249. /*----------------------------------------------------------------------
  4250. * nestedClassesSupport()
  4251. *--------------------------------------------------------------------*/
  4252. NestedClassSupport nestedClassesSupport() const {
  4253. return NCS_Full;
  4254. }
  4255. }; /* class JAVA */
  4256. /* -----------------------------------------------------------------------------
  4257. * swig_java() - Instantiate module
  4258. * ----------------------------------------------------------------------------- */
  4259. static Language *new_swig_java() {
  4260. return new JAVA();
  4261. }
  4262. extern "C" Language *swig_java(void) {
  4263. return new_swig_java();
  4264. }
  4265. /* -----------------------------------------------------------------------------
  4266. * Static member variables
  4267. * ----------------------------------------------------------------------------- */
  4268. const char *JAVA::usage = "\
  4269. Java Options (available with -java)\n\
  4270. -doxygen - Convert C++ doxygen comments to JavaDoc comments in proxy classes\n\
  4271. -debug-doxygen-parser - Display doxygen parser module debugging information\n\
  4272. -debug-doxygen-translator - Display doxygen translator module debugging information\n\
  4273. -nopgcpp - Suppress premature garbage collection prevention parameter\n\
  4274. -noproxy - Generate the low-level functional interface instead\n\
  4275. of proxy classes\n\
  4276. -oldvarnames - Old intermediary method names for variable wrappers\n\
  4277. -package <name> - Set name of the Java package to <name>\n\
  4278. \n";