as_scriptengine.cpp 195 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671
  1. /*
  2. AngelCode Scripting Library
  3. Copyright (c) 2003-2022 Andreas Jonsson
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any
  6. damages arising from the use of this software.
  7. Permission is granted to anyone to use this software for any
  8. purpose, including commercial applications, and to alter it and
  9. redistribute it freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you
  11. must not claim that you wrote the original software. If you use
  12. this software in a product, an acknowledgment in the product
  13. documentation would be appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and
  15. must not be misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source
  17. distribution.
  18. The original version of this library can be located at:
  19. http://www.angelcode.com/angelscript/
  20. Andreas Jonsson
  21. [email protected]
  22. */
  23. //
  24. // as_scriptengine.cpp
  25. //
  26. // The implementation of the script engine interface
  27. //
  28. #include <stdlib.h>
  29. #include "as_config.h"
  30. #include "as_scriptengine.h"
  31. #include "as_builder.h"
  32. #include "as_context.h"
  33. #include "as_string_util.h"
  34. #include "as_tokenizer.h"
  35. #include "as_texts.h"
  36. #include "as_module.h"
  37. #include "as_callfunc.h"
  38. #include "as_generic.h"
  39. #include "as_scriptobject.h"
  40. #include "as_compiler.h"
  41. #include "as_bytecode.h"
  42. #include "as_debug.h"
  43. BEGIN_AS_NAMESPACE
  44. #ifdef AS_PROFILE
  45. // Instantiate the profiler once
  46. CProfiler g_profiler;
  47. #endif
  48. extern "C"
  49. {
  50. AS_API const char * asGetLibraryVersion()
  51. {
  52. #ifdef _DEBUG
  53. return ANGELSCRIPT_VERSION_STRING " DEBUG";
  54. #else
  55. return ANGELSCRIPT_VERSION_STRING;
  56. #endif
  57. }
  58. AS_API const char * asGetLibraryOptions()
  59. {
  60. const char *string = " "
  61. // Options
  62. #ifdef AS_MAX_PORTABILITY
  63. "AS_MAX_PORTABILITY "
  64. #endif
  65. #ifdef AS_DEBUG
  66. "AS_DEBUG "
  67. #endif
  68. #ifdef AS_NO_CLASS_METHODS
  69. "AS_NO_CLASS_METHODS "
  70. #endif
  71. #ifdef AS_USE_DOUBLE_AS_FLOAT
  72. "AS_USE_DOUBLE_AS_FLOAT "
  73. #endif
  74. #ifdef AS_64BIT_PTR
  75. "AS_64BIT_PTR "
  76. #endif
  77. #ifdef AS_NO_THREADS
  78. "AS_NO_THREADS "
  79. #endif
  80. #ifdef AS_NO_ATOMIC
  81. "AS_NO_ATOMIC "
  82. #endif
  83. #ifdef AS_NO_COMPILER
  84. "AS_NO_COMPILER "
  85. #endif
  86. #ifdef AS_NO_MEMBER_INIT
  87. "AS_NO_MEMBER_INIT "
  88. #endif
  89. #ifdef AS_NO_THISCALL_FUNCTOR_METHOD
  90. "AS_NO_THISCALL_FUNCTOR_METHOD "
  91. #endif
  92. #ifdef AS_NO_EXCEPTIONS
  93. "AS_NO_EXCEPTIONS "
  94. #endif
  95. #ifdef WIP_16BYTE_ALIGN
  96. "WIP_16BYTE_ALIGN "
  97. #endif
  98. #ifdef AS_BIG_ENDIAN
  99. "AS_BIG_ENDIAN "
  100. #endif
  101. // Target system
  102. #ifdef AS_WIN
  103. "AS_WIN "
  104. #endif
  105. #ifdef AS_LINUX
  106. "AS_LINUX "
  107. #endif
  108. #ifdef AS_MAC
  109. "AS_MAC "
  110. #endif
  111. #ifdef AS_SUN
  112. "AS_SUN "
  113. #endif
  114. #ifdef AS_BSD
  115. "AS_BSD "
  116. #endif
  117. #ifdef AS_XBOX
  118. "AS_XBOX "
  119. #endif
  120. #ifdef AS_XBOX360
  121. "AS_XBOX360 "
  122. #endif
  123. #ifdef AS_PSP
  124. "AS_PSP "
  125. #endif
  126. #ifdef AS_PS2
  127. "AS_PS2 "
  128. #endif
  129. #ifdef AS_PS3
  130. "AS_PS3 "
  131. #endif
  132. #ifdef AS_PSVITA
  133. "AS_PSVITA "
  134. #endif
  135. #ifdef AS_DC
  136. "AS_DC "
  137. #endif
  138. #ifdef AS_GC
  139. "AS_GC "
  140. #endif
  141. #ifdef AS_WII
  142. "AS_WII "
  143. #endif
  144. #ifdef AS_WIIU
  145. "AS_WIIU "
  146. #endif
  147. #ifdef AS_IPHONE
  148. "AS_IPHONE "
  149. #endif
  150. #ifdef AS_ANDROID
  151. "AS_ANDROID "
  152. #endif
  153. #ifdef AS_HAIKU
  154. "AS_HAIKU "
  155. #endif
  156. #ifdef AS_ILLUMOS
  157. "AS_ILLUMOS "
  158. #endif
  159. #ifdef AS_MARMALADE
  160. "AS_MARMALADE "
  161. #endif
  162. // CPU family
  163. #ifdef AS_PPC
  164. "AS_PPC "
  165. #endif
  166. #ifdef AS_PPC_64
  167. "AS_PPC_64 "
  168. #endif
  169. #ifdef AS_X86
  170. "AS_X86 "
  171. #endif
  172. #ifdef AS_MIPS
  173. "AS_MIPS "
  174. #endif
  175. #ifdef AS_SH4
  176. "AS_SH4 "
  177. #endif
  178. #ifdef AS_XENON
  179. "AS_XENON "
  180. #endif
  181. #ifdef AS_ARM
  182. "AS_ARM "
  183. #endif
  184. #ifdef AS_SOFTFP
  185. "AS_SOFTFP "
  186. #endif
  187. #ifdef AS_X64_GCC
  188. "AS_X64_GCC "
  189. #endif
  190. #ifdef AS_X64_MSVC
  191. "AS_X64_MSVC "
  192. #endif
  193. #ifdef AS_SPARC
  194. "AS_SPARC "
  195. #endif
  196. #ifdef AS_ARM64
  197. "AS_ARM64 "
  198. #endif
  199. ;
  200. return string;
  201. }
  202. AS_API asIScriptEngine *asCreateScriptEngine(asDWORD version)
  203. {
  204. // Verify the version that the application expects
  205. if( (version/10000) != (ANGELSCRIPT_VERSION/10000) )
  206. return 0;
  207. if( (version/100)%100 != (ANGELSCRIPT_VERSION/100)%100 )
  208. return 0;
  209. if( (version%100) > (ANGELSCRIPT_VERSION%100) )
  210. return 0;
  211. // Verify the size of the types
  212. asASSERT( sizeof(asBYTE) == 1 );
  213. asASSERT( sizeof(asWORD) == 2 );
  214. asASSERT( sizeof(asDWORD) == 4 );
  215. asASSERT( sizeof(asQWORD) == 8 );
  216. asASSERT( sizeof(asPWORD) == sizeof(void*) );
  217. // Verify the boolean type
  218. asASSERT( sizeof(bool) == AS_SIZEOF_BOOL );
  219. asASSERT( true == VALUE_OF_BOOLEAN_TRUE );
  220. // Verify endianess
  221. #ifdef AS_BIG_ENDIAN
  222. asDWORD dw = 0x00010203;
  223. asQWORD qw = ((asQWORD(0x00010203)<<32)|asQWORD(0x04050607));
  224. #else
  225. asDWORD dw = 0x03020100;
  226. // C++ didn't have a standard way of declaring 64bit literal constants until C++11, so
  227. // I'm forced to do it like this to avoid compilers warnings when compiling with the full
  228. // C++ compliance.
  229. asQWORD qw = ((asQWORD(0x07060504)<<32)|asQWORD(0x03020100));
  230. #endif
  231. asASSERT( memcmp("\x00\x01\x02\x03", &dw, 4) == 0 );
  232. asASSERT( memcmp("\x00\x01\x02\x03\x04\x05\x06\x07", &qw, 8) == 0 );
  233. UNUSED_VAR(dw);
  234. UNUSED_VAR(qw);
  235. return asNEW(asCScriptEngine)();
  236. }
  237. } // extern "C"
  238. // interface
  239. int asCScriptEngine::SetEngineProperty(asEEngineProp property, asPWORD value)
  240. {
  241. switch( property )
  242. {
  243. case asEP_ALLOW_UNSAFE_REFERENCES:
  244. ep.allowUnsafeReferences = value ? true : false;
  245. break;
  246. case asEP_OPTIMIZE_BYTECODE:
  247. ep.optimizeByteCode = value ? true : false;
  248. break;
  249. case asEP_COPY_SCRIPT_SECTIONS:
  250. ep.copyScriptSections = value ? true : false;
  251. break;
  252. case asEP_MAX_STACK_SIZE:
  253. if( value == 0 )
  254. {
  255. // Restore default: no limit and initially size 4KB
  256. ep.maximumContextStackSize = 0;
  257. }
  258. else
  259. {
  260. // The size is given in bytes, but we only store dwords
  261. ep.maximumContextStackSize = (asUINT)value/4;
  262. }
  263. break;
  264. case asEP_INIT_STACK_SIZE:
  265. if (value < 4)
  266. {
  267. // At least one dword
  268. ep.initContextStackSize = 1;
  269. }
  270. else
  271. {
  272. // The size is given in bytes, but we only store dwords
  273. ep.initContextStackSize = (asUINT)value / 4;
  274. }
  275. break;
  276. case asEP_USE_CHARACTER_LITERALS:
  277. ep.useCharacterLiterals = value ? true : false;
  278. break;
  279. case asEP_ALLOW_MULTILINE_STRINGS:
  280. ep.allowMultilineStrings = value ? true : false;
  281. break;
  282. case asEP_ALLOW_IMPLICIT_HANDLE_TYPES:
  283. ep.allowImplicitHandleTypes = value ? true : false;
  284. break;
  285. case asEP_BUILD_WITHOUT_LINE_CUES:
  286. ep.buildWithoutLineCues = value ? true : false;
  287. break;
  288. case asEP_INIT_GLOBAL_VARS_AFTER_BUILD:
  289. ep.initGlobalVarsAfterBuild = value ? true : false;
  290. break;
  291. case asEP_REQUIRE_ENUM_SCOPE:
  292. ep.requireEnumScope = value ? true : false;
  293. break;
  294. case asEP_SCRIPT_SCANNER:
  295. if( value <= 1 )
  296. ep.scanner = (int)value;
  297. else
  298. return asINVALID_ARG;
  299. break;
  300. case asEP_INCLUDE_JIT_INSTRUCTIONS:
  301. ep.includeJitInstructions = value ? true : false;
  302. break;
  303. case asEP_STRING_ENCODING:
  304. if( value <= 1 )
  305. ep.stringEncoding = (int)value;
  306. else
  307. return asINVALID_ARG;
  308. break;
  309. case asEP_PROPERTY_ACCESSOR_MODE:
  310. if( value <= 3 )
  311. ep.propertyAccessorMode = (int)value;
  312. else
  313. return asINVALID_ARG;
  314. break;
  315. case asEP_EXPAND_DEF_ARRAY_TO_TMPL:
  316. ep.expandDefaultArrayToTemplate = value ? true : false;
  317. break;
  318. case asEP_AUTO_GARBAGE_COLLECT:
  319. ep.autoGarbageCollect = value ? true : false;
  320. break;
  321. case asEP_DISALLOW_GLOBAL_VARS:
  322. ep.disallowGlobalVars = value ? true : false;
  323. break;
  324. case asEP_ALWAYS_IMPL_DEFAULT_CONSTRUCT:
  325. ep.alwaysImplDefaultConstruct = value ? true : false;
  326. break;
  327. case asEP_COMPILER_WARNINGS:
  328. if( value <= 2 )
  329. ep.compilerWarnings = (int)value;
  330. else
  331. return asINVALID_ARG;
  332. break;
  333. case asEP_DISALLOW_VALUE_ASSIGN_FOR_REF_TYPE:
  334. ep.disallowValueAssignForRefType = value ? true : false;
  335. break;
  336. case asEP_ALTER_SYNTAX_NAMED_ARGS:
  337. if( value <= 2 )
  338. ep.alterSyntaxNamedArgs = (int)value;
  339. else
  340. return asINVALID_ARG;
  341. break;
  342. case asEP_DISABLE_INTEGER_DIVISION:
  343. ep.disableIntegerDivision = value ? true : false;
  344. break;
  345. case asEP_DISALLOW_EMPTY_LIST_ELEMENTS:
  346. ep.disallowEmptyListElements = value ? true : false;
  347. break;
  348. case asEP_PRIVATE_PROP_AS_PROTECTED:
  349. ep.privatePropAsProtected = value ? true : false;
  350. break;
  351. case asEP_ALLOW_UNICODE_IDENTIFIERS:
  352. ep.allowUnicodeIdentifiers = value ? true : false;
  353. break;
  354. case asEP_HEREDOC_TRIM_MODE:
  355. if (value <= 2)
  356. ep.heredocTrimMode = (int)value;
  357. else
  358. return asINVALID_ARG;
  359. break;
  360. case asEP_MAX_NESTED_CALLS:
  361. if (value > 0xFFFFFFFF)
  362. ep.maxNestedCalls = 0xFFFFFFFF;
  363. else
  364. ep.maxNestedCalls = (asUINT)value;
  365. break;
  366. case asEP_GENERIC_CALL_MODE:
  367. if (value > 1)
  368. ep.genericCallMode = 1;
  369. else
  370. ep.genericCallMode = (asUINT)value;
  371. break;
  372. case asEP_INIT_CALL_STACK_SIZE:
  373. ep.initCallStackSize = (asUINT)value;
  374. break;
  375. case asEP_MAX_CALL_STACK_SIZE:
  376. ep.maxCallStackSize = (asUINT)value;
  377. break;
  378. case asEP_IGNORE_DUPLICATE_SHARED_INTF:
  379. ep.ignoreDuplicateSharedIntf = value ? true : false;
  380. break;
  381. case asEP_NO_DEBUG_OUTPUT:
  382. ep.noDebugOutput = value ? true : false;
  383. break;
  384. default:
  385. return asINVALID_ARG;
  386. }
  387. return asSUCCESS;
  388. }
  389. // interface
  390. asPWORD asCScriptEngine::GetEngineProperty(asEEngineProp property) const
  391. {
  392. switch( property )
  393. {
  394. case asEP_ALLOW_UNSAFE_REFERENCES:
  395. return ep.allowUnsafeReferences;
  396. case asEP_OPTIMIZE_BYTECODE:
  397. return ep.optimizeByteCode;
  398. case asEP_COPY_SCRIPT_SECTIONS:
  399. return ep.copyScriptSections;
  400. case asEP_MAX_STACK_SIZE:
  401. return ep.maximumContextStackSize * 4;
  402. case asEP_INIT_STACK_SIZE:
  403. return ep.initContextStackSize * 4;
  404. case asEP_USE_CHARACTER_LITERALS:
  405. return ep.useCharacterLiterals;
  406. case asEP_ALLOW_MULTILINE_STRINGS:
  407. return ep.allowMultilineStrings;
  408. case asEP_ALLOW_IMPLICIT_HANDLE_TYPES:
  409. return ep.allowImplicitHandleTypes;
  410. case asEP_BUILD_WITHOUT_LINE_CUES:
  411. return ep.buildWithoutLineCues;
  412. case asEP_INIT_GLOBAL_VARS_AFTER_BUILD:
  413. return ep.initGlobalVarsAfterBuild;
  414. case asEP_REQUIRE_ENUM_SCOPE:
  415. return ep.requireEnumScope;
  416. case asEP_SCRIPT_SCANNER:
  417. return ep.scanner;
  418. case asEP_INCLUDE_JIT_INSTRUCTIONS:
  419. return ep.includeJitInstructions;
  420. case asEP_STRING_ENCODING:
  421. return ep.stringEncoding;
  422. case asEP_PROPERTY_ACCESSOR_MODE:
  423. return ep.propertyAccessorMode;
  424. case asEP_EXPAND_DEF_ARRAY_TO_TMPL:
  425. return ep.expandDefaultArrayToTemplate;
  426. case asEP_AUTO_GARBAGE_COLLECT:
  427. return ep.autoGarbageCollect;
  428. case asEP_DISALLOW_GLOBAL_VARS:
  429. return ep.disallowGlobalVars;
  430. case asEP_ALWAYS_IMPL_DEFAULT_CONSTRUCT:
  431. return ep.alwaysImplDefaultConstruct;
  432. case asEP_COMPILER_WARNINGS:
  433. return ep.compilerWarnings;
  434. case asEP_DISALLOW_VALUE_ASSIGN_FOR_REF_TYPE:
  435. return ep.disallowValueAssignForRefType;
  436. case asEP_ALTER_SYNTAX_NAMED_ARGS:
  437. return ep.alterSyntaxNamedArgs;
  438. case asEP_DISABLE_INTEGER_DIVISION:
  439. return ep.disableIntegerDivision;
  440. case asEP_DISALLOW_EMPTY_LIST_ELEMENTS:
  441. return ep.disallowEmptyListElements;
  442. case asEP_PRIVATE_PROP_AS_PROTECTED:
  443. return ep.privatePropAsProtected;
  444. case asEP_ALLOW_UNICODE_IDENTIFIERS:
  445. return ep.allowUnicodeIdentifiers;
  446. case asEP_HEREDOC_TRIM_MODE:
  447. return ep.heredocTrimMode;
  448. case asEP_MAX_NESTED_CALLS:
  449. return ep.maxNestedCalls;
  450. case asEP_GENERIC_CALL_MODE:
  451. return ep.genericCallMode;
  452. case asEP_INIT_CALL_STACK_SIZE:
  453. return ep.initCallStackSize;
  454. case asEP_MAX_CALL_STACK_SIZE:
  455. return ep.maxCallStackSize;
  456. case asEP_IGNORE_DUPLICATE_SHARED_INTF:
  457. return ep.ignoreDuplicateSharedIntf;
  458. case asEP_NO_DEBUG_OUTPUT:
  459. return ep.noDebugOutput;
  460. default:
  461. return 0;
  462. }
  463. UNREACHABLE_RETURN;
  464. }
  465. // interface
  466. asIScriptFunction *asCScriptEngine::CreateDelegate(asIScriptFunction *func, void *obj)
  467. {
  468. if( func == 0 || obj == 0 )
  469. return 0;
  470. // The function must be a class method
  471. asITypeInfo *type = func->GetObjectType();
  472. if( type == 0 )
  473. return 0;
  474. // The object type must allow handles
  475. if( (type->GetFlags() & asOBJ_REF) == 0 || (type->GetFlags() & (asOBJ_SCOPED | asOBJ_NOHANDLE)) )
  476. return 0;
  477. // Create the delegate the same way it would be created by the scripts
  478. return AS_NAMESPACE_QUALIFIER CreateDelegate(reinterpret_cast<asCScriptFunction*>(func), obj);
  479. }
  480. asCScriptEngine::asCScriptEngine()
  481. {
  482. asCThreadManager::Prepare(0);
  483. shuttingDown = false;
  484. inDestructor = false;
  485. // Engine properties
  486. {
  487. ep.allowUnsafeReferences = false;
  488. ep.optimizeByteCode = true;
  489. ep.copyScriptSections = true;
  490. ep.maximumContextStackSize = 0; // no limit
  491. ep.initContextStackSize = 1024; // 4KB default init stack size
  492. ep.useCharacterLiterals = false;
  493. ep.allowMultilineStrings = false;
  494. ep.allowImplicitHandleTypes = false;
  495. // TODO: optimize: Maybe this should be turned off by default? If a debugger is not used
  496. // then this is just slowing down the execution.
  497. ep.buildWithoutLineCues = false;
  498. ep.initGlobalVarsAfterBuild = true;
  499. ep.requireEnumScope = false;
  500. ep.scanner = 1; // utf8. 0 = ascii
  501. ep.includeJitInstructions = false;
  502. ep.stringEncoding = 0; // utf8. 1 = utf16
  503. ep.propertyAccessorMode = 3; // 0 = disable, 1 = app registered only, 2 = app and script created, 3 = flag with 'property'
  504. ep.expandDefaultArrayToTemplate = false;
  505. ep.autoGarbageCollect = true;
  506. ep.disallowGlobalVars = false;
  507. ep.alwaysImplDefaultConstruct = false;
  508. ep.compilerWarnings = 1; // 0 = no warnings, 1 = warning, 2 = treat as error
  509. // TODO: 3.0.0: disallowValueAssignForRefType should be true by default
  510. ep.disallowValueAssignForRefType = false;
  511. ep.alterSyntaxNamedArgs = 0; // 0 = no alternate syntax, 1 = accept alternate syntax but warn, 2 = accept without warning
  512. ep.disableIntegerDivision = false;
  513. ep.disallowEmptyListElements = false;
  514. ep.privatePropAsProtected = false;
  515. ep.allowUnicodeIdentifiers = false;
  516. ep.heredocTrimMode = 1; // 0 = never trim, 1 = don't trim on single line, 2 = trim initial and final empty line
  517. ep.maxNestedCalls = 100;
  518. ep.genericCallMode = 1; // 0 = old (pre 2.33.0) behavior where generic ignored auto handles, 1 = treat handles like in native call
  519. ep.initCallStackSize = 10; // 10 levels of calls
  520. ep.maxCallStackSize = 0; // 0 = no limit
  521. ep.ignoreDuplicateSharedIntf = false;
  522. ep.noDebugOutput = false;
  523. }
  524. gc.engine = this;
  525. tok.engine = this;
  526. refCount.set(1);
  527. stringFactory = 0;
  528. configFailed = false;
  529. isPrepared = false;
  530. isBuilding = false;
  531. deferValidationOfTemplateTypes = false;
  532. lastModule = 0;
  533. typeIdSeqNbr = 0;
  534. currentGroup = &defaultGroup;
  535. defaultAccessMask = 0xFFFFFFFF; // All bits set so that built-in functions/types will be available to all modules
  536. msgCallback = 0;
  537. jitCompiler = 0;
  538. // Create the global namespace
  539. defaultNamespace = AddNameSpace("");
  540. requestCtxFunc = 0;
  541. returnCtxFunc = 0;
  542. ctxCallbackParam = 0;
  543. // We must set the namespace in the built-in types explicitly as
  544. // this wasn't done by the default constructor. If we do not do
  545. // this we will get null pointer access in other parts of the code
  546. scriptTypeBehaviours.nameSpace = defaultNamespace;
  547. functionBehaviours.nameSpace = defaultNamespace;
  548. // Reserve function id 0 for no function
  549. scriptFunctions.PushLast(0);
  550. // Reserve the first typeIds for the primitive types
  551. typeIdSeqNbr = asTYPEID_DOUBLE + 1;
  552. // Make sure typeId for the built-in primitives are defined according to asETypeIdFlags
  553. asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttVoid, false)) == asTYPEID_VOID );
  554. asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttBool, false)) == asTYPEID_BOOL );
  555. asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttInt8, false)) == asTYPEID_INT8 );
  556. asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttInt16, false)) == asTYPEID_INT16 );
  557. asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttInt, false)) == asTYPEID_INT32 );
  558. asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttInt64, false)) == asTYPEID_INT64 );
  559. asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttUInt8, false)) == asTYPEID_UINT8 );
  560. asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttUInt16, false)) == asTYPEID_UINT16 );
  561. asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttUInt, false)) == asTYPEID_UINT32 );
  562. asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttUInt64, false)) == asTYPEID_UINT64 );
  563. asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttFloat, false)) == asTYPEID_FLOAT );
  564. asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttDouble, false)) == asTYPEID_DOUBLE );
  565. defaultArrayObjectType = 0;
  566. RegisterScriptObject(this);
  567. RegisterScriptFunction(this);
  568. #ifndef AS_NO_EXCEPTIONS
  569. translateExceptionCallback = false;
  570. #endif
  571. }
  572. void asCScriptEngine::DeleteDiscardedModules()
  573. {
  574. // TODO: redesign: Prevent more than one thread from entering this function at the same time.
  575. // If a thread is already doing the work for the clean-up the other thread should
  576. // simply return, as the first thread will continue.
  577. ACQUIRESHARED(engineRWLock);
  578. asUINT maxCount = discardedModules.GetLength();
  579. RELEASESHARED(engineRWLock);
  580. for( asUINT n = 0; n < maxCount; n++ )
  581. {
  582. ACQUIRESHARED(engineRWLock);
  583. asCModule *mod = discardedModules[n];
  584. RELEASESHARED(engineRWLock);
  585. if( !mod->HasExternalReferences(shuttingDown) )
  586. {
  587. asDELETE(mod, asCModule);
  588. n--;
  589. }
  590. ACQUIRESHARED(engineRWLock);
  591. // Determine the max count again, since another module may have been discarded during the processing
  592. maxCount = discardedModules.GetLength();
  593. RELEASESHARED(engineRWLock);
  594. }
  595. // Go over the list of global properties, to see if it is possible to clean
  596. // up some variables that are no longer referred to by any functions
  597. for( asUINT n = 0; n < globalProperties.GetLength(); n++ )
  598. {
  599. asCGlobalProperty *prop = globalProperties[n];
  600. if( prop && prop->refCount.get() == 1 )
  601. RemoveGlobalProperty(prop);
  602. }
  603. }
  604. asCScriptEngine::~asCScriptEngine()
  605. {
  606. // TODO: clean-up: Clean up redundant code
  607. inDestructor = true;
  608. asASSERT(refCount.get() == 0);
  609. // If ShutDown hasn't been called yet do it now
  610. if( !shuttingDown )
  611. {
  612. AddRef();
  613. ShutDownAndRelease();
  614. }
  615. // Unravel the registered interface
  616. if( defaultArrayObjectType )
  617. {
  618. defaultArrayObjectType->ReleaseInternal();
  619. defaultArrayObjectType = 0;
  620. }
  621. // Delete the functions for generated template types that may references object types
  622. for( asUINT n = 0; n < generatedTemplateTypes.GetLength(); n++ )
  623. {
  624. asCObjectType *templateType = generatedTemplateTypes[n];
  625. if( templateType )
  626. templateType->DestroyInternal();
  627. }
  628. for( asUINT n = 0; n < listPatternTypes.GetLength(); n++ )
  629. {
  630. asCObjectType *type = listPatternTypes[n];
  631. if( type )
  632. type->ReleaseInternal();
  633. }
  634. listPatternTypes.SetLength(0);
  635. // No script types must have survived
  636. asASSERT( sharedScriptTypes.GetLength() == 0 );
  637. // It is allowed to create new references to the engine temporarily while destroying objects
  638. // but these references must be release immediately or else something is can go wrong later on
  639. if( refCount.get() > 0 )
  640. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ENGINE_REF_COUNT_ERROR_DURING_SHUTDOWN);
  641. mapTypeIdToTypeInfo.EraseAll();
  642. // First remove what is not used, so that other groups can be deleted safely
  643. defaultGroup.RemoveConfiguration(this, true);
  644. while( configGroups.GetLength() )
  645. {
  646. // Delete config groups in the right order
  647. asCConfigGroup *grp = configGroups.PopLast();
  648. if( grp )
  649. {
  650. grp->RemoveConfiguration(this);
  651. asDELETE(grp,asCConfigGroup);
  652. }
  653. }
  654. // Remove what is remaining
  655. defaultGroup.RemoveConfiguration(this);
  656. // Any remaining objects in templateInstanceTypes is from generated template instances
  657. for( asUINT n = 0; n < templateInstanceTypes.GetLength(); n++ )
  658. {
  659. asCObjectType *templateType = templateInstanceTypes[n];
  660. if( templateInstanceTypes[n] )
  661. templateType->ReleaseInternal();
  662. }
  663. templateInstanceTypes.SetLength(0);
  664. asCSymbolTable<asCGlobalProperty>::iterator it = registeredGlobalProps.List();
  665. for( ; it; it++ )
  666. {
  667. RemoveGlobalProperty(*it);
  668. (*it)->Release();
  669. }
  670. registeredGlobalProps.Clear();
  671. for( asUINT n = 0; n < templateSubTypes.GetLength(); n++ )
  672. {
  673. if( templateSubTypes[n] )
  674. {
  675. templateSubTypes[n]->DestroyInternal();
  676. templateSubTypes[n]->ReleaseInternal();
  677. }
  678. }
  679. templateSubTypes.SetLength(0);
  680. registeredTypeDefs.SetLength(0);
  681. registeredEnums.SetLength(0);
  682. registeredObjTypes.SetLength(0);
  683. asCSymbolTable<asCScriptFunction>::iterator funcIt = registeredGlobalFuncs.List();
  684. for( ; funcIt; funcIt++ )
  685. (*funcIt)->ReleaseInternal();
  686. registeredGlobalFuncs.Clear();
  687. scriptTypeBehaviours.ReleaseAllFunctions();
  688. functionBehaviours.ReleaseAllFunctions();
  689. for( asUINT n = 0; n < scriptFunctions.GetLength(); n++ )
  690. if( scriptFunctions[n] )
  691. {
  692. scriptFunctions[n]->DestroyInternal();
  693. // Set the engine pointer to null to signal that the function is no longer part of the engine
  694. scriptFunctions[n]->engine = 0;
  695. }
  696. scriptFunctions.SetLength(0);
  697. // Increase the internal ref count for these builtin object types, so the destructor is not called incorrectly
  698. scriptTypeBehaviours.AddRefInternal();
  699. functionBehaviours.AddRefInternal();
  700. // Destroy the funcdefs
  701. // As funcdefs are shared between modules it shouldn't be a problem to keep the objects until the engine is released
  702. for( asUINT n = 0; n < funcDefs.GetLength(); n++ )
  703. if( funcDefs[n] )
  704. {
  705. funcDefs[n]->DestroyInternal();
  706. funcDefs[n]->ReleaseInternal();
  707. }
  708. funcDefs.SetLength(0);
  709. // Free the global properties
  710. for( asUINT n = 0; n < globalProperties.GetLength(); n++ )
  711. {
  712. asCGlobalProperty *prop = globalProperties[n];
  713. if( prop )
  714. {
  715. asASSERT( prop->refCount.get() == 1 );
  716. RemoveGlobalProperty(prop);
  717. }
  718. }
  719. // Free the script section names
  720. for( asUINT n = 0; n < scriptSectionNames.GetLength(); n++ )
  721. asDELETE(scriptSectionNames[n],asCString);
  722. scriptSectionNames.SetLength(0);
  723. // Clean the user data
  724. for( asUINT n = 0; n < userData.GetLength(); n += 2 )
  725. {
  726. if( userData[n+1] )
  727. {
  728. for( asUINT c = 0; c < cleanEngineFuncs.GetLength(); c++ )
  729. if( cleanEngineFuncs[c].type == userData[n] )
  730. cleanEngineFuncs[c].cleanFunc(this);
  731. }
  732. }
  733. // Free namespaces
  734. for( asUINT n = 0; n < nameSpaces.GetLength(); n++ )
  735. asDELETE(nameSpaces[n], asSNameSpace);
  736. nameSpaces.SetLength(0);
  737. asCThreadManager::Unprepare();
  738. }
  739. // interface
  740. int asCScriptEngine::SetContextCallbacks(asREQUESTCONTEXTFUNC_t requestCtx, asRETURNCONTEXTFUNC_t returnCtx, void *param)
  741. {
  742. // Both callbacks or neither must be set
  743. if( (requestCtx == 0 && returnCtx != 0) || (requestCtx != 0 && returnCtx == 0) )
  744. return asINVALID_ARG;
  745. requestCtxFunc = requestCtx;
  746. returnCtxFunc = returnCtx;
  747. ctxCallbackParam = param;
  748. return 0;
  749. }
  750. // interface
  751. asIScriptContext *asCScriptEngine::RequestContext()
  752. {
  753. if( requestCtxFunc )
  754. {
  755. // The return callback must also exist
  756. asASSERT( returnCtxFunc );
  757. asIScriptContext *ctx = requestCtxFunc(this, ctxCallbackParam);
  758. return ctx;
  759. }
  760. // As fallback we create a new context
  761. return CreateContext();
  762. }
  763. // internal
  764. asCModule *asCScriptEngine::FindNewOwnerForSharedType(asCTypeInfo *in_type, asCModule *in_mod)
  765. {
  766. asASSERT( in_type->IsShared() );
  767. if( in_type->module != in_mod)
  768. return in_type->module;
  769. for( asUINT n = 0; n < scriptModules.GetLength(); n++ )
  770. {
  771. // TODO: optimize: If the modules already stored the shared types separately, this would be quicker
  772. int foundIdx = -1;
  773. asCModule *mod = scriptModules[n];
  774. if( mod == in_type->module ) continue;
  775. if( in_type->flags & asOBJ_ENUM )
  776. foundIdx = mod->m_enumTypes.IndexOf(CastToEnumType(in_type));
  777. else if (in_type->flags & asOBJ_TYPEDEF)
  778. foundIdx = mod->m_typeDefs.IndexOf(CastToTypedefType(in_type));
  779. else if (in_type->flags & asOBJ_FUNCDEF)
  780. foundIdx = mod->m_funcDefs.IndexOf(CastToFuncdefType(in_type));
  781. else if (in_type->flags & asOBJ_TEMPLATE)
  782. foundIdx = mod->m_templateInstances.IndexOf(CastToObjectType(in_type));
  783. else
  784. foundIdx = mod->m_classTypes.IndexOf(CastToObjectType(in_type));
  785. if( foundIdx >= 0 )
  786. {
  787. in_type->module = mod;
  788. break;
  789. }
  790. }
  791. return in_type->module;
  792. }
  793. // internal
  794. asCModule *asCScriptEngine::FindNewOwnerForSharedFunc(asCScriptFunction *in_func, asCModule *in_mod)
  795. {
  796. asASSERT( in_func->IsShared() );
  797. asASSERT(!(in_func->funcType & asFUNC_FUNCDEF));
  798. if( in_func->module != in_mod)
  799. return in_func->module;
  800. // Check if this is a class method or class factory for a type that has already been moved to a different module
  801. if ((in_func->objectType && in_func->objectType->module && in_func->objectType->module != in_func->module) ||
  802. (in_func->IsFactory() && in_func->returnType.GetTypeInfo()->module && in_func->returnType.GetTypeInfo()->module != in_func->module))
  803. {
  804. // The object type for the method has already been transferred to
  805. // another module, so transfer the method to the same module
  806. if (in_func->objectType)
  807. in_func->module = in_func->objectType->module;
  808. else
  809. in_func->module = in_func->returnType.GetTypeInfo()->module;
  810. // Make sure the function is listed in the module
  811. // The compiler may not have done this earlier, since the object
  812. // type is shared and originally compiled from another module
  813. if (in_func->module->m_scriptFunctions.IndexOf(in_func) < 0)
  814. {
  815. in_func->module->m_scriptFunctions.PushLast(in_func);
  816. in_func->AddRefInternal();
  817. }
  818. }
  819. for( asUINT n = 0; n < scriptModules.GetLength(); n++ )
  820. {
  821. // TODO: optimize: If the modules already stored the shared types separately, this would be quicker
  822. int foundIdx = -1;
  823. asCModule *mod = scriptModules[n];
  824. if( mod == in_func->module ) continue;
  825. foundIdx = mod->m_scriptFunctions.IndexOf(in_func);
  826. if( foundIdx >= 0 )
  827. {
  828. in_func->module = mod;
  829. break;
  830. }
  831. }
  832. return in_func->module;
  833. }
  834. // interface
  835. void asCScriptEngine::ReturnContext(asIScriptContext *ctx)
  836. {
  837. if( returnCtxFunc )
  838. {
  839. returnCtxFunc(this, ctx, ctxCallbackParam);
  840. return;
  841. }
  842. // As fallback we just release the context
  843. if( ctx )
  844. ctx->Release();
  845. }
  846. // interface
  847. int asCScriptEngine::AddRef() const
  848. {
  849. asASSERT( refCount.get() > 0 || inDestructor );
  850. return refCount.atomicInc();
  851. }
  852. // interface
  853. int asCScriptEngine::Release() const
  854. {
  855. int r = refCount.atomicDec();
  856. if( r == 0 )
  857. {
  858. // It is possible that some function will temporarily increment the engine ref count
  859. // during clean-up for example while destroying the objects in the garbage collector.
  860. if( !inDestructor )
  861. asDELETE(const_cast<asCScriptEngine*>(this),asCScriptEngine);
  862. return 0;
  863. }
  864. return r;
  865. }
  866. // interface
  867. int asCScriptEngine::ShutDownAndRelease()
  868. {
  869. // Do a full garbage collection cycle to clean up any object that may still hold on to the engine
  870. GarbageCollect();
  871. // Set the flag that the engine is being shutdown now. This will speed up
  872. // the process, and will also allow the engine to warn about invalid calls
  873. shuttingDown = true;
  874. // Clear the context callbacks. If new context's are needed for the clean-up the engine will take care of this itself.
  875. // Context callbacks are normally used for pooling contexts, and if we allow new contexts to be created without being
  876. // immediately destroyed afterwards it means the engine's refcount will increase. This is turn may cause memory access
  877. // violations later on when the pool releases its contexts.
  878. SetContextCallbacks(0, 0, 0);
  879. // The modules must be deleted first, as they may use
  880. // object types from the config groups
  881. for( asUINT n = (asUINT)scriptModules.GetLength(); n-- > 0; )
  882. if( scriptModules[n] )
  883. scriptModules[n]->Discard();
  884. scriptModules.SetLength(0);
  885. // Do another full garbage collection to destroy the object types/functions
  886. // that may have been placed in the gc when destroying the modules
  887. GarbageCollect();
  888. // Do another sweep to delete discarded modules, that may not have
  889. // been deleted earlier due to still having external references
  890. DeleteDiscardedModules();
  891. // If the application hasn't registered GC behaviours for all types
  892. // that can form circular references with script types, then there
  893. // may still be objects in the GC.
  894. gc.ReportAndReleaseUndestroyedObjects();
  895. // Release the engine reference
  896. return Release();
  897. }
  898. // internal
  899. asSNameSpace *asCScriptEngine::AddNameSpace(const char *name)
  900. {
  901. // First check if it doesn't exist already
  902. asSNameSpace *ns = FindNameSpace(name);
  903. if( ns ) return ns;
  904. ns = asNEW(asSNameSpace);
  905. if( ns == 0 )
  906. {
  907. // Out of memory
  908. return 0;
  909. }
  910. ns->name = name;
  911. nameSpaces.PushLast(ns);
  912. return ns;
  913. }
  914. // internal
  915. asSNameSpace *asCScriptEngine::FindNameSpace(const char *name) const
  916. {
  917. // TODO: optimize: Improve linear search
  918. for( asUINT n = 0; n < nameSpaces.GetLength(); n++ )
  919. if( nameSpaces[n]->name == name )
  920. return nameSpaces[n];
  921. return 0;
  922. }
  923. // interface
  924. const char *asCScriptEngine::GetDefaultNamespace() const
  925. {
  926. return defaultNamespace->name.AddressOf();
  927. }
  928. // interface
  929. int asCScriptEngine::SetDefaultNamespace(const char *nameSpace)
  930. {
  931. if( nameSpace == 0 )
  932. return ConfigError(asINVALID_ARG, "SetDefaultNamespace", nameSpace, 0);
  933. asCString ns = nameSpace;
  934. if( ns != "" )
  935. {
  936. // Make sure the namespace is composed of alternating identifier and ::
  937. size_t pos = 0;
  938. bool expectIdentifier = true;
  939. size_t len;
  940. eTokenType t = ttIdentifier;
  941. for( ; pos < ns.GetLength(); pos += len)
  942. {
  943. t = tok.GetToken(ns.AddressOf() + pos, ns.GetLength() - pos, &len);
  944. if( (expectIdentifier && t != ttIdentifier) || (!expectIdentifier && t != ttScope) )
  945. return ConfigError(asINVALID_DECLARATION, "SetDefaultNamespace", nameSpace, 0);
  946. // Make sure parent namespaces are registred in case of nested namespaces
  947. if (expectIdentifier)
  948. AddNameSpace(ns.SubString(0, pos + len).AddressOf());
  949. expectIdentifier = !expectIdentifier;
  950. }
  951. // If the namespace ends with :: then strip it off
  952. if( t == ttScope )
  953. ns.SetLength(ns.GetLength()-2);
  954. }
  955. defaultNamespace = AddNameSpace(ns.AddressOf());
  956. return 0;
  957. }
  958. // interface
  959. void *asCScriptEngine::SetUserData(void *data, asPWORD type)
  960. {
  961. // As a thread might add a new new user data at the same time as another
  962. // it is necessary to protect both read and write access to the userData member
  963. ACQUIREEXCLUSIVE(engineRWLock);
  964. // It is not intended to store a lot of different types of userdata,
  965. // so a more complex structure like a associative map would just have
  966. // more overhead than a simple array.
  967. for( asUINT n = 0; n < userData.GetLength(); n += 2 )
  968. {
  969. if( userData[n] == type )
  970. {
  971. void *oldData = reinterpret_cast<void*>(userData[n+1]);
  972. userData[n+1] = reinterpret_cast<asPWORD>(data);
  973. RELEASEEXCLUSIVE(engineRWLock);
  974. return oldData;
  975. }
  976. }
  977. userData.PushLast(type);
  978. userData.PushLast(reinterpret_cast<asPWORD>(data));
  979. RELEASEEXCLUSIVE(engineRWLock);
  980. return 0;
  981. }
  982. // interface
  983. void *asCScriptEngine::GetUserData(asPWORD type) const
  984. {
  985. // There may be multiple threads reading, but when
  986. // setting the user data nobody must be reading.
  987. ACQUIRESHARED(engineRWLock);
  988. for( asUINT n = 0; n < userData.GetLength(); n += 2 )
  989. {
  990. if( userData[n] == type )
  991. {
  992. RELEASESHARED(engineRWLock);
  993. return reinterpret_cast<void*>(userData[n+1]);
  994. }
  995. }
  996. RELEASESHARED(engineRWLock);
  997. return 0;
  998. }
  999. // interface
  1000. int asCScriptEngine::SetMessageCallback(const asSFuncPtr &callback, void *obj, asDWORD callConv)
  1001. {
  1002. msgCallback = true;
  1003. msgCallbackObj = obj;
  1004. bool isObj = false;
  1005. if( (unsigned)callConv == asCALL_GENERIC || (unsigned)callConv == asCALL_THISCALL_OBJFIRST || (unsigned)callConv == asCALL_THISCALL_OBJLAST )
  1006. {
  1007. msgCallback = false;
  1008. return asNOT_SUPPORTED;
  1009. }
  1010. if( (unsigned)callConv >= asCALL_THISCALL )
  1011. {
  1012. isObj = true;
  1013. if( obj == 0 )
  1014. {
  1015. msgCallback = false;
  1016. return asINVALID_ARG;
  1017. }
  1018. }
  1019. int r = DetectCallingConvention(isObj, callback, callConv, 0, &msgCallbackFunc);
  1020. if( r < 0 ) msgCallback = false;
  1021. return r;
  1022. }
  1023. // interface
  1024. int asCScriptEngine::ClearMessageCallback()
  1025. {
  1026. msgCallback = false;
  1027. return 0;
  1028. }
  1029. // interface
  1030. int asCScriptEngine::WriteMessage(const char *section, int row, int col, asEMsgType type, const char *message)
  1031. {
  1032. // Validate input parameters
  1033. if( section == 0 ||
  1034. message == 0 )
  1035. return asINVALID_ARG;
  1036. // If there is no callback then there's nothing to do
  1037. if( !msgCallback )
  1038. return 0;
  1039. // If a pre-message has been set, then write that first
  1040. if( preMessage.isSet )
  1041. {
  1042. asSMessageInfo msg;
  1043. msg.section = preMessage.scriptname.AddressOf();
  1044. msg.row = preMessage.r;
  1045. msg.col = preMessage.c;
  1046. msg.type = asMSGTYPE_INFORMATION;
  1047. msg.message = preMessage.message.AddressOf();
  1048. if( msgCallbackFunc.callConv < ICC_THISCALL )
  1049. CallGlobalFunction(&msg, msgCallbackObj, &msgCallbackFunc, 0);
  1050. else
  1051. CallObjectMethod(msgCallbackObj, &msg, &msgCallbackFunc, 0);
  1052. preMessage.isSet = false;
  1053. }
  1054. // Write the message to the callback
  1055. asSMessageInfo msg;
  1056. msg.section = section;
  1057. msg.row = row;
  1058. msg.col = col;
  1059. msg.type = type;
  1060. msg.message = message;
  1061. if( msgCallbackFunc.callConv < ICC_THISCALL )
  1062. CallGlobalFunction(&msg, msgCallbackObj, &msgCallbackFunc, 0);
  1063. else
  1064. CallObjectMethod(msgCallbackObj, &msg, &msgCallbackFunc, 0);
  1065. return 0;
  1066. }
  1067. int asCScriptEngine::SetJITCompiler(asIJITCompiler *compiler)
  1068. {
  1069. jitCompiler = compiler;
  1070. return asSUCCESS;
  1071. }
  1072. asIJITCompiler *asCScriptEngine::GetJITCompiler() const
  1073. {
  1074. return jitCompiler;
  1075. }
  1076. // interface
  1077. asETokenClass asCScriptEngine::ParseToken(const char *string, size_t stringLength, asUINT *tokenLength) const
  1078. {
  1079. if( stringLength == 0 )
  1080. stringLength = strlen(string);
  1081. size_t len;
  1082. asETokenClass tc;
  1083. tok.GetToken(string, stringLength, &len, &tc);
  1084. if( tokenLength )
  1085. *tokenLength = (asUINT)len;
  1086. return tc;
  1087. }
  1088. // interface
  1089. asIScriptModule *asCScriptEngine::GetModule(const char *module, asEGMFlags flag)
  1090. {
  1091. asCModule *mod = GetModule(module, false);
  1092. if( flag == asGM_ALWAYS_CREATE )
  1093. {
  1094. if( mod != 0 )
  1095. mod->Discard();
  1096. return GetModule(module, true);
  1097. }
  1098. if( mod == 0 && flag == asGM_CREATE_IF_NOT_EXISTS )
  1099. return GetModule(module, true);
  1100. return mod;
  1101. }
  1102. // interface
  1103. int asCScriptEngine::DiscardModule(const char *module)
  1104. {
  1105. asCModule *mod = GetModule(module, false);
  1106. if( mod == 0 ) return asNO_MODULE;
  1107. mod->Discard();
  1108. return 0;
  1109. }
  1110. // interface
  1111. asUINT asCScriptEngine::GetModuleCount() const
  1112. {
  1113. ACQUIRESHARED(engineRWLock);
  1114. asUINT length = asUINT(scriptModules.GetLength());
  1115. RELEASESHARED(engineRWLock);
  1116. return length;
  1117. }
  1118. // interface
  1119. asIScriptModule *asCScriptEngine::GetModuleByIndex(asUINT index) const
  1120. {
  1121. asIScriptModule *mod = 0;
  1122. ACQUIRESHARED(engineRWLock);
  1123. if( index < scriptModules.GetLength() )
  1124. mod = scriptModules[index];
  1125. RELEASESHARED(engineRWLock);
  1126. return mod;
  1127. }
  1128. // internal
  1129. int asCScriptEngine::GetFactoryIdByDecl(const asCObjectType *ot, const char *decl)
  1130. {
  1131. asCModule *mod = 0;
  1132. // Is this a script class?
  1133. if( (ot->flags & asOBJ_SCRIPT_OBJECT) && ot->size > 0 )
  1134. mod = scriptFunctions[ot->beh.factories[0]]->module;
  1135. asCBuilder bld(this, mod);
  1136. // Don't write parser errors to the message callback
  1137. bld.silent = true;
  1138. asCScriptFunction func(this, mod, asFUNC_DUMMY);
  1139. int r = bld.ParseFunctionDeclaration(0, decl, &func, false, 0, 0, defaultNamespace);
  1140. if( r < 0 )
  1141. return asINVALID_DECLARATION;
  1142. // Search for matching factory function
  1143. int id = -1;
  1144. for( asUINT n = 0; n < ot->beh.factories.GetLength(); n++ )
  1145. {
  1146. asCScriptFunction *f = scriptFunctions[ot->beh.factories[n]];
  1147. // We don't really care if the name of the function is correct
  1148. if( f->IsSignatureExceptNameEqual(&func) )
  1149. {
  1150. id = ot->beh.factories[n];
  1151. break;
  1152. }
  1153. }
  1154. if( id == -1 ) return asNO_FUNCTION;
  1155. return id;
  1156. }
  1157. // internal
  1158. int asCScriptEngine::GetMethodIdByDecl(const asCObjectType *ot, const char *decl, asCModule *mod)
  1159. {
  1160. asCBuilder bld(this, mod);
  1161. // Don't write parser errors to the message callback
  1162. bld.silent = true;
  1163. asCScriptFunction func(this, mod, asFUNC_DUMMY);
  1164. // Set the object type so that the signature can be properly compared
  1165. // This cast is OK, it will only be used for comparison
  1166. func.objectType = const_cast<asCObjectType*>(ot);
  1167. func.objectType->AddRefInternal();
  1168. int r = bld.ParseFunctionDeclaration(func.objectType, decl, &func, false);
  1169. if( r < 0 )
  1170. return asINVALID_DECLARATION;
  1171. // Search script functions for matching interface
  1172. int id = -1;
  1173. for( asUINT n = 0; n < ot->methods.GetLength(); ++n )
  1174. {
  1175. if( func.IsSignatureEqual(scriptFunctions[ot->methods[n]]) )
  1176. {
  1177. if( id == -1 )
  1178. id = ot->methods[n];
  1179. else
  1180. return asMULTIPLE_FUNCTIONS;
  1181. }
  1182. }
  1183. if( id == -1 ) return asNO_FUNCTION;
  1184. return id;
  1185. }
  1186. // internal
  1187. asCString asCScriptEngine::GetFunctionDeclaration(int funcId)
  1188. {
  1189. asCString str;
  1190. asCScriptFunction *func = GetScriptFunction(funcId);
  1191. if( func )
  1192. str = func->GetDeclarationStr();
  1193. return str;
  1194. }
  1195. // internal
  1196. asCScriptFunction *asCScriptEngine::GetScriptFunction(int funcId) const
  1197. {
  1198. if( funcId < 0 || funcId >= (int)scriptFunctions.GetLength() )
  1199. return 0;
  1200. return scriptFunctions[funcId];
  1201. }
  1202. // interface
  1203. asIScriptContext *asCScriptEngine::CreateContext()
  1204. {
  1205. asIScriptContext *ctx = 0;
  1206. CreateContext(&ctx, false);
  1207. return ctx;
  1208. }
  1209. // internal
  1210. int asCScriptEngine::CreateContext(asIScriptContext **context, bool isInternal)
  1211. {
  1212. *context = asNEW(asCContext)(this, !isInternal);
  1213. if( *context == 0 )
  1214. return asOUT_OF_MEMORY;
  1215. // We need to make sure the engine has been
  1216. // prepared before any context is executed
  1217. PrepareEngine();
  1218. return 0;
  1219. }
  1220. // interface
  1221. int asCScriptEngine::RegisterObjectProperty(const char *obj, const char *declaration, int byteOffset, int compositeOffset, bool isCompositeIndirect)
  1222. {
  1223. int r;
  1224. asCDataType dt;
  1225. asCBuilder bld(this, 0);
  1226. r = bld.ParseDataType(obj, &dt, defaultNamespace);
  1227. if( r < 0 )
  1228. return ConfigError(r, "RegisterObjectProperty", obj, declaration);
  1229. if (dt.GetTypeInfo() == 0 || (dt.IsObjectHandle() && !(dt.GetTypeInfo()->GetFlags() & asOBJ_IMPLICIT_HANDLE)))
  1230. return ConfigError(asINVALID_OBJECT, "RegisterObjectProperty", obj, declaration);
  1231. // Don't allow modifying generated template instances
  1232. if( dt.GetTypeInfo() && (dt.GetTypeInfo()->flags & asOBJ_TEMPLATE) && generatedTemplateTypes.Exists(CastToObjectType(dt.GetTypeInfo())) )
  1233. return ConfigError(asINVALID_TYPE, "RegisterObjectProperty", obj, declaration);
  1234. // Verify that the correct config group is used
  1235. if( currentGroup->FindType(dt.GetTypeInfo()->name.AddressOf()) == 0 )
  1236. return ConfigError(asWRONG_CONFIG_GROUP, "RegisterObjectProperty", obj, declaration);
  1237. asCDataType type;
  1238. asCString name;
  1239. if( (r = bld.VerifyProperty(&dt, declaration, name, type, 0)) < 0 )
  1240. return ConfigError(r, "RegisterObjectProperty", obj, declaration);
  1241. // The VM currently only supports 16bit offsets
  1242. // TODO: The VM needs to have support for 32bit offsets. Probably with a second ADDSi instruction
  1243. // However, when implementing this it is necessary for the bytecode serialization to support
  1244. // the switch between the instructions upon loading bytecode as the offset may not be the
  1245. // same on all platforms
  1246. if( byteOffset > 32767 || byteOffset < -32768 )
  1247. return ConfigError(asINVALID_ARG, "RegisterObjectProperty", obj, declaration);
  1248. // The composite offset must also obey the ADDSi restriction
  1249. if (compositeOffset > 32767 || compositeOffset < -32768)
  1250. return ConfigError(asINVALID_ARG, "RegisterObjectProperty", obj, declaration);
  1251. asCObjectProperty *prop = asNEW(asCObjectProperty);
  1252. if( prop == 0 )
  1253. return ConfigError(asOUT_OF_MEMORY, "RegisterObjectProperty", obj, declaration);
  1254. prop->name = name;
  1255. prop->type = type;
  1256. prop->byteOffset = byteOffset;
  1257. prop->isPrivate = false;
  1258. prop->isProtected = false;
  1259. prop->compositeOffset = compositeOffset;
  1260. prop->isCompositeIndirect = isCompositeIndirect;
  1261. prop->accessMask = defaultAccessMask;
  1262. asCObjectType *ot = CastToObjectType(dt.GetTypeInfo());
  1263. asUINT idx = ot->properties.GetLength();
  1264. ot->properties.PushLast(prop);
  1265. // Add references to types so they are not released too early
  1266. if( type.GetTypeInfo() )
  1267. {
  1268. type.GetTypeInfo()->AddRefInternal();
  1269. // Add template instances to the config group
  1270. if( (type.GetTypeInfo()->flags & asOBJ_TEMPLATE) && !currentGroup->types.Exists(type.GetTypeInfo()) )
  1271. currentGroup->types.PushLast(type.GetTypeInfo());
  1272. }
  1273. currentGroup->AddReferencesForType(this, type.GetTypeInfo());
  1274. // Return the index of the property to signal success
  1275. return idx;
  1276. }
  1277. // interface
  1278. int asCScriptEngine::RegisterInterface(const char *name)
  1279. {
  1280. if( name == 0 ) return ConfigError(asINVALID_NAME, "RegisterInterface", 0, 0);
  1281. // Verify if the name has been registered as a type already
  1282. if( GetRegisteredType(name, defaultNamespace) )
  1283. return asALREADY_REGISTERED;
  1284. // Use builder to parse the datatype
  1285. asCDataType dt;
  1286. asCBuilder bld(this, 0);
  1287. bool oldMsgCallback = msgCallback; msgCallback = false;
  1288. int r = bld.ParseDataType(name, &dt, defaultNamespace);
  1289. msgCallback = oldMsgCallback;
  1290. if( r >= 0 )
  1291. {
  1292. // If it is not in the defaultNamespace then the type was successfully parsed because
  1293. // it is declared in a parent namespace which shouldn't be treated as an error
  1294. if( dt.GetTypeInfo() && dt.GetTypeInfo()->nameSpace == defaultNamespace )
  1295. return ConfigError(asERROR, "RegisterInterface", name, 0);
  1296. }
  1297. // Make sure the name is not a reserved keyword
  1298. size_t tokenLen;
  1299. int token = tok.GetToken(name, strlen(name), &tokenLen);
  1300. if( token != ttIdentifier || strlen(name) != tokenLen )
  1301. return ConfigError(asINVALID_NAME, "RegisterInterface", name, 0);
  1302. r = bld.CheckNameConflict(name, 0, 0, defaultNamespace, true, false, false);
  1303. if( r < 0 )
  1304. return ConfigError(asNAME_TAKEN, "RegisterInterface", name, 0);
  1305. // Don't have to check against members of object
  1306. // types as they are allowed to use the names
  1307. // Register the object type for the interface
  1308. asCObjectType *st = asNEW(asCObjectType)(this);
  1309. if( st == 0 )
  1310. return ConfigError(asOUT_OF_MEMORY, "RegisterInterface", name, 0);
  1311. st->flags = asOBJ_REF | asOBJ_SCRIPT_OBJECT | asOBJ_SHARED;
  1312. st->size = 0; // Cannot be instantiated
  1313. st->name = name;
  1314. st->nameSpace = defaultNamespace;
  1315. // Use the default script class behaviours
  1316. st->beh.factory = 0;
  1317. st->beh.addref = scriptTypeBehaviours.beh.addref;
  1318. scriptFunctions[st->beh.addref]->AddRefInternal();
  1319. st->beh.release = scriptTypeBehaviours.beh.release;
  1320. scriptFunctions[st->beh.release]->AddRefInternal();
  1321. st->beh.copy = 0;
  1322. allRegisteredTypes.Insert(asSNameSpaceNamePair(st->nameSpace, st->name), st);
  1323. registeredObjTypes.PushLast(st);
  1324. currentGroup->types.PushLast(st);
  1325. return GetTypeIdByDecl(name);
  1326. }
  1327. // interface
  1328. int asCScriptEngine::RegisterInterfaceMethod(const char *intf, const char *declaration)
  1329. {
  1330. // Verify that the correct config group is set.
  1331. if( currentGroup->FindType(intf) == 0 )
  1332. return ConfigError(asWRONG_CONFIG_GROUP, "RegisterInterfaceMethod", intf, declaration);
  1333. asCDataType dt;
  1334. asCBuilder bld(this, 0);
  1335. int r = bld.ParseDataType(intf, &dt, defaultNamespace);
  1336. if( r < 0 )
  1337. return ConfigError(r, "RegisterInterfaceMethod", intf, declaration);
  1338. asCScriptFunction *func = asNEW(asCScriptFunction)(this, 0, asFUNC_INTERFACE);
  1339. if( func == 0 )
  1340. return ConfigError(asOUT_OF_MEMORY, "RegisterInterfaceMethod", intf, declaration);
  1341. func->objectType = CastToObjectType(dt.GetTypeInfo());
  1342. func->objectType->AddRefInternal();
  1343. r = bld.ParseFunctionDeclaration(func->objectType, declaration, func, false);
  1344. if( r < 0 )
  1345. {
  1346. func->funcType = asFUNC_DUMMY;
  1347. asDELETE(func,asCScriptFunction);
  1348. return ConfigError(asINVALID_DECLARATION, "RegisterInterfaceMethod", intf, declaration);
  1349. }
  1350. // Check name conflicts
  1351. r = bld.CheckNameConflictMember(dt.GetTypeInfo(), func->name.AddressOf(), 0, 0, false, false);
  1352. if( r < 0 )
  1353. {
  1354. func->funcType = asFUNC_DUMMY;
  1355. asDELETE(func,asCScriptFunction);
  1356. return ConfigError(asNAME_TAKEN, "RegisterInterfaceMethod", intf, declaration);
  1357. }
  1358. func->id = GetNextScriptFunctionId();
  1359. AddScriptFunction(func);
  1360. // The index into the interface's vftable chunk should be
  1361. // its index in the methods array.
  1362. func->vfTableIdx = int(func->objectType->methods.GetLength());
  1363. func->objectType->methods.PushLast(func->id);
  1364. func->ComputeSignatureId();
  1365. currentGroup->AddReferencesForFunc(this, func);
  1366. // Return function id as success
  1367. return func->id;
  1368. }
  1369. int asCScriptEngine::RegisterObjectType(const char *name, int byteSize, asDWORD flags)
  1370. {
  1371. int r;
  1372. isPrepared = false;
  1373. // Verify flags
  1374. // Must have either asOBJ_REF or asOBJ_VALUE
  1375. if( flags & asOBJ_REF )
  1376. {
  1377. // Can optionally have the asOBJ_GC, asOBJ_NOHANDLE, asOBJ_SCOPED, or asOBJ_TEMPLATE flag set, but nothing else
  1378. if( flags & ~(asOBJ_REF | asOBJ_GC | asOBJ_NOHANDLE | asOBJ_SCOPED | asOBJ_TEMPLATE | asOBJ_NOCOUNT | asOBJ_IMPLICIT_HANDLE) )
  1379. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1380. // flags are exclusive
  1381. if( (flags & asOBJ_GC) && (flags & (asOBJ_NOHANDLE|asOBJ_SCOPED|asOBJ_NOCOUNT)) )
  1382. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1383. if( (flags & asOBJ_NOHANDLE) && (flags & (asOBJ_GC|asOBJ_SCOPED|asOBJ_NOCOUNT|asOBJ_IMPLICIT_HANDLE)) )
  1384. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1385. if( (flags & asOBJ_SCOPED) && (flags & (asOBJ_GC|asOBJ_NOHANDLE|asOBJ_NOCOUNT|asOBJ_IMPLICIT_HANDLE)) )
  1386. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1387. if( (flags & asOBJ_NOCOUNT) && (flags & (asOBJ_GC|asOBJ_NOHANDLE|asOBJ_SCOPED)) )
  1388. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1389. // Implicit handle is only allowed if the engine property for this is turned on
  1390. if( !ep.allowImplicitHandleTypes && (flags & asOBJ_IMPLICIT_HANDLE) )
  1391. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1392. }
  1393. else if( flags & asOBJ_VALUE )
  1394. {
  1395. // Cannot use reference flags
  1396. if( flags & (asOBJ_REF | asOBJ_NOHANDLE | asOBJ_SCOPED | asOBJ_NOCOUNT | asOBJ_IMPLICIT_HANDLE) )
  1397. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1398. // Flags are exclusive
  1399. if( (flags & asOBJ_POD) && (flags & (asOBJ_ASHANDLE | asOBJ_TEMPLATE)) )
  1400. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1401. // If the app type is given, we must validate the flags
  1402. if( flags & asOBJ_APP_CLASS )
  1403. {
  1404. // Must not set the primitive or float flag
  1405. if( flags & (asOBJ_APP_PRIMITIVE | asOBJ_APP_FLOAT | asOBJ_APP_ARRAY) )
  1406. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1407. }
  1408. else
  1409. {
  1410. // Must not set the class properties, without the class flag
  1411. if( flags & (asOBJ_APP_CLASS_CONSTRUCTOR |
  1412. asOBJ_APP_CLASS_DESTRUCTOR |
  1413. asOBJ_APP_CLASS_ASSIGNMENT |
  1414. asOBJ_APP_CLASS_COPY_CONSTRUCTOR |
  1415. asOBJ_APP_CLASS_ALLINTS |
  1416. asOBJ_APP_CLASS_ALLFLOATS) )
  1417. {
  1418. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1419. }
  1420. }
  1421. if( flags & asOBJ_APP_PRIMITIVE )
  1422. {
  1423. if( flags & (asOBJ_APP_CLASS |
  1424. asOBJ_APP_FLOAT |
  1425. asOBJ_APP_ARRAY) )
  1426. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1427. }
  1428. else if( flags & asOBJ_APP_FLOAT )
  1429. {
  1430. if( flags & (asOBJ_APP_CLASS |
  1431. asOBJ_APP_PRIMITIVE |
  1432. asOBJ_APP_ARRAY) )
  1433. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1434. }
  1435. else if( flags & asOBJ_APP_ARRAY )
  1436. {
  1437. if( flags & (asOBJ_APP_CLASS |
  1438. asOBJ_APP_PRIMITIVE |
  1439. asOBJ_APP_FLOAT) )
  1440. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1441. }
  1442. }
  1443. else
  1444. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1445. // Don't allow anything else than the defined flags
  1446. #ifndef WIP_16BYTE_ALIGN
  1447. if( flags - (flags & asOBJ_MASK_VALID_FLAGS) )
  1448. #else
  1449. if( flags - (flags & (asOBJ_MASK_VALID_FLAGS | asOBJ_APP_ALIGN16)) )
  1450. #endif
  1451. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1452. // Value types must have a defined size
  1453. if( (flags & asOBJ_VALUE) && byteSize == 0 )
  1454. {
  1455. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_VALUE_TYPE_MUST_HAVE_SIZE);
  1456. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1457. }
  1458. // Verify type name
  1459. if( name == 0 )
  1460. return ConfigError(asINVALID_NAME, "RegisterObjectType", name, 0);
  1461. asCString typeName;
  1462. asCBuilder bld(this, 0);
  1463. if( flags & asOBJ_TEMPLATE )
  1464. {
  1465. asCArray<asCString> subtypeNames;
  1466. r = bld.ParseTemplateDecl(name, &typeName, subtypeNames);
  1467. if( r < 0 )
  1468. return ConfigError(r, "RegisterObjectType", name, 0);
  1469. // Verify that the template name hasn't been registered as a type already
  1470. if( GetRegisteredType(typeName, defaultNamespace) )
  1471. // This is not an irrepairable error, as it may just be that the same type is registered twice
  1472. return asALREADY_REGISTERED;
  1473. asCObjectType *type = asNEW(asCObjectType)(this);
  1474. if( type == 0 )
  1475. return ConfigError(asOUT_OF_MEMORY, "RegisterObjectType", name, 0);
  1476. type->name = typeName;
  1477. type->nameSpace = defaultNamespace;
  1478. type->size = byteSize;
  1479. #ifdef WIP_16BYTE_ALIGN
  1480. // TODO: Types smaller than 4 don't need to be aligned to 4 byte boundaries
  1481. type->alignment = (flags & asOBJ_APP_ALIGN16) ? 16 : 4;
  1482. #endif
  1483. type->flags = flags;
  1484. type->accessMask = defaultAccessMask;
  1485. // Store it in the object types
  1486. allRegisteredTypes.Insert(asSNameSpaceNamePair(type->nameSpace, type->name), type);
  1487. currentGroup->types.PushLast(type);
  1488. registeredObjTypes.PushLast(type);
  1489. registeredTemplateTypes.PushLast(type);
  1490. // Define the template subtypes
  1491. for( asUINT subTypeIdx = 0; subTypeIdx < subtypeNames.GetLength(); subTypeIdx++ )
  1492. {
  1493. asCTypeInfo *subtype = 0;
  1494. for( asUINT n = 0; n < templateSubTypes.GetLength(); n++ )
  1495. {
  1496. if( templateSubTypes[n]->name == subtypeNames[subTypeIdx] )
  1497. {
  1498. subtype = templateSubTypes[n];
  1499. break;
  1500. }
  1501. }
  1502. if( subtype == 0 )
  1503. {
  1504. // Create the new subtype if not already existing
  1505. subtype = asNEW(asCTypeInfo)(this);
  1506. if( subtype == 0 )
  1507. return ConfigError(asOUT_OF_MEMORY, "RegisterObjectType", name, 0);
  1508. subtype->name = subtypeNames[subTypeIdx];
  1509. subtype->size = 0;
  1510. subtype->flags = asOBJ_TEMPLATE_SUBTYPE;
  1511. templateSubTypes.PushLast(subtype);
  1512. }
  1513. type->templateSubTypes.PushLast(asCDataType::CreateType(subtype, false));
  1514. subtype->AddRefInternal();
  1515. }
  1516. }
  1517. else
  1518. {
  1519. typeName = name;
  1520. // Verify if the name has been registered as a type already
  1521. if( GetRegisteredType(typeName, defaultNamespace) )
  1522. // This is not an irrepairable error, as it may just be that the same type is registered twice
  1523. return asALREADY_REGISTERED;
  1524. // Keep the most recent template generated instance type, so we know what it was before parsing the datatype
  1525. asCObjectType *mostRecentTemplateInstanceType = 0;
  1526. asUINT originalSizeOfGeneratedTemplateTypes = (asUINT)generatedTemplateTypes.GetLength();
  1527. if( originalSizeOfGeneratedTemplateTypes )
  1528. mostRecentTemplateInstanceType = generatedTemplateTypes[originalSizeOfGeneratedTemplateTypes-1];
  1529. // Use builder to parse the datatype
  1530. asCDataType dt;
  1531. bool oldMsgCallback = msgCallback; msgCallback = false;
  1532. r = bld.ParseDataType(name, &dt, defaultNamespace);
  1533. msgCallback = oldMsgCallback;
  1534. // If the builder fails or the namespace is different than the default
  1535. // namespace, then the type name is new and it should be registered
  1536. if( r < 0 || dt.GetTypeInfo()->nameSpace != defaultNamespace )
  1537. {
  1538. // Make sure the name is not a reserved keyword
  1539. size_t tokenLen;
  1540. int token = tok.GetToken(name, typeName.GetLength(), &tokenLen);
  1541. if( token != ttIdentifier || typeName.GetLength() != tokenLen )
  1542. return ConfigError(asINVALID_NAME, "RegisterObjectType", name, 0);
  1543. r = bld.CheckNameConflict(name, 0, 0, defaultNamespace, true, false, false);
  1544. if( r < 0 )
  1545. return ConfigError(asNAME_TAKEN, "RegisterObjectType", name, 0);
  1546. // Don't have to check against members of object
  1547. // types as they are allowed to use the names
  1548. // Put the data type in the list
  1549. asCObjectType *type = asNEW(asCObjectType)(this);
  1550. if( type == 0 )
  1551. return ConfigError(asOUT_OF_MEMORY, "RegisterObjectType", name, 0);
  1552. type->name = typeName;
  1553. type->nameSpace = defaultNamespace;
  1554. type->size = byteSize;
  1555. #ifdef WIP_16BYTE_ALIGN
  1556. // TODO: Types smaller than 4 don't need to be aligned to 4 byte boundaries
  1557. type->alignment = (flags & asOBJ_APP_ALIGN16) ? 16 : 4;
  1558. #endif
  1559. type->flags = flags;
  1560. type->accessMask = defaultAccessMask;
  1561. allRegisteredTypes.Insert(asSNameSpaceNamePair(type->nameSpace, type->name), type);
  1562. registeredObjTypes.PushLast(type);
  1563. currentGroup->types.PushLast(type);
  1564. }
  1565. else
  1566. {
  1567. // The application is registering a template specialization so we
  1568. // need to replace the template instance type with the new type.
  1569. // TODO: Template: We don't require the lower dimensions to be registered first for registered template types
  1570. // int[][] must not be allowed to be registered
  1571. // if int[] hasn't been registered first
  1572. if( dt.GetSubType().IsTemplate() )
  1573. return ConfigError(asLOWER_ARRAY_DIMENSION_NOT_REGISTERED, "RegisterObjectType", name, 0);
  1574. if( dt.IsReadOnly() ||
  1575. dt.IsReference() )
  1576. return ConfigError(asINVALID_TYPE, "RegisterObjectType", name, 0);
  1577. // Was the template instance type generated before?
  1578. if( generatedTemplateTypes.Exists(CastToObjectType(dt.GetTypeInfo())) &&
  1579. generatedTemplateTypes[generatedTemplateTypes.GetLength()-1] == mostRecentTemplateInstanceType )
  1580. {
  1581. asCString str;
  1582. str.Format(TXT_TEMPLATE_s_ALREADY_GENERATED_CANT_REGISTER, typeName.AddressOf());
  1583. WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  1584. return ConfigError(asNOT_SUPPORTED, "RegisterObjectType", name, 0);
  1585. }
  1586. // If this is not a generated template instance type, then it means it is an
  1587. // already registered template specialization
  1588. if( !generatedTemplateTypes.Exists(CastToObjectType(dt.GetTypeInfo())) )
  1589. return ConfigError(asALREADY_REGISTERED, "RegisterObjectType", name, 0);
  1590. // TODO: Add this again. The type is used by the factory stubs so we need to discount that
  1591. // Is the template instance type already being used?
  1592. // if( dt.GetTypeInfo()->GetRefCount() > 1 )
  1593. // return ConfigError(asNOT_SUPPORTED, "RegisterObjectType", name, 0);
  1594. // Put the data type in the list
  1595. asCObjectType *type = asNEW(asCObjectType)(this);
  1596. if( type == 0 )
  1597. return ConfigError(asOUT_OF_MEMORY, "RegisterObjectType", name, 0);
  1598. type->name = dt.GetTypeInfo()->name;
  1599. // The namespace will be the same as the original template type
  1600. type->nameSpace = dt.GetTypeInfo()->nameSpace;
  1601. type->templateSubTypes.PushLast(dt.GetSubType());
  1602. for( asUINT s = 0; s < type->templateSubTypes.GetLength(); s++ )
  1603. if( type->templateSubTypes[s].GetTypeInfo() )
  1604. type->templateSubTypes[s].GetTypeInfo()->AddRefInternal();
  1605. type->size = byteSize;
  1606. #ifdef WIP_16BYTE_ALIGN
  1607. // TODO: Types smaller than 4 don't need to be aligned to 4 byte boundaries
  1608. type->alignment = (flags & asOBJ_APP_ALIGN16) ? 16 : 4;
  1609. #endif
  1610. type->flags = flags;
  1611. type->accessMask = defaultAccessMask;
  1612. templateInstanceTypes.PushLast(type);
  1613. currentGroup->types.PushLast(type);
  1614. // Remove the template instance type, which will no longer be used.
  1615. // It is possible that multiple template instances are generated if
  1616. // they have any relationship, so all of them must be removed
  1617. while( generatedTemplateTypes.GetLength() > originalSizeOfGeneratedTemplateTypes )
  1618. RemoveTemplateInstanceType(generatedTemplateTypes[generatedTemplateTypes.GetLength()-1]);
  1619. }
  1620. }
  1621. // Return the type id as the success (except for template types)
  1622. if( flags & asOBJ_TEMPLATE )
  1623. return asSUCCESS;
  1624. return GetTypeIdByDecl(name);
  1625. }
  1626. // interface
  1627. int asCScriptEngine::RegisterObjectBehaviour(const char *datatype, asEBehaviours behaviour, const char *decl, const asSFuncPtr &funcPointer, asDWORD callConv, void *auxiliary, int compositeOffset, bool isCompositeIndirect)
  1628. {
  1629. if( datatype == 0 ) return ConfigError(asINVALID_ARG, "RegisterObjectBehaviour", datatype, decl);
  1630. // Determine the object type
  1631. asCBuilder bld(this, 0);
  1632. asCDataType type;
  1633. int r = bld.ParseDataType(datatype, &type, defaultNamespace);
  1634. if( r < 0 )
  1635. return ConfigError(r, "RegisterObjectBehaviour", datatype, decl);
  1636. if( type.GetTypeInfo() == 0 || (type.IsObjectHandle() && !(type.GetTypeInfo()->GetFlags() & asOBJ_IMPLICIT_HANDLE)) )
  1637. return ConfigError(asINVALID_TYPE, "RegisterObjectBehaviour", datatype, decl);
  1638. // Don't allow application to modify built-in types
  1639. if( type.GetTypeInfo() == &functionBehaviours ||
  1640. type.GetTypeInfo() == &scriptTypeBehaviours )
  1641. return ConfigError(asINVALID_TYPE, "RegisterObjectBehaviour", datatype, decl);
  1642. if( type.IsReadOnly() || type.IsReference() )
  1643. return ConfigError(asINVALID_TYPE, "RegisterObjectBehaviour", datatype, decl);
  1644. // Don't allow modifying generated template instances
  1645. if( type.GetTypeInfo() && (type.GetTypeInfo()->flags & asOBJ_TEMPLATE) && generatedTemplateTypes.Exists(CastToObjectType(type.GetTypeInfo())) )
  1646. return ConfigError(asINVALID_TYPE, "RegisterObjectBehaviour", datatype, decl);
  1647. return RegisterBehaviourToObjectType(CastToObjectType(type.GetTypeInfo()), behaviour, decl, funcPointer, callConv, auxiliary, compositeOffset, isCompositeIndirect);
  1648. }
  1649. // internal
  1650. int asCScriptEngine::RegisterBehaviourToObjectType(asCObjectType *objectType, asEBehaviours behaviour, const char *decl, const asSFuncPtr &funcPointer, asDWORD callConv, void *auxiliary, int compositeOffset, bool isCompositeIndirect)
  1651. {
  1652. #ifdef AS_MAX_PORTABILITY
  1653. if( callConv != asCALL_GENERIC )
  1654. return ConfigError(asNOT_SUPPORTED, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1655. #endif
  1656. asSSystemFunctionInterface internal;
  1657. bool isMethod = !(behaviour == asBEHAVE_FACTORY ||
  1658. behaviour == asBEHAVE_LIST_FACTORY ||
  1659. behaviour == asBEHAVE_TEMPLATE_CALLBACK);
  1660. int r = DetectCallingConvention(isMethod, funcPointer, callConv, auxiliary, &internal);
  1661. if( r < 0 )
  1662. return ConfigError(r, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1663. internal.compositeOffset = compositeOffset;
  1664. internal.isCompositeIndirect = isCompositeIndirect;
  1665. if( (compositeOffset || isCompositeIndirect) && callConv != asCALL_THISCALL )
  1666. return ConfigError(asINVALID_ARG, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1667. // TODO: cleanup: This is identical to what is in RegisterMethodToObjectType
  1668. // If the object type is a template, make sure there are no generated instances already
  1669. if( objectType->flags & asOBJ_TEMPLATE )
  1670. {
  1671. for( asUINT n = 0; n < generatedTemplateTypes.GetLength(); n++ )
  1672. {
  1673. asCObjectType *tmpl = generatedTemplateTypes[n];
  1674. if( tmpl->name == objectType->name &&
  1675. tmpl->nameSpace == objectType->nameSpace &&
  1676. !(tmpl->templateSubTypes[0].GetTypeInfo() && (tmpl->templateSubTypes[0].GetTypeInfo()->flags & asOBJ_TEMPLATE_SUBTYPE)) )
  1677. {
  1678. asCString msg;
  1679. msg.Format(TXT_TEMPLATE_s_ALREADY_GENERATED_CANT_REGISTER, asCDataType::CreateType(tmpl, false).Format(tmpl->nameSpace).AddressOf());
  1680. WriteMessage("",0,0, asMSGTYPE_ERROR, msg.AddressOf());
  1681. return ConfigError(asERROR, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1682. }
  1683. }
  1684. }
  1685. isPrepared = false;
  1686. asSTypeBehaviour *beh = &objectType->beh;
  1687. // Verify function declaration
  1688. asCScriptFunction func(this, 0, asFUNC_DUMMY);
  1689. bool expectListPattern = behaviour == asBEHAVE_LIST_FACTORY || behaviour == asBEHAVE_LIST_CONSTRUCT;
  1690. asCScriptNode *listPattern = 0;
  1691. asCBuilder bld(this, 0);
  1692. r = bld.ParseFunctionDeclaration(objectType, decl, &func, true, &internal.paramAutoHandles, &internal.returnAutoHandle, 0, expectListPattern ? &listPattern : 0);
  1693. if( r < 0 )
  1694. {
  1695. if( listPattern )
  1696. listPattern->Destroy(this);
  1697. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1698. }
  1699. func.name.Format("$beh%d", behaviour);
  1700. if( behaviour != asBEHAVE_FACTORY && behaviour != asBEHAVE_LIST_FACTORY )
  1701. {
  1702. func.objectType = objectType;
  1703. func.objectType->AddRefInternal();
  1704. }
  1705. // Check if the method restricts that use of the template to value types or reference types
  1706. if( objectType->flags & asOBJ_TEMPLATE )
  1707. {
  1708. r = SetTemplateRestrictions(objectType, &func, "RegisterObjectBehaviour", decl);
  1709. if (r < 0)
  1710. return r;
  1711. }
  1712. if( behaviour == asBEHAVE_CONSTRUCT )
  1713. {
  1714. // Verify that the return type is void
  1715. if( func.returnType != asCDataType::CreatePrimitive(ttVoid, false) )
  1716. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1717. if( objectType->flags & asOBJ_SCRIPT_OBJECT )
  1718. {
  1719. // The script object is a special case
  1720. asASSERT(func.parameterTypes.GetLength() == 1);
  1721. beh->construct = AddBehaviourFunction(func, internal);
  1722. beh->factory = beh->construct;
  1723. scriptFunctions[beh->factory]->AddRefInternal();
  1724. beh->constructors.PushLast(beh->construct);
  1725. beh->factories.PushLast(beh->factory);
  1726. func.id = beh->construct;
  1727. }
  1728. else
  1729. {
  1730. // Verify that it is a value type
  1731. if( !(func.objectType->flags & asOBJ_VALUE) )
  1732. {
  1733. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
  1734. return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1735. }
  1736. // The templates take a hidden parameter with the object type
  1737. if( (objectType->flags & asOBJ_TEMPLATE) &&
  1738. (func.parameterTypes.GetLength() == 0 ||
  1739. !func.parameterTypes[0].IsReference()) )
  1740. {
  1741. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_FIRST_PARAM_MUST_BE_REF_FOR_TEMPLATE_FACTORY);
  1742. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1743. }
  1744. // TODO: Verify that the same constructor hasn't been registered already
  1745. // Store all constructors in a list
  1746. func.id = AddBehaviourFunction(func, internal);
  1747. beh->constructors.PushLast(func.id);
  1748. if( func.parameterTypes.GetLength() == 0 ||
  1749. (func.parameterTypes.GetLength() == 1 && (objectType->flags & asOBJ_TEMPLATE)) )
  1750. {
  1751. beh->construct = func.id;
  1752. }
  1753. else if( func.parameterTypes.GetLength() == 1 )
  1754. {
  1755. // Is this the copy constructor?
  1756. asCDataType paramType = func.parameterTypes[0];
  1757. // If the parameter is object, and const reference for input or inout,
  1758. // and same type as this class, then this is a copy constructor.
  1759. if( paramType.IsObject() && paramType.IsReference() && paramType.IsReadOnly() &&
  1760. (func.inOutFlags[0] & asTM_INREF) && paramType.GetTypeInfo() == objectType )
  1761. beh->copyconstruct = func.id;
  1762. }
  1763. }
  1764. }
  1765. else if( behaviour == asBEHAVE_DESTRUCT )
  1766. {
  1767. // Must be a value type
  1768. if( !(func.objectType->flags & asOBJ_VALUE) )
  1769. {
  1770. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
  1771. return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1772. }
  1773. if( beh->destruct )
  1774. return ConfigError(asALREADY_REGISTERED, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1775. // Verify that the return type is void
  1776. if( func.returnType != asCDataType::CreatePrimitive(ttVoid, false) )
  1777. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1778. // Verify that there are no parameters
  1779. if( func.parameterTypes.GetLength() > 0 )
  1780. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1781. func.id = beh->destruct = AddBehaviourFunction(func, internal);
  1782. }
  1783. else if( behaviour == asBEHAVE_LIST_CONSTRUCT )
  1784. {
  1785. func.name = "$list";
  1786. // Verify that the return type is void
  1787. if( func.returnType != asCDataType::CreatePrimitive(ttVoid, false) )
  1788. {
  1789. if( listPattern )
  1790. listPattern->Destroy(this);
  1791. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1792. }
  1793. // Verify that it is a value type
  1794. if( !(func.objectType->flags & asOBJ_VALUE) )
  1795. {
  1796. if( listPattern )
  1797. listPattern->Destroy(this);
  1798. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
  1799. return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1800. }
  1801. // Verify the parameters
  1802. // The templates take a hidden parameter with the object type
  1803. if( (!(objectType->flags & asOBJ_TEMPLATE) && (func.parameterTypes.GetLength() != 1 || !func.parameterTypes[0].IsReference())) ||
  1804. ((objectType->flags & asOBJ_TEMPLATE) && (func.parameterTypes.GetLength() != 2 || !func.parameterTypes[0].IsReference() || !func.parameterTypes[1].IsReference())) )
  1805. {
  1806. if( listPattern )
  1807. listPattern->Destroy(this);
  1808. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_LIST_FACTORY_EXPECTS_1_REF_PARAM);
  1809. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1810. }
  1811. // Don't accept duplicates
  1812. if( beh->listFactory )
  1813. {
  1814. if( listPattern )
  1815. listPattern->Destroy(this);
  1816. return ConfigError(asALREADY_REGISTERED, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1817. }
  1818. // Add the function
  1819. func.id = AddBehaviourFunction(func, internal);
  1820. // Re-use the listFactory member, as it is not possible to have both anyway
  1821. beh->listFactory = func.id;
  1822. // Store the list pattern for this function
  1823. r = scriptFunctions[func.id]->RegisterListPattern(decl, listPattern);
  1824. if( listPattern )
  1825. listPattern->Destroy(this);
  1826. if( r < 0 )
  1827. return ConfigError(r, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1828. }
  1829. else if( behaviour == asBEHAVE_FACTORY || behaviour == asBEHAVE_LIST_FACTORY )
  1830. {
  1831. if( behaviour == asBEHAVE_LIST_FACTORY )
  1832. func.name = "$list";
  1833. // Must be a ref type and must not have asOBJ_NOHANDLE
  1834. if( !(objectType->flags & asOBJ_REF) || (objectType->flags & asOBJ_NOHANDLE) )
  1835. {
  1836. if( listPattern )
  1837. listPattern->Destroy(this);
  1838. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
  1839. return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1840. }
  1841. // Verify that the return type is a handle to the type
  1842. if( func.returnType != asCDataType::CreateObjectHandle(objectType, false) )
  1843. {
  1844. if( listPattern )
  1845. listPattern->Destroy(this);
  1846. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1847. }
  1848. // The templates take a hidden parameter with the object type
  1849. if( (objectType->flags & asOBJ_TEMPLATE) &&
  1850. (func.parameterTypes.GetLength() == 0 ||
  1851. !func.parameterTypes[0].IsReference()) )
  1852. {
  1853. if( listPattern )
  1854. listPattern->Destroy(this);
  1855. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_FIRST_PARAM_MUST_BE_REF_FOR_TEMPLATE_FACTORY);
  1856. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1857. }
  1858. if( behaviour == asBEHAVE_LIST_FACTORY )
  1859. {
  1860. // Make sure the factory takes a reference as its last parameter
  1861. if( objectType->flags & asOBJ_TEMPLATE )
  1862. {
  1863. if( func.parameterTypes.GetLength() != 2 || !func.parameterTypes[1].IsReference() )
  1864. {
  1865. if( listPattern )
  1866. listPattern->Destroy(this);
  1867. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_TEMPLATE_LIST_FACTORY_EXPECTS_2_REF_PARAMS);
  1868. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1869. }
  1870. }
  1871. else
  1872. {
  1873. if( func.parameterTypes.GetLength() != 1 || !func.parameterTypes[0].IsReference() )
  1874. {
  1875. if( listPattern )
  1876. listPattern->Destroy(this);
  1877. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_LIST_FACTORY_EXPECTS_1_REF_PARAM);
  1878. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1879. }
  1880. }
  1881. }
  1882. // TODO: Verify that the same factory function hasn't been registered already
  1883. // Don't accept duplicates
  1884. if( behaviour == asBEHAVE_LIST_FACTORY && beh->listFactory )
  1885. {
  1886. if( listPattern )
  1887. listPattern->Destroy(this);
  1888. return ConfigError(asALREADY_REGISTERED, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1889. }
  1890. // Store all factory functions in a list
  1891. func.id = AddBehaviourFunction(func, internal);
  1892. // The list factory is a special factory and isn't stored together with the rest
  1893. if( behaviour != asBEHAVE_LIST_FACTORY )
  1894. beh->factories.PushLast(func.id);
  1895. if( (func.parameterTypes.GetLength() == 0) ||
  1896. (func.parameterTypes.GetLength() == 1 && (objectType->flags & asOBJ_TEMPLATE)) )
  1897. {
  1898. beh->factory = func.id;
  1899. }
  1900. else if( (func.parameterTypes.GetLength() == 1) ||
  1901. (func.parameterTypes.GetLength() == 2 && (objectType->flags & asOBJ_TEMPLATE)) )
  1902. {
  1903. if( behaviour == asBEHAVE_LIST_FACTORY )
  1904. {
  1905. beh->listFactory = func.id;
  1906. // Store the list pattern for this function
  1907. r = scriptFunctions[func.id]->RegisterListPattern(decl, listPattern);
  1908. if( listPattern )
  1909. listPattern->Destroy(this);
  1910. if( r < 0 )
  1911. return ConfigError(r, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1912. }
  1913. else
  1914. {
  1915. // Is this the copy factory?
  1916. asCDataType paramType = func.parameterTypes[func.parameterTypes.GetLength()-1];
  1917. // If the parameter is object, and const reference for input,
  1918. // and same type as this class, then this is a copy constructor.
  1919. if( paramType.IsObject() && paramType.IsReference() && paramType.IsReadOnly() && func.inOutFlags[func.parameterTypes.GetLength()-1] == asTM_INREF && paramType.GetTypeInfo() == objectType )
  1920. beh->copyfactory = func.id;
  1921. }
  1922. }
  1923. }
  1924. else if( behaviour == asBEHAVE_ADDREF )
  1925. {
  1926. // Must be a ref type and must not have asOBJ_NOHANDLE, nor asOBJ_SCOPED
  1927. if( !(func.objectType->flags & asOBJ_REF) ||
  1928. (func.objectType->flags & asOBJ_NOHANDLE) ||
  1929. (func.objectType->flags & asOBJ_SCOPED) ||
  1930. (func.objectType->flags & asOBJ_NOCOUNT) )
  1931. {
  1932. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
  1933. return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1934. }
  1935. if( beh->addref )
  1936. return ConfigError(asALREADY_REGISTERED, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1937. // Verify that the return type is void
  1938. if( func.returnType != asCDataType::CreatePrimitive(ttVoid, false) )
  1939. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1940. // Verify that there are no parameters
  1941. if( func.parameterTypes.GetLength() > 0 )
  1942. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1943. func.id = beh->addref = AddBehaviourFunction(func, internal);
  1944. }
  1945. else if( behaviour == asBEHAVE_RELEASE )
  1946. {
  1947. // Must be a ref type and must not have asOBJ_NOHANDLE
  1948. if( !(func.objectType->flags & asOBJ_REF) ||
  1949. (func.objectType->flags & asOBJ_NOHANDLE) ||
  1950. (func.objectType->flags & asOBJ_NOCOUNT) )
  1951. {
  1952. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
  1953. return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1954. }
  1955. if( beh->release )
  1956. return ConfigError(asALREADY_REGISTERED, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1957. // Verify that the return type is void
  1958. if( func.returnType != asCDataType::CreatePrimitive(ttVoid, false) )
  1959. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1960. // Verify that there are no parameters
  1961. if( func.parameterTypes.GetLength() > 0 )
  1962. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1963. func.id = beh->release = AddBehaviourFunction(func, internal);
  1964. }
  1965. else if( behaviour == asBEHAVE_TEMPLATE_CALLBACK )
  1966. {
  1967. // Must be a template type
  1968. if( !(func.objectType->flags & asOBJ_TEMPLATE) )
  1969. {
  1970. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
  1971. return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1972. }
  1973. if( beh->templateCallback )
  1974. return ConfigError(asALREADY_REGISTERED, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1975. // Verify that the return type is bool
  1976. if( func.returnType != asCDataType::CreatePrimitive(ttBool, false) )
  1977. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1978. // Verify that there are two parameters
  1979. if( func.parameterTypes.GetLength() != 2 )
  1980. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1981. // The first parameter must be an inref (to receive the object type), and
  1982. // the second must be a bool out ref (to return if the type should or shouldn't be garbage collected)
  1983. if( func.inOutFlags[0] != asTM_INREF || func.inOutFlags[1] != asTM_OUTREF || !func.parameterTypes[1].IsEqualExceptRef(asCDataType::CreatePrimitive(ttBool, false)) )
  1984. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1985. func.id = beh->templateCallback = AddBehaviourFunction(func, internal);
  1986. }
  1987. else if( behaviour >= asBEHAVE_FIRST_GC &&
  1988. behaviour <= asBEHAVE_LAST_GC )
  1989. {
  1990. // Only allow GC behaviours for types registered to be garbage collected
  1991. if( !(func.objectType->flags & asOBJ_GC) )
  1992. {
  1993. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
  1994. return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1995. }
  1996. // Verify parameter count
  1997. if( (behaviour == asBEHAVE_GETREFCOUNT ||
  1998. behaviour == asBEHAVE_SETGCFLAG ||
  1999. behaviour == asBEHAVE_GETGCFLAG) &&
  2000. func.parameterTypes.GetLength() != 0 )
  2001. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  2002. if( (behaviour == asBEHAVE_ENUMREFS ||
  2003. behaviour == asBEHAVE_RELEASEREFS) &&
  2004. func.parameterTypes.GetLength() != 1 )
  2005. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  2006. // Verify return type
  2007. if( behaviour == asBEHAVE_GETREFCOUNT &&
  2008. func.returnType != asCDataType::CreatePrimitive(ttInt, false) )
  2009. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  2010. if( behaviour == asBEHAVE_GETGCFLAG &&
  2011. func.returnType != asCDataType::CreatePrimitive(ttBool, false) )
  2012. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  2013. if( (behaviour == asBEHAVE_SETGCFLAG ||
  2014. behaviour == asBEHAVE_ENUMREFS ||
  2015. behaviour == asBEHAVE_RELEASEREFS) &&
  2016. func.returnType != asCDataType::CreatePrimitive(ttVoid, false) )
  2017. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  2018. if( behaviour == asBEHAVE_GETREFCOUNT )
  2019. func.id = beh->gcGetRefCount = AddBehaviourFunction(func, internal);
  2020. else if( behaviour == asBEHAVE_SETGCFLAG )
  2021. func.id = beh->gcSetFlag = AddBehaviourFunction(func, internal);
  2022. else if( behaviour == asBEHAVE_GETGCFLAG )
  2023. func.id = beh->gcGetFlag = AddBehaviourFunction(func, internal);
  2024. else if( behaviour == asBEHAVE_ENUMREFS )
  2025. func.id = beh->gcEnumReferences = AddBehaviourFunction(func, internal);
  2026. else if( behaviour == asBEHAVE_RELEASEREFS )
  2027. func.id = beh->gcReleaseAllReferences = AddBehaviourFunction(func, internal);
  2028. }
  2029. else if ( behaviour == asBEHAVE_GET_WEAKREF_FLAG )
  2030. {
  2031. // This behaviour is only allowed for reference types
  2032. if( !(func.objectType->flags & asOBJ_REF) )
  2033. {
  2034. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
  2035. return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  2036. }
  2037. // Don't allow it if the type is registered with nohandle or scoped
  2038. if( func.objectType->flags & (asOBJ_NOHANDLE|asOBJ_SCOPED) )
  2039. {
  2040. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
  2041. return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  2042. }
  2043. // Verify that the return type is a reference since it needs to return a pointer to an asISharedBool
  2044. if( !func.returnType.IsReference() )
  2045. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  2046. // Verify that there are no parameters
  2047. if( func.parameterTypes.GetLength() != 0 )
  2048. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  2049. if( beh->getWeakRefFlag )
  2050. return ConfigError(asALREADY_REGISTERED, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  2051. func.id = beh->getWeakRefFlag = AddBehaviourFunction(func, internal);
  2052. }
  2053. else
  2054. {
  2055. asASSERT(false);
  2056. return ConfigError(asINVALID_ARG, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  2057. }
  2058. if( func.id < 0 )
  2059. return ConfigError(func.id, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  2060. // Return function id as success
  2061. return func.id;
  2062. }
  2063. int asCScriptEngine::SetTemplateRestrictions(asCObjectType *templateType, asCScriptFunction *func, const char *caller, const char *decl)
  2064. {
  2065. asASSERT(templateType->flags & asOBJ_TEMPLATE);
  2066. for (asUINT subTypeIdx = 0; subTypeIdx < templateType->templateSubTypes.GetLength(); subTypeIdx++)
  2067. {
  2068. if (func->returnType.GetTypeInfo() == templateType->templateSubTypes[subTypeIdx].GetTypeInfo())
  2069. {
  2070. if (func->returnType.IsObjectHandle())
  2071. templateType->acceptValueSubType = false;
  2072. else if (!func->returnType.IsReference())
  2073. templateType->acceptRefSubType = false;
  2074. // Can't support template subtypes by value, since each type is treated differently in the ABI
  2075. if (!func->returnType.IsObjectHandle() && !func->returnType.IsReference())
  2076. return ConfigError(asNOT_SUPPORTED, caller, templateType->name.AddressOf(), decl);
  2077. }
  2078. for (asUINT n = 0; n < func->parameterTypes.GetLength(); n++)
  2079. {
  2080. if (func->parameterTypes[n].GetTypeInfo() == templateType->templateSubTypes[subTypeIdx].GetTypeInfo())
  2081. {
  2082. if (func->parameterTypes[n].IsObjectHandle() ||
  2083. (!ep.allowUnsafeReferences && func->parameterTypes[n].IsReference() && func->inOutFlags[n] == asTM_INOUTREF))
  2084. templateType->acceptValueSubType = false;
  2085. else if (!func->parameterTypes[n].IsReference())
  2086. templateType->acceptRefSubType = false;
  2087. // Can't support template subtypes by value, since each type is treated differently in the ABI
  2088. if (!func->parameterTypes[n].IsObjectHandle() && !func->parameterTypes[n].IsReference())
  2089. return ConfigError(asNOT_SUPPORTED, caller, templateType->name.AddressOf(), decl);
  2090. }
  2091. }
  2092. }
  2093. return asSUCCESS;
  2094. }
  2095. int asCScriptEngine::VerifyVarTypeNotInFunction(asCScriptFunction *func)
  2096. {
  2097. // Don't allow var type in this function
  2098. if( func->returnType.GetTokenType() == ttQuestion )
  2099. return asINVALID_DECLARATION;
  2100. for( unsigned int n = 0; n < func->parameterTypes.GetLength(); n++ )
  2101. if( func->parameterTypes[n].GetTokenType() == ttQuestion )
  2102. return asINVALID_DECLARATION;
  2103. return 0;
  2104. }
  2105. int asCScriptEngine::AddBehaviourFunction(asCScriptFunction &func, asSSystemFunctionInterface &internal)
  2106. {
  2107. asUINT n;
  2108. int id = GetNextScriptFunctionId();
  2109. asSSystemFunctionInterface *newInterface = asNEW(asSSystemFunctionInterface)(internal);
  2110. if( newInterface == 0 )
  2111. return asOUT_OF_MEMORY;
  2112. asCScriptFunction *f = asNEW(asCScriptFunction)(this, 0, asFUNC_SYSTEM);
  2113. if( f == 0 )
  2114. {
  2115. asDELETE(newInterface, asSSystemFunctionInterface);
  2116. return asOUT_OF_MEMORY;
  2117. }
  2118. asASSERT(func.name != "" && func.name != "f");
  2119. f->name = func.name;
  2120. f->sysFuncIntf = newInterface;
  2121. f->returnType = func.returnType;
  2122. f->objectType = func.objectType;
  2123. if( f->objectType )
  2124. f->objectType->AddRefInternal();
  2125. f->id = id;
  2126. f->SetReadOnly(func.IsReadOnly());
  2127. f->accessMask = defaultAccessMask;
  2128. f->parameterTypes = func.parameterTypes;
  2129. f->parameterNames = func.parameterNames;
  2130. f->inOutFlags = func.inOutFlags;
  2131. f->traits = func.traits;
  2132. for( n = 0; n < func.defaultArgs.GetLength(); n++ )
  2133. if( func.defaultArgs[n] )
  2134. f->defaultArgs.PushLast(asNEW(asCString)(*func.defaultArgs[n]));
  2135. else
  2136. f->defaultArgs.PushLast(0);
  2137. AddScriptFunction(f);
  2138. // If parameter type from other groups are used, add references
  2139. currentGroup->AddReferencesForFunc(this, f);
  2140. return id;
  2141. }
  2142. // interface
  2143. int asCScriptEngine::RegisterGlobalProperty(const char *declaration, void *pointer)
  2144. {
  2145. // Don't accept a null pointer
  2146. if( pointer == 0 )
  2147. return ConfigError(asINVALID_ARG, "RegisterGlobalProperty", declaration, 0);
  2148. asCDataType type;
  2149. asCString name;
  2150. int r;
  2151. asCBuilder bld(this, 0);
  2152. if( (r = bld.VerifyProperty(0, declaration, name, type, defaultNamespace)) < 0 )
  2153. return ConfigError(r, "RegisterGlobalProperty", declaration, 0);
  2154. // Don't allow registering references as global properties
  2155. if( type.IsReference() )
  2156. return ConfigError(asINVALID_TYPE, "RegisterGlobalProperty", declaration, 0);
  2157. // Store the property info
  2158. asCGlobalProperty *prop = AllocateGlobalProperty();
  2159. prop->name = name;
  2160. prop->nameSpace = defaultNamespace;
  2161. prop->type = type;
  2162. prop->accessMask = defaultAccessMask;
  2163. prop->SetRegisteredAddress(pointer);
  2164. varAddressMap.Insert(prop->GetAddressOfValue(), prop);
  2165. asUINT idx = registeredGlobalProps.Put(prop);
  2166. prop->AddRef();
  2167. currentGroup->globalProps.PushLast(prop);
  2168. currentGroup->AddReferencesForType(this, type.GetTypeInfo());
  2169. // Return the index of the property to signal success
  2170. return int(idx);
  2171. }
  2172. // internal
  2173. asCGlobalProperty *asCScriptEngine::AllocateGlobalProperty()
  2174. {
  2175. asCGlobalProperty *prop = asNEW(asCGlobalProperty);
  2176. if( prop == 0 )
  2177. {
  2178. // Out of memory
  2179. return 0;
  2180. }
  2181. // First check the availability of a free slot
  2182. if( freeGlobalPropertyIds.GetLength() )
  2183. {
  2184. prop->id = freeGlobalPropertyIds.PopLast();
  2185. globalProperties[prop->id] = prop;
  2186. return prop;
  2187. }
  2188. prop->id = (asUINT)globalProperties.GetLength();
  2189. globalProperties.PushLast(prop);
  2190. return prop;
  2191. }
  2192. // internal
  2193. void asCScriptEngine::RemoveGlobalProperty(asCGlobalProperty *prop)
  2194. {
  2195. int index = globalProperties.IndexOf(prop);
  2196. if( index >= 0 )
  2197. {
  2198. freeGlobalPropertyIds.PushLast(index);
  2199. globalProperties[index] = 0;
  2200. asSMapNode<void*, asCGlobalProperty*> *node;
  2201. varAddressMap.MoveTo(&node, prop->GetAddressOfValue());
  2202. asASSERT(node);
  2203. if( node )
  2204. varAddressMap.Erase(node);
  2205. prop->Release();
  2206. }
  2207. }
  2208. // interface
  2209. asUINT asCScriptEngine::GetGlobalPropertyCount() const
  2210. {
  2211. return asUINT(registeredGlobalProps.GetSize());
  2212. }
  2213. // interface
  2214. // TODO: If the typeId ever encodes the const flag, then the isConst parameter should be removed
  2215. int asCScriptEngine::GetGlobalPropertyByIndex(asUINT index, const char **name, const char **nameSpace, int *typeId, bool *isConst, const char **configGroup, void **pointer, asDWORD *accessMask) const
  2216. {
  2217. const asCGlobalProperty *prop = registeredGlobalProps.Get(index);
  2218. if( !prop )
  2219. return asINVALID_ARG;
  2220. if( name ) *name = prop->name.AddressOf();
  2221. if( nameSpace ) *nameSpace = prop->nameSpace->name.AddressOf();
  2222. if( typeId ) *typeId = GetTypeIdFromDataType(prop->type);
  2223. if( isConst ) *isConst = prop->type.IsReadOnly();
  2224. if( pointer ) *pointer = prop->GetRegisteredAddress();
  2225. if( accessMask ) *accessMask = prop->accessMask;
  2226. if( configGroup )
  2227. {
  2228. asCConfigGroup *group = FindConfigGroupForGlobalVar(index);
  2229. if( group )
  2230. *configGroup = group->groupName.AddressOf();
  2231. else
  2232. *configGroup = 0;
  2233. }
  2234. return asSUCCESS;
  2235. }
  2236. // interface
  2237. int asCScriptEngine::GetGlobalPropertyIndexByName(const char *in_name) const
  2238. {
  2239. asCString name;
  2240. asSNameSpace *ns = 0;
  2241. if( DetermineNameAndNamespace(in_name, defaultNamespace, name, ns) < 0 )
  2242. return asINVALID_ARG;
  2243. // Find the global var id
  2244. while( ns )
  2245. {
  2246. int id = registeredGlobalProps.GetFirstIndex(ns, name);
  2247. if( id >= 0 )
  2248. return id;
  2249. // Recursively search parent namespace
  2250. ns = GetParentNameSpace(ns);
  2251. }
  2252. return asNO_GLOBAL_VAR;
  2253. }
  2254. // interface
  2255. int asCScriptEngine::GetGlobalPropertyIndexByDecl(const char *decl) const
  2256. {
  2257. // This const cast is OK. The builder won't modify the engine
  2258. asCBuilder bld(const_cast<asCScriptEngine*>(this), 0);
  2259. // Don't write parser errors to the message callback
  2260. bld.silent = true;
  2261. asCString name;
  2262. asSNameSpace *ns;
  2263. asCDataType dt;
  2264. int r = bld.ParseVariableDeclaration(decl, defaultNamespace, name, ns, dt);
  2265. if( r < 0 )
  2266. return r;
  2267. // Search for a match
  2268. while( ns )
  2269. {
  2270. int id = registeredGlobalProps.GetFirstIndex(ns, name, asCCompGlobPropType(dt));
  2271. if( id >= 0 )
  2272. return id;
  2273. ns = GetParentNameSpace(ns);
  2274. }
  2275. return asNO_GLOBAL_VAR;
  2276. }
  2277. // interface
  2278. int asCScriptEngine::RegisterObjectMethod(const char *obj, const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *auxiliary, int compositeOffset, bool isCompositeIndirect)
  2279. {
  2280. if( obj == 0 )
  2281. return ConfigError(asINVALID_ARG, "RegisterObjectMethod", obj, declaration);
  2282. // Determine the object type
  2283. asCDataType dt;
  2284. asCBuilder bld(this, 0);
  2285. int r = bld.ParseDataType(obj, &dt, defaultNamespace);
  2286. if( r < 0 )
  2287. return ConfigError(r, "RegisterObjectMethod", obj, declaration);
  2288. // Don't allow application to modify primitives or handles
  2289. if( dt.GetTypeInfo() == 0 || (dt.IsObjectHandle() && !(dt.GetTypeInfo()->GetFlags() & asOBJ_IMPLICIT_HANDLE)))
  2290. return ConfigError(asINVALID_ARG, "RegisterObjectMethod", obj, declaration);
  2291. // Don't allow application to modify built-in types or funcdefs
  2292. if( dt.GetTypeInfo() == &functionBehaviours ||
  2293. dt.GetTypeInfo() == &scriptTypeBehaviours ||
  2294. CastToFuncdefType(dt.GetTypeInfo()) )
  2295. return ConfigError(asINVALID_ARG, "RegisterObjectMethod", obj, declaration);
  2296. // Don't allow modifying generated template instances
  2297. if( dt.GetTypeInfo() && (dt.GetTypeInfo()->flags & asOBJ_TEMPLATE) && generatedTemplateTypes.Exists(CastToObjectType(dt.GetTypeInfo())) )
  2298. return ConfigError(asINVALID_TYPE, "RegisterObjectMethod", obj, declaration);
  2299. return RegisterMethodToObjectType(CastToObjectType(dt.GetTypeInfo()), declaration, funcPointer, callConv, auxiliary, compositeOffset, isCompositeIndirect);
  2300. }
  2301. // internal
  2302. int asCScriptEngine::RegisterMethodToObjectType(asCObjectType *objectType, const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *auxiliary, int compositeOffset, bool isCompositeIndirect)
  2303. {
  2304. #ifdef AS_MAX_PORTABILITY
  2305. if( callConv != asCALL_GENERIC )
  2306. return ConfigError(asNOT_SUPPORTED, "RegisterObjectMethod", objectType->name.AddressOf(), declaration);
  2307. #endif
  2308. asSSystemFunctionInterface internal;
  2309. int r = DetectCallingConvention(true, funcPointer, callConv, auxiliary, &internal);
  2310. if( r < 0 )
  2311. return ConfigError(r, "RegisterObjectMethod", objectType->name.AddressOf(), declaration);
  2312. internal.compositeOffset = compositeOffset;
  2313. internal.isCompositeIndirect = isCompositeIndirect;
  2314. if( (compositeOffset || isCompositeIndirect) && callConv != asCALL_THISCALL )
  2315. return ConfigError(asINVALID_ARG, "RegisterObjectMethod", objectType->name.AddressOf(), declaration);
  2316. // TODO: cleanup: This is identical to what is in RegisterMethodToObjectType
  2317. // If the object type is a template, make sure there are no generated instances already
  2318. if( objectType->flags & asOBJ_TEMPLATE )
  2319. {
  2320. for( asUINT n = 0; n < generatedTemplateTypes.GetLength(); n++ )
  2321. {
  2322. asCObjectType *tmpl = generatedTemplateTypes[n];
  2323. if( tmpl->name == objectType->name &&
  2324. tmpl->nameSpace == objectType->nameSpace &&
  2325. !(tmpl->templateSubTypes[0].GetTypeInfo() && (tmpl->templateSubTypes[0].GetTypeInfo()->flags & asOBJ_TEMPLATE_SUBTYPE)) )
  2326. {
  2327. asCString msg;
  2328. msg.Format(TXT_TEMPLATE_s_ALREADY_GENERATED_CANT_REGISTER, asCDataType::CreateType(tmpl, false).Format(tmpl->nameSpace).AddressOf());
  2329. WriteMessage("",0,0, asMSGTYPE_ERROR, msg.AddressOf());
  2330. return ConfigError(asERROR, "RegisterObjectMethod", objectType->name.AddressOf(), declaration);
  2331. }
  2332. }
  2333. }
  2334. isPrepared = false;
  2335. // Put the system function in the list of system functions
  2336. asSSystemFunctionInterface *newInterface = asNEW(asSSystemFunctionInterface)(internal);
  2337. if( newInterface == 0 )
  2338. return ConfigError(asOUT_OF_MEMORY, "RegisterObjectMethod", objectType->name.AddressOf(), declaration);
  2339. asCScriptFunction *func = asNEW(asCScriptFunction)(this, 0, asFUNC_SYSTEM);
  2340. if( func == 0 )
  2341. {
  2342. asDELETE(newInterface, asSSystemFunctionInterface);
  2343. return ConfigError(asOUT_OF_MEMORY, "RegisterObjectMethod", objectType->name.AddressOf(), declaration);
  2344. }
  2345. func->sysFuncIntf = newInterface;
  2346. func->objectType = objectType;
  2347. func->objectType->AddRefInternal();
  2348. asCBuilder bld(this, 0);
  2349. r = bld.ParseFunctionDeclaration(func->objectType, declaration, func, true, &newInterface->paramAutoHandles, &newInterface->returnAutoHandle);
  2350. if( r < 0 )
  2351. {
  2352. // Set as dummy function before deleting
  2353. func->funcType = asFUNC_DUMMY;
  2354. asDELETE(func,asCScriptFunction);
  2355. return ConfigError(asINVALID_DECLARATION, "RegisterObjectMethod", objectType->name.AddressOf(), declaration);
  2356. }
  2357. // Check name conflicts
  2358. r = bld.CheckNameConflictMember(objectType, func->name.AddressOf(), 0, 0, false, false);
  2359. if( r < 0 )
  2360. {
  2361. func->funcType = asFUNC_DUMMY;
  2362. asDELETE(func,asCScriptFunction);
  2363. return ConfigError(asNAME_TAKEN, "RegisterObjectMethod", objectType->name.AddressOf(), declaration);
  2364. }
  2365. // Validate property signature
  2366. if( func->IsProperty() && (r = bld.ValidateVirtualProperty(func)) < 0 )
  2367. {
  2368. // Set as dummy function before deleting
  2369. func->funcType = asFUNC_DUMMY;
  2370. asDELETE(func,asCScriptFunction);
  2371. if( r == -5 )
  2372. return ConfigError(asNAME_TAKEN, "RegisterObjectMethod", objectType->name.AddressOf(), declaration);
  2373. else
  2374. return ConfigError(asINVALID_DECLARATION, "RegisterObjectMethod", objectType->name.AddressOf(), declaration);
  2375. }
  2376. // Check against duplicate methods
  2377. if( func->name == "opConv" || func->name == "opImplConv" || func->name == "opCast" || func->name == "opImplCast" )
  2378. {
  2379. // opConv and opCast are special methods that the compiler differentiates between by the return type
  2380. for( asUINT n = 0; n < func->objectType->methods.GetLength(); n++ )
  2381. {
  2382. asCScriptFunction *f = scriptFunctions[func->objectType->methods[n]];
  2383. if( f->name == func->name &&
  2384. f->IsSignatureExceptNameEqual(func) )
  2385. {
  2386. func->funcType = asFUNC_DUMMY;
  2387. asDELETE(func,asCScriptFunction);
  2388. return ConfigError(asALREADY_REGISTERED, "RegisterObjectMethod", objectType->name.AddressOf(), declaration);
  2389. }
  2390. }
  2391. }
  2392. else
  2393. {
  2394. for( asUINT n = 0; n < func->objectType->methods.GetLength(); n++ )
  2395. {
  2396. asCScriptFunction *f = scriptFunctions[func->objectType->methods[n]];
  2397. if( f->name == func->name &&
  2398. f->IsSignatureExceptNameAndReturnTypeEqual(func) )
  2399. {
  2400. func->funcType = asFUNC_DUMMY;
  2401. asDELETE(func,asCScriptFunction);
  2402. return ConfigError(asALREADY_REGISTERED, "RegisterObjectMethod", objectType->name.AddressOf(), declaration);
  2403. }
  2404. }
  2405. }
  2406. func->id = GetNextScriptFunctionId();
  2407. func->objectType->methods.PushLast(func->id);
  2408. func->accessMask = defaultAccessMask;
  2409. AddScriptFunction(func);
  2410. // If parameter type from other groups are used, add references
  2411. currentGroup->AddReferencesForFunc(this, func);
  2412. // Check if the method restricts that use of the template to value types or reference types
  2413. if( func->objectType->flags & asOBJ_TEMPLATE )
  2414. {
  2415. r = SetTemplateRestrictions(func->objectType, func, "RegisterObjectMethod", declaration);
  2416. if (r < 0)
  2417. return r;
  2418. }
  2419. // TODO: beh.copy member will be removed, so this is not necessary
  2420. // Is this the default copy behaviour?
  2421. if( func->name == "opAssign" && func->parameterTypes.GetLength() == 1 && !func->IsReadOnly() &&
  2422. ((objectType->flags & asOBJ_SCRIPT_OBJECT) || func->parameterTypes[0].IsEqualExceptRefAndConst(asCDataType::CreateType(func->objectType, false))) )
  2423. {
  2424. if( func->objectType->beh.copy != 0 )
  2425. return ConfigError(asALREADY_REGISTERED, "RegisterObjectMethod", objectType->name.AddressOf(), declaration);
  2426. func->objectType->beh.copy = func->id;
  2427. func->AddRefInternal();
  2428. }
  2429. // Return the function id as success
  2430. return func->id;
  2431. }
  2432. // interface
  2433. int asCScriptEngine::RegisterGlobalFunction(const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *auxiliary)
  2434. {
  2435. #ifdef AS_MAX_PORTABILITY
  2436. if( callConv != asCALL_GENERIC )
  2437. return ConfigError(asNOT_SUPPORTED, "RegisterGlobalFunction", declaration, 0);
  2438. #endif
  2439. asSSystemFunctionInterface internal;
  2440. int r = DetectCallingConvention(false, funcPointer, callConv, auxiliary, &internal);
  2441. if( r < 0 )
  2442. return ConfigError(r, "RegisterGlobalFunction", declaration, 0);
  2443. isPrepared = false;
  2444. // Put the system function in the list of system functions
  2445. asSSystemFunctionInterface *newInterface = asNEW(asSSystemFunctionInterface)(internal);
  2446. if( newInterface == 0 )
  2447. return ConfigError(asOUT_OF_MEMORY, "RegisterGlobalFunction", declaration, 0);
  2448. asCScriptFunction *func = asNEW(asCScriptFunction)(this, 0, asFUNC_SYSTEM);
  2449. if( func == 0 )
  2450. {
  2451. asDELETE(newInterface, asSSystemFunctionInterface);
  2452. return ConfigError(asOUT_OF_MEMORY, "RegisterGlobalFunction", declaration, 0);
  2453. }
  2454. func->sysFuncIntf = newInterface;
  2455. asCBuilder bld(this, 0);
  2456. r = bld.ParseFunctionDeclaration(0, declaration, func, true, &newInterface->paramAutoHandles, &newInterface->returnAutoHandle, defaultNamespace);
  2457. if( r < 0 )
  2458. {
  2459. // Set as dummy function before deleting
  2460. func->funcType = asFUNC_DUMMY;
  2461. asDELETE(func,asCScriptFunction);
  2462. return ConfigError(asINVALID_DECLARATION, "RegisterGlobalFunction", declaration, 0);
  2463. }
  2464. // TODO: namespace: What if the declaration defined an explicit namespace?
  2465. func->nameSpace = defaultNamespace;
  2466. // Check name conflicts
  2467. r = bld.CheckNameConflict(func->name.AddressOf(), 0, 0, defaultNamespace, false, false, false);
  2468. if( r < 0 )
  2469. {
  2470. // Set as dummy function before deleting
  2471. func->funcType = asFUNC_DUMMY;
  2472. asDELETE(func,asCScriptFunction);
  2473. return ConfigError(asNAME_TAKEN, "RegisterGlobalFunction", declaration, 0);
  2474. }
  2475. // Validate property signature
  2476. if( func->IsProperty() && (r = bld.ValidateVirtualProperty(func)) < 0 )
  2477. {
  2478. // Set as dummy function before deleting
  2479. func->funcType = asFUNC_DUMMY;
  2480. asDELETE(func,asCScriptFunction);
  2481. if( r == -5 )
  2482. return ConfigError(asNAME_TAKEN, "RegisterGlobalFunction", declaration, 0);
  2483. else
  2484. return ConfigError(asINVALID_DECLARATION, "RegisterGlobalFunction", declaration, 0);
  2485. }
  2486. // Make sure the function is not identical to a previously registered function
  2487. asUINT n;
  2488. const asCArray<unsigned int> &idxs = registeredGlobalFuncs.GetIndexes(func->nameSpace, func->name);
  2489. for( n = 0; n < idxs.GetLength(); n++ )
  2490. {
  2491. asCScriptFunction *f = registeredGlobalFuncs.Get(idxs[n]);
  2492. if( f->IsSignatureExceptNameAndReturnTypeEqual(func) )
  2493. {
  2494. func->funcType = asFUNC_DUMMY;
  2495. asDELETE(func,asCScriptFunction);
  2496. return ConfigError(asALREADY_REGISTERED, "RegisterGlobalFunction", declaration, 0);
  2497. }
  2498. }
  2499. func->id = GetNextScriptFunctionId();
  2500. AddScriptFunction(func);
  2501. currentGroup->scriptFunctions.PushLast(func);
  2502. func->accessMask = defaultAccessMask;
  2503. registeredGlobalFuncs.Put(func);
  2504. // If parameter type from other groups are used, add references
  2505. currentGroup->AddReferencesForFunc(this, func);
  2506. // Return the function id as success
  2507. return func->id;
  2508. }
  2509. // interface
  2510. asUINT asCScriptEngine::GetGlobalFunctionCount() const
  2511. {
  2512. // Don't count the builtin delegate factory
  2513. return asUINT(registeredGlobalFuncs.GetSize()-1);
  2514. }
  2515. // interface
  2516. asIScriptFunction *asCScriptEngine::GetGlobalFunctionByIndex(asUINT index) const
  2517. {
  2518. // Don't count the builtin delegate factory
  2519. index++;
  2520. if( index >= registeredGlobalFuncs.GetSize() )
  2521. return 0;
  2522. return static_cast<asIScriptFunction*>(const_cast<asCScriptFunction*>(registeredGlobalFuncs.Get(index)));
  2523. }
  2524. // interface
  2525. asIScriptFunction *asCScriptEngine::GetGlobalFunctionByDecl(const char *decl) const
  2526. {
  2527. asCBuilder bld(const_cast<asCScriptEngine*>(this), 0);
  2528. // Don't write parser errors to the message callback
  2529. bld.silent = true;
  2530. asCScriptFunction func(const_cast<asCScriptEngine*>(this), 0, asFUNC_DUMMY);
  2531. int r = bld.ParseFunctionDeclaration(0, decl, &func, false, 0, 0, defaultNamespace);
  2532. if( r < 0 )
  2533. return 0;
  2534. asSNameSpace *ns = defaultNamespace;
  2535. // Search script functions for matching interface
  2536. while( ns )
  2537. {
  2538. asIScriptFunction *f = 0;
  2539. const asCArray<unsigned int> &idxs = registeredGlobalFuncs.GetIndexes(ns, func.name);
  2540. for( unsigned int n = 0; n < idxs.GetLength(); n++ )
  2541. {
  2542. const asCScriptFunction *funcPtr = registeredGlobalFuncs.Get(idxs[n]);
  2543. if( funcPtr->objectType == 0 &&
  2544. func.returnType == funcPtr->returnType &&
  2545. func.parameterTypes.GetLength() == funcPtr->parameterTypes.GetLength()
  2546. )
  2547. {
  2548. bool match = true;
  2549. for( asUINT p = 0; p < func.parameterTypes.GetLength(); ++p )
  2550. {
  2551. if( func.parameterTypes[p] != funcPtr->parameterTypes[p] )
  2552. {
  2553. match = false;
  2554. break;
  2555. }
  2556. }
  2557. if( match )
  2558. {
  2559. if( f == 0 )
  2560. f = const_cast<asCScriptFunction*>(funcPtr);
  2561. else
  2562. // Multiple functions
  2563. return 0;
  2564. }
  2565. }
  2566. }
  2567. if( f )
  2568. return f;
  2569. // Recursively search parent namespaces
  2570. ns = GetParentNameSpace(ns);
  2571. }
  2572. return 0;
  2573. }
  2574. asCTypeInfo *asCScriptEngine::GetRegisteredType(const asCString &type, asSNameSpace *ns) const
  2575. {
  2576. asSMapNode<asSNameSpaceNamePair, asCTypeInfo *> *cursor;
  2577. if( allRegisteredTypes.MoveTo(&cursor, asSNameSpaceNamePair(ns, type)) )
  2578. return cursor->value;
  2579. return 0;
  2580. }
  2581. void asCScriptEngine::PrepareEngine()
  2582. {
  2583. if( isPrepared ) return;
  2584. if( configFailed ) return;
  2585. asUINT n;
  2586. for( n = 0; n < scriptFunctions.GetLength(); n++ )
  2587. {
  2588. // Determine the host application interface
  2589. if( scriptFunctions[n] && scriptFunctions[n]->funcType == asFUNC_SYSTEM )
  2590. {
  2591. if( scriptFunctions[n]->sysFuncIntf->callConv == ICC_GENERIC_FUNC ||
  2592. scriptFunctions[n]->sysFuncIntf->callConv == ICC_GENERIC_METHOD )
  2593. PrepareSystemFunctionGeneric(scriptFunctions[n], scriptFunctions[n]->sysFuncIntf, this);
  2594. else
  2595. PrepareSystemFunction(scriptFunctions[n], scriptFunctions[n]->sysFuncIntf, this);
  2596. }
  2597. }
  2598. // Validate object type registrations
  2599. for( n = 0; n < registeredObjTypes.GetLength(); n++ )
  2600. {
  2601. asCObjectType *type = registeredObjTypes[n];
  2602. if( type && !(type->flags & asOBJ_SCRIPT_OBJECT) )
  2603. {
  2604. bool missingBehaviour = false;
  2605. const char *infoMsg = 0;
  2606. // Verify that GC types have all behaviours
  2607. if( type->flags & asOBJ_GC )
  2608. {
  2609. if (type->flags & asOBJ_REF)
  2610. {
  2611. if (type->beh.addref == 0 ||
  2612. type->beh.release == 0 ||
  2613. type->beh.gcGetRefCount == 0 ||
  2614. type->beh.gcSetFlag == 0 ||
  2615. type->beh.gcGetFlag == 0 ||
  2616. type->beh.gcEnumReferences == 0 ||
  2617. type->beh.gcReleaseAllReferences == 0)
  2618. {
  2619. infoMsg = TXT_GC_REQUIRE_ADD_REL_GC_BEHAVIOUR;
  2620. missingBehaviour = true;
  2621. }
  2622. }
  2623. else
  2624. {
  2625. if (type->beh.gcEnumReferences == 0)
  2626. {
  2627. infoMsg = TXT_VALUE_GC_REQUIRE_GC_BEHAVIOUR;
  2628. missingBehaviour = true;
  2629. }
  2630. }
  2631. }
  2632. // Verify that scoped ref types have the release behaviour
  2633. if( type->flags & asOBJ_SCOPED )
  2634. {
  2635. if( type->beh.release == 0 )
  2636. {
  2637. infoMsg = TXT_SCOPE_REQUIRE_REL_BEHAVIOUR;
  2638. missingBehaviour = true;
  2639. }
  2640. }
  2641. // Verify that ref types have add ref and release behaviours
  2642. if( (type->flags & asOBJ_REF) &&
  2643. !(type->flags & asOBJ_SCOPED) &&
  2644. !(type->flags & asOBJ_NOHANDLE) &&
  2645. !(type->flags & asOBJ_NOCOUNT) )
  2646. {
  2647. if( type->beh.addref == 0 ||
  2648. type->beh.release == 0 )
  2649. {
  2650. infoMsg = TXT_REF_REQUIRE_ADD_REL_BEHAVIOUR;
  2651. missingBehaviour = true;
  2652. }
  2653. }
  2654. // Verify that non-pod value types have the constructor and destructor registered
  2655. if( (type->flags & asOBJ_VALUE) &&
  2656. !(type->flags & asOBJ_POD) )
  2657. {
  2658. if( type->beh.constructors.GetLength() == 0 ||
  2659. type->beh.destruct == 0 )
  2660. {
  2661. infoMsg = TXT_NON_POD_REQUIRE_CONSTR_DESTR_BEHAVIOUR;
  2662. missingBehaviour = true;
  2663. }
  2664. }
  2665. if( missingBehaviour )
  2666. {
  2667. asCString str;
  2668. str.Format(TXT_TYPE_s_IS_MISSING_BEHAVIOURS, type->name.AddressOf());
  2669. WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  2670. WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, infoMsg);
  2671. ConfigError(asINVALID_CONFIGURATION, 0, 0, 0);
  2672. }
  2673. }
  2674. }
  2675. isPrepared = true;
  2676. }
  2677. int asCScriptEngine::ConfigError(int err, const char *funcName, const char *arg1, const char *arg2)
  2678. {
  2679. configFailed = true;
  2680. if( funcName )
  2681. {
  2682. asCString str;
  2683. if( arg1 )
  2684. {
  2685. if( arg2 )
  2686. str.Format(TXT_FAILED_IN_FUNC_s_WITH_s_AND_s_s_d, funcName, arg1, arg2, errorNames[-err], err);
  2687. else
  2688. str.Format(TXT_FAILED_IN_FUNC_s_WITH_s_s_d, funcName, arg1, errorNames[-err], err);
  2689. }
  2690. else
  2691. str.Format(TXT_FAILED_IN_FUNC_s_s_d, funcName, errorNames[-err], err);
  2692. WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  2693. }
  2694. return err;
  2695. }
  2696. // interface
  2697. int asCScriptEngine::RegisterDefaultArrayType(const char *type)
  2698. {
  2699. asCBuilder bld(this, 0);
  2700. asCDataType dt;
  2701. int r = bld.ParseDataType(type, &dt, defaultNamespace);
  2702. if( r < 0 ) return r;
  2703. if( dt.GetTypeInfo() == 0 ||
  2704. !(dt.GetTypeInfo()->GetFlags() & asOBJ_TEMPLATE) )
  2705. return asINVALID_TYPE;
  2706. defaultArrayObjectType = CastToObjectType(dt.GetTypeInfo());
  2707. defaultArrayObjectType->AddRefInternal();
  2708. return 0;
  2709. }
  2710. // interface
  2711. int asCScriptEngine::GetDefaultArrayTypeId() const
  2712. {
  2713. if( defaultArrayObjectType )
  2714. return GetTypeIdFromDataType(asCDataType::CreateType(defaultArrayObjectType, false));
  2715. return asINVALID_TYPE;
  2716. }
  2717. // interface
  2718. int asCScriptEngine::RegisterStringFactory(const char *datatype, asIStringFactory *factory)
  2719. {
  2720. if (factory == 0)
  2721. return ConfigError(asINVALID_ARG, "RegisterStringFactory", datatype, 0);
  2722. // Parse the data type
  2723. asCBuilder bld(this, 0);
  2724. asCDataType dt;
  2725. int r = bld.ParseDataType(datatype, &dt, defaultNamespace, true);
  2726. if (r < 0)
  2727. return ConfigError(asINVALID_TYPE, "RegisterStringFactory", datatype, 0);
  2728. // Validate the type. It must not be reference or handle
  2729. if (dt.IsReference() || dt.IsObjectHandle())
  2730. return ConfigError(asINVALID_TYPE, "RegisterStringFactory", datatype, 0);
  2731. // All string literals will be treated as const
  2732. dt.MakeReadOnly(true);
  2733. stringType = dt;
  2734. stringFactory = factory;
  2735. return asSUCCESS;
  2736. }
  2737. // interface
  2738. int asCScriptEngine::GetStringFactoryReturnTypeId(asDWORD *flags) const
  2739. {
  2740. if( stringFactory == 0 )
  2741. return asNO_FUNCTION;
  2742. if( flags )
  2743. *flags = 0;
  2744. return GetTypeIdFromDataType(stringType);
  2745. }
  2746. // internal
  2747. asCModule *asCScriptEngine::GetModule(const char *name, bool create)
  2748. {
  2749. // Accept null as well as zero-length string
  2750. if( name == 0 ) name = "";
  2751. asCModule *retModule = 0;
  2752. ACQUIRESHARED(engineRWLock);
  2753. if( lastModule && lastModule->m_name == name )
  2754. retModule = lastModule;
  2755. else
  2756. {
  2757. // TODO: optimize: Improve linear search
  2758. for( asUINT n = 0; n < scriptModules.GetLength(); ++n )
  2759. if( scriptModules[n] && scriptModules[n]->m_name == name )
  2760. {
  2761. retModule = scriptModules[n];
  2762. break;
  2763. }
  2764. }
  2765. RELEASESHARED(engineRWLock);
  2766. if( retModule )
  2767. {
  2768. ACQUIREEXCLUSIVE(engineRWLock);
  2769. lastModule = retModule;
  2770. RELEASEEXCLUSIVE(engineRWLock);
  2771. return retModule;
  2772. }
  2773. if( create )
  2774. {
  2775. retModule = asNEW(asCModule)(name, this);
  2776. if( retModule == 0 )
  2777. {
  2778. // Out of memory
  2779. return 0;
  2780. }
  2781. ACQUIREEXCLUSIVE(engineRWLock);
  2782. scriptModules.PushLast(retModule);
  2783. lastModule = retModule;
  2784. RELEASEEXCLUSIVE(engineRWLock);
  2785. }
  2786. return retModule;
  2787. }
  2788. asCModule *asCScriptEngine::GetModuleFromFuncId(int id)
  2789. {
  2790. if( id < 0 ) return 0;
  2791. if( id >= (int)scriptFunctions.GetLength() ) return 0;
  2792. asCScriptFunction *func = scriptFunctions[id];
  2793. if( func == 0 ) return 0;
  2794. return func->module;
  2795. }
  2796. // internal
  2797. int asCScriptEngine::RequestBuild()
  2798. {
  2799. ACQUIREEXCLUSIVE(engineRWLock);
  2800. if( isBuilding )
  2801. {
  2802. RELEASEEXCLUSIVE(engineRWLock);
  2803. return asBUILD_IN_PROGRESS;
  2804. }
  2805. isBuilding = true;
  2806. RELEASEEXCLUSIVE(engineRWLock);
  2807. return 0;
  2808. }
  2809. // internal
  2810. void asCScriptEngine::BuildCompleted()
  2811. {
  2812. // Always free up pooled memory after a completed build
  2813. memoryMgr.FreeUnusedMemory();
  2814. isBuilding = false;
  2815. }
  2816. void asCScriptEngine::RemoveTemplateInstanceType(asCObjectType *t)
  2817. {
  2818. // If there is a module that still owns the generated type, then don't remove it
  2819. if( t->module )
  2820. return;
  2821. // Don't remove it if there are external refernces
  2822. if( t->externalRefCount.get() )
  2823. return;
  2824. // Only remove the template instance type if no config group is using it
  2825. if( defaultGroup.generatedTemplateInstances.Exists(t) )
  2826. return;
  2827. for( asUINT n = 0; n < configGroups.GetLength(); n++ )
  2828. if( configGroups[n]->generatedTemplateInstances.Exists(t) )
  2829. return;
  2830. t->DestroyInternal();
  2831. templateInstanceTypes.RemoveValue(t);
  2832. generatedTemplateTypes.RemoveValue(t);
  2833. t->ReleaseInternal();
  2834. }
  2835. // internal
  2836. asCObjectType *asCScriptEngine::GetTemplateInstanceType(asCObjectType *templateType, asCArray<asCDataType> &subTypes, asCModule *requestingModule)
  2837. {
  2838. asUINT n;
  2839. // Is there any template instance type or template specialization already with this subtype?
  2840. for( n = 0; n < templateInstanceTypes.GetLength(); n++ )
  2841. {
  2842. asCObjectType *type = templateInstanceTypes[n];
  2843. if( type &&
  2844. type->name == templateType->name &&
  2845. type->nameSpace == templateType->nameSpace &&
  2846. type->templateSubTypes == subTypes )
  2847. {
  2848. // If the template instance is generated, then the module should hold a reference
  2849. // to it so the config group can determine see that the template type is in use.
  2850. // Template specializations will be treated as normal types
  2851. if( requestingModule && generatedTemplateTypes.Exists(type) )
  2852. {
  2853. if( type->module == 0 )
  2854. {
  2855. // Set the ownership of this template type
  2856. // It may be without ownership if it was previously created from application with for example GetTypeInfoByDecl
  2857. type->module = requestingModule;
  2858. }
  2859. if( !requestingModule->m_templateInstances.Exists(type) )
  2860. {
  2861. requestingModule->m_templateInstances.PushLast(type);
  2862. type->AddRefInternal();
  2863. }
  2864. }
  2865. return templateInstanceTypes[n];
  2866. }
  2867. }
  2868. // No previous template instance exists
  2869. // Make sure this template supports the subtype
  2870. for( n = 0; n < subTypes.GetLength(); n++ )
  2871. {
  2872. if( !templateType->acceptValueSubType && (subTypes[n].IsPrimitive() || (subTypes[n].GetTypeInfo()->flags & asOBJ_VALUE)) )
  2873. return 0;
  2874. if( !templateType->acceptRefSubType && (subTypes[n].IsObject() && (subTypes[n].GetTypeInfo()->flags & asOBJ_REF)) )
  2875. return 0;
  2876. }
  2877. // Create a new template instance type based on the templateType
  2878. asCObjectType *ot = asNEW(asCObjectType)(this);
  2879. if( ot == 0 )
  2880. {
  2881. // Out of memory
  2882. return 0;
  2883. }
  2884. ot->templateSubTypes = subTypes;
  2885. ot->flags = templateType->flags;
  2886. ot->size = templateType->size;
  2887. ot->name = templateType->name;
  2888. ot->nameSpace = templateType->nameSpace;
  2889. // If the template is being requested from a module, then the module should hold a reference to the type
  2890. if( requestingModule )
  2891. {
  2892. // Set the ownership of this template type
  2893. ot->module = requestingModule;
  2894. requestingModule->m_templateInstances.PushLast(ot);
  2895. ot->AddRefInternal();
  2896. }
  2897. else
  2898. {
  2899. // If the template type is not requested directly from a module, then set the ownership
  2900. // of it to the same module as one of the subtypes. If none of the subtypes are owned by]
  2901. // any module, the template instance will be without ownership and can be removed from the
  2902. // engine at any time (unless the application holds an external reference).
  2903. for( n = 0; n < subTypes.GetLength(); n++ )
  2904. {
  2905. if( subTypes[n].GetTypeInfo() )
  2906. {
  2907. ot->module = subTypes[n].GetTypeInfo()->module;
  2908. if( ot->module )
  2909. {
  2910. ot->module->m_templateInstances.PushLast(ot);
  2911. ot->AddRefInternal();
  2912. break;
  2913. }
  2914. }
  2915. }
  2916. }
  2917. // Before filling in the methods, call the template instance callback behaviour to validate the type
  2918. if( templateType->beh.templateCallback )
  2919. {
  2920. // If the validation is deferred then the validation will be done later,
  2921. // so it is necessary to continue the preparation of the template instance type
  2922. if( !deferValidationOfTemplateTypes )
  2923. {
  2924. asCScriptFunction *callback = scriptFunctions[templateType->beh.templateCallback];
  2925. bool dontGarbageCollect = false;
  2926. if( !CallGlobalFunctionRetBool(ot, &dontGarbageCollect, callback->sysFuncIntf, callback) )
  2927. {
  2928. // The type cannot be instantiated
  2929. ot->templateSubTypes.SetLength(0);
  2930. if( ot->module )
  2931. {
  2932. ot->module->m_templateInstances.RemoveValue(ot);
  2933. ot->ReleaseInternal();
  2934. }
  2935. ot->ReleaseInternal();
  2936. return 0;
  2937. }
  2938. // If the callback said this template instance won't be garbage collected then remove the flag
  2939. if( dontGarbageCollect )
  2940. ot->flags &= ~asOBJ_GC;
  2941. }
  2942. ot->beh.templateCallback = templateType->beh.templateCallback;
  2943. scriptFunctions[ot->beh.templateCallback]->AddRefInternal();
  2944. }
  2945. ot->methods = templateType->methods;
  2946. for( n = 0; n < ot->methods.GetLength(); n++ )
  2947. scriptFunctions[ot->methods[n]]->AddRefInternal();
  2948. if( templateType->flags & asOBJ_REF )
  2949. {
  2950. // Store the real factory in the constructor. This is used by the CreateScriptObject function.
  2951. // Otherwise it wouldn't be necessary to store the real factory ids.
  2952. ot->beh.construct = templateType->beh.factory;
  2953. ot->beh.constructors = templateType->beh.factories;
  2954. }
  2955. else
  2956. {
  2957. ot->beh.construct = templateType->beh.construct;
  2958. ot->beh.constructors = templateType->beh.constructors;
  2959. }
  2960. for( n = 0; n < ot->beh.constructors.GetLength(); n++ )
  2961. scriptFunctions[ot->beh.constructors[n]]->AddRefInternal();
  2962. // Before proceeding with the generation of the template functions for the template instance it is necessary
  2963. // to include the new template instance type in the list of known types, otherwise it is possible that we get
  2964. // a infinite recursive loop as the template instance type is requested again during the generation of the
  2965. // template functions.
  2966. templateInstanceTypes.PushLast(ot);
  2967. // Store the template instance types that have been created automatically by the engine from a template type
  2968. // The object types in templateInstanceTypes that are not also in generatedTemplateTypes are registered template specializations
  2969. generatedTemplateTypes.PushLast(ot);
  2970. // Any child funcdefs must be copied to the template instance (with adjustments in case of template subtypes)
  2971. // This must be done before resolving other methods, to make sure the other methods that may refer to the
  2972. // templated funcdef will resolve to the new funcdef
  2973. for (n = 0; n < templateType->childFuncDefs.GetLength(); n++)
  2974. {
  2975. asCFuncdefType *funcdef = GenerateNewTemplateFuncdef(templateType, ot, templateType->childFuncDefs[n]);
  2976. funcdef->parentClass = ot;
  2977. ot->childFuncDefs.PushLast(funcdef);
  2978. }
  2979. // As the new template type is instantiated the engine should
  2980. // generate new functions to substitute the ones with the template subtype.
  2981. for( n = 0; n < ot->beh.constructors.GetLength(); n++ )
  2982. {
  2983. int funcId = ot->beh.constructors[n];
  2984. asCScriptFunction *func = scriptFunctions[funcId];
  2985. if( GenerateNewTemplateFunction(templateType, ot, func, &func) )
  2986. {
  2987. // Release the old function, the new one already has its ref count set to 1
  2988. scriptFunctions[funcId]->ReleaseInternal();
  2989. ot->beh.constructors[n] = func->id;
  2990. if( ot->beh.construct == funcId )
  2991. ot->beh.construct = func->id;
  2992. }
  2993. }
  2994. ot->beh.factory = 0;
  2995. if( templateType->flags & asOBJ_REF )
  2996. {
  2997. // Generate factory stubs for each of the factories
  2998. for( n = 0; n < ot->beh.constructors.GetLength(); n++ )
  2999. {
  3000. asCScriptFunction *func = GenerateTemplateFactoryStub(templateType, ot, ot->beh.constructors[n]);
  3001. ot->beh.factories.PushLast(func->id);
  3002. // Set the default factory as well
  3003. if( ot->beh.constructors[n] == ot->beh.construct )
  3004. ot->beh.factory = func->id;
  3005. }
  3006. }
  3007. else
  3008. {
  3009. // Generate factory stubs for each of the constructors
  3010. for( n = 0; n < ot->beh.constructors.GetLength(); n++ )
  3011. {
  3012. asCScriptFunction *func = GenerateTemplateFactoryStub(templateType, ot, ot->beh.constructors[n]);
  3013. if( ot->beh.constructors[n] == ot->beh.construct )
  3014. ot->beh.construct = func->id;
  3015. // Release previous constructor
  3016. scriptFunctions[ot->beh.constructors[n]]->ReleaseInternal();
  3017. ot->beh.constructors[n] = func->id;
  3018. }
  3019. }
  3020. // Generate stub for the list factory as well
  3021. if( templateType->beh.listFactory )
  3022. {
  3023. asCScriptFunction *func = GenerateTemplateFactoryStub(templateType, ot, templateType->beh.listFactory);
  3024. // Rename the function to easily identify it in LoadByteCode
  3025. func->name = "$list";
  3026. ot->beh.listFactory = func->id;
  3027. }
  3028. // Create new template functions for behaviours that may need to know the new object type id
  3029. int funcId = templateType->beh.destruct;
  3030. asCScriptFunction* func = scriptFunctions[funcId];
  3031. if (func && GenerateNewTemplateFunction(templateType, ot, func, &func))
  3032. ot->beh.destruct = func->id;
  3033. else
  3034. {
  3035. ot->beh.destruct = templateType->beh.destruct;
  3036. if (scriptFunctions[ot->beh.destruct]) scriptFunctions[ot->beh.destruct]->AddRefInternal();
  3037. }
  3038. funcId = templateType->beh.copy;
  3039. func = scriptFunctions[funcId];
  3040. if (func && GenerateNewTemplateFunction(templateType, ot, func, &func))
  3041. ot->beh.copy = func->id;
  3042. else
  3043. {
  3044. ot->beh.copy = templateType->beh.copy;
  3045. if (scriptFunctions[ot->beh.copy]) scriptFunctions[ot->beh.copy]->AddRefInternal();
  3046. }
  3047. funcId = templateType->beh.gcEnumReferences;
  3048. func = scriptFunctions[funcId];
  3049. if (func && GenerateNewTemplateFunction(templateType, ot, func, &func))
  3050. ot->beh.gcEnumReferences = func->id;
  3051. else
  3052. {
  3053. ot->beh.gcEnumReferences = templateType->beh.gcEnumReferences;
  3054. if (scriptFunctions[ot->beh.gcEnumReferences]) scriptFunctions[ot->beh.gcEnumReferences]->AddRefInternal();
  3055. }
  3056. funcId = templateType->beh.gcReleaseAllReferences;
  3057. func = scriptFunctions[funcId];
  3058. if (func && GenerateNewTemplateFunction(templateType, ot, func, &func))
  3059. ot->beh.gcReleaseAllReferences = func->id;
  3060. else
  3061. {
  3062. ot->beh.gcReleaseAllReferences = templateType->beh.gcReleaseAllReferences;
  3063. if (scriptFunctions[ot->beh.gcReleaseAllReferences]) scriptFunctions[ot->beh.gcReleaseAllReferences]->AddRefInternal();
  3064. }
  3065. // For the last behaviours no unique copy is generated. It is not expected that
  3066. // anyone will need to see the correct objectType for these to implement them
  3067. ot->beh.addref = templateType->beh.addref;
  3068. if( scriptFunctions[ot->beh.addref] ) scriptFunctions[ot->beh.addref]->AddRefInternal();
  3069. ot->beh.release = templateType->beh.release;
  3070. if( scriptFunctions[ot->beh.release] ) scriptFunctions[ot->beh.release]->AddRefInternal();
  3071. ot->beh.gcGetRefCount = templateType->beh.gcGetRefCount;
  3072. if( scriptFunctions[ot->beh.gcGetRefCount] ) scriptFunctions[ot->beh.gcGetRefCount]->AddRefInternal();
  3073. ot->beh.gcSetFlag = templateType->beh.gcSetFlag;
  3074. if( scriptFunctions[ot->beh.gcSetFlag] ) scriptFunctions[ot->beh.gcSetFlag]->AddRefInternal();
  3075. ot->beh.gcGetFlag = templateType->beh.gcGetFlag;
  3076. if( scriptFunctions[ot->beh.gcGetFlag] ) scriptFunctions[ot->beh.gcGetFlag]->AddRefInternal();
  3077. ot->beh.getWeakRefFlag = templateType->beh.getWeakRefFlag;
  3078. if( scriptFunctions[ot->beh.getWeakRefFlag] ) scriptFunctions[ot->beh.getWeakRefFlag]->AddRefInternal();
  3079. // As the new template type is instantiated, the engine should
  3080. // generate new functions to substitute the ones with the template subtype.
  3081. for( n = 0; n < ot->methods.GetLength(); n++ )
  3082. {
  3083. funcId = ot->methods[n];
  3084. func = scriptFunctions[funcId];
  3085. if( GenerateNewTemplateFunction(templateType, ot, func, &func) )
  3086. {
  3087. // Release the old function, the new one already has its ref count set to 1
  3088. scriptFunctions[funcId]->ReleaseInternal();
  3089. ot->methods[n] = func->id;
  3090. }
  3091. }
  3092. // Increase ref counter for sub type if it is an object type
  3093. for( n = 0; n < ot->templateSubTypes.GetLength(); n++ )
  3094. if( ot->templateSubTypes[n].GetTypeInfo() )
  3095. ot->templateSubTypes[n].GetTypeInfo()->AddRefInternal();
  3096. // Copy the properties to the template instance
  3097. for( n = 0; n < templateType->properties.GetLength(); n++ )
  3098. {
  3099. asCObjectProperty *prop = templateType->properties[n];
  3100. ot->properties.PushLast(asNEW(asCObjectProperty)(*prop));
  3101. if( prop->type.GetTypeInfo() )
  3102. prop->type.GetTypeInfo()->AddRefInternal();
  3103. }
  3104. return ot;
  3105. }
  3106. // interface
  3107. asILockableSharedBool *asCScriptEngine::GetWeakRefFlagOfScriptObject(void *obj, const asITypeInfo *type) const
  3108. {
  3109. // Make sure it is not a null pointer
  3110. if( obj == 0 || type == 0 ) return 0;
  3111. const asCObjectType *objType = static_cast<const asCObjectType *>(type);
  3112. asILockableSharedBool *dest = 0;
  3113. if( objType->beh.getWeakRefFlag )
  3114. {
  3115. // Call the getweakrefflag behaviour
  3116. dest = reinterpret_cast<asILockableSharedBool*>(CallObjectMethodRetPtr(obj, objType->beh.getWeakRefFlag));
  3117. }
  3118. return dest;
  3119. }
  3120. // internal
  3121. // orig is the parameter type that is to be replaced
  3122. // tmpl is the registered template. Used to find which subtype is being replaced
  3123. // ot is the new template instance that is being created. Used to find the target type
  3124. asCDataType asCScriptEngine::DetermineTypeForTemplate(const asCDataType &orig, asCObjectType *tmpl, asCObjectType *ot)
  3125. {
  3126. asCDataType dt;
  3127. if( orig.GetTypeInfo() && (orig.GetTypeInfo()->flags & asOBJ_TEMPLATE_SUBTYPE) )
  3128. {
  3129. bool found = false;
  3130. for( asUINT n = 0; n < tmpl->templateSubTypes.GetLength(); n++ )
  3131. {
  3132. if( orig.GetTypeInfo() == tmpl->templateSubTypes[n].GetTypeInfo() )
  3133. {
  3134. found = true;
  3135. dt = ot->templateSubTypes[n];
  3136. if( orig.IsObjectHandle() && !ot->templateSubTypes[n].IsObjectHandle() )
  3137. {
  3138. dt.MakeHandle(true, true);
  3139. asASSERT(dt.IsObjectHandle());
  3140. if( orig.IsHandleToConst() )
  3141. dt.MakeHandleToConst(true);
  3142. dt.MakeReference(orig.IsReference());
  3143. dt.MakeReadOnly(orig.IsReadOnly());
  3144. }
  3145. else
  3146. {
  3147. // The target type is a handle, then check if the application
  3148. // wants this handle to be to a const object. This is done by
  3149. // flagging the type with 'if_handle_then_const' in the declaration.
  3150. if (dt.IsObjectHandle() && orig.HasIfHandleThenConst())
  3151. dt.MakeHandleToConst(true);
  3152. dt.MakeReference(orig.IsReference());
  3153. dt.MakeReadOnly(ot->templateSubTypes[n].IsReadOnly() || orig.IsReadOnly());
  3154. // If the target is a @& then don't make the handle const,
  3155. // as it is not possible to declare functions with @const &
  3156. if (orig.IsReference() && dt.IsObjectHandle())
  3157. dt.MakeReadOnly(false);
  3158. }
  3159. break;
  3160. }
  3161. }
  3162. asASSERT( found );
  3163. UNUSED_VAR( found );
  3164. }
  3165. else if( orig.GetTypeInfo() == tmpl )
  3166. {
  3167. if( orig.IsObjectHandle() )
  3168. dt = asCDataType::CreateObjectHandle(ot, false);
  3169. else
  3170. dt = asCDataType::CreateType(ot, false);
  3171. dt.MakeReference(orig.IsReference());
  3172. dt.MakeReadOnly(orig.IsReadOnly());
  3173. }
  3174. else if( orig.GetTypeInfo() && (orig.GetTypeInfo()->flags & asOBJ_TEMPLATE) )
  3175. {
  3176. // The type is itself a template, so it is necessary to find the correct template instance type
  3177. asCArray<asCDataType> tmplSubTypes;
  3178. asCObjectType *origType = CastToObjectType(orig.GetTypeInfo());
  3179. bool needInstance = true;
  3180. // Find the matching replacements for the subtypes
  3181. for( asUINT n = 0; n < origType->templateSubTypes.GetLength(); n++ )
  3182. {
  3183. if( origType->templateSubTypes[n].GetTypeInfo() == 0 ||
  3184. !(origType->templateSubTypes[n].GetTypeInfo()->flags & asOBJ_TEMPLATE_SUBTYPE) )
  3185. {
  3186. // The template is already an instance so we shouldn't attempt to create another instance
  3187. needInstance = false;
  3188. break;
  3189. }
  3190. for( asUINT m = 0; m < tmpl->templateSubTypes.GetLength(); m++ )
  3191. if( origType->templateSubTypes[n].GetTypeInfo() == tmpl->templateSubTypes[m].GetTypeInfo() )
  3192. tmplSubTypes.PushLast(ot->templateSubTypes[m]);
  3193. if( tmplSubTypes.GetLength() != n+1 )
  3194. {
  3195. asASSERT( false );
  3196. return orig;
  3197. }
  3198. }
  3199. asCObjectType *ntype = origType;
  3200. if( needInstance )
  3201. {
  3202. // Always find the original template type when creating a new template instance otherwise the
  3203. // generation will fail since it will attempt to create factory stubs when they already exists, etc
  3204. for( asUINT n = 0; n < registeredTemplateTypes.GetLength(); n++ )
  3205. if( registeredTemplateTypes[n]->name == origType->name &&
  3206. registeredTemplateTypes[n]->nameSpace == origType->nameSpace )
  3207. {
  3208. origType = registeredTemplateTypes[n];
  3209. break;
  3210. }
  3211. ntype = GetTemplateInstanceType(origType, tmplSubTypes, ot->module);
  3212. if( ntype == 0 )
  3213. {
  3214. // It not possible to instantiate the subtype
  3215. asASSERT( false );
  3216. ntype = tmpl;
  3217. }
  3218. }
  3219. if( orig.IsObjectHandle() )
  3220. dt = asCDataType::CreateObjectHandle(ntype, false);
  3221. else
  3222. dt = asCDataType::CreateType(ntype, false);
  3223. dt.MakeReference(orig.IsReference());
  3224. dt.MakeReadOnly(orig.IsReadOnly());
  3225. }
  3226. else if (orig.GetTypeInfo() && (orig.GetTypeInfo()->flags & asOBJ_FUNCDEF) && CastToFuncdefType(orig.GetTypeInfo())->parentClass == tmpl)
  3227. {
  3228. // The type is a child funcdef. Find the corresponding child funcdef in the template instance
  3229. for (asUINT n = 0; n < ot->childFuncDefs.GetLength(); n++)
  3230. {
  3231. if (ot->childFuncDefs[n]->name == orig.GetTypeInfo()->name)
  3232. {
  3233. dt = orig;
  3234. dt.SetTypeInfo(ot->childFuncDefs[n]);
  3235. }
  3236. }
  3237. }
  3238. else
  3239. dt = orig;
  3240. return dt;
  3241. }
  3242. // internal
  3243. asCScriptFunction *asCScriptEngine::GenerateTemplateFactoryStub(asCObjectType *templateType, asCObjectType *ot, int factoryId)
  3244. {
  3245. asCScriptFunction *factory = scriptFunctions[factoryId];
  3246. // By first instantiating the function as a dummy and then changing it to be a script function
  3247. // I avoid having it added to the garbage collector. As it is known that this object will stay
  3248. // alive until the template instance is no longer used there is no need to have the GC check
  3249. // this function all the time.
  3250. asCScriptFunction *func = asNEW(asCScriptFunction)(this, 0, asFUNC_DUMMY);
  3251. if( func == 0 )
  3252. {
  3253. // Out of memory
  3254. return 0;
  3255. }
  3256. func->funcType = asFUNC_SCRIPT;
  3257. func->AllocateScriptFunctionData();
  3258. func->id = GetNextScriptFunctionId();
  3259. AddScriptFunction(func);
  3260. func->traits = factory->traits;
  3261. func->SetShared(true);
  3262. if( templateType->flags & asOBJ_REF )
  3263. {
  3264. func->name = "$fact";
  3265. func->returnType = asCDataType::CreateObjectHandle(ot, false);
  3266. }
  3267. else
  3268. {
  3269. func->name = "$beh0";
  3270. func->returnType = factory->returnType; // constructors return nothing
  3271. func->objectType = ot;
  3272. func->objectType->AddRefInternal();
  3273. }
  3274. // Skip the first parameter as this is the object type pointer that the stub will add
  3275. func->parameterTypes.SetLength(factory->parameterTypes.GetLength()-1);
  3276. func->parameterNames.SetLength(factory->parameterNames.GetLength()-1);
  3277. func->inOutFlags.SetLength(factory->inOutFlags.GetLength()-1);
  3278. func->defaultArgs.SetLength(factory->defaultArgs.GetLength()-1);
  3279. for( asUINT p = 1; p < factory->parameterTypes.GetLength(); p++ )
  3280. {
  3281. func->parameterTypes[p-1] = factory->parameterTypes[p];
  3282. func->parameterNames[p-1] = factory->parameterNames[p];
  3283. func->inOutFlags[p-1] = factory->inOutFlags[p];
  3284. func->defaultArgs[p-1] = factory->defaultArgs[p] ? asNEW(asCString)(*factory->defaultArgs[p]) : 0;
  3285. }
  3286. // Generate the bytecode for the factory stub
  3287. asUINT bcLength = asBCTypeSize[asBCInfo[asBC_OBJTYPE].type] +
  3288. asBCTypeSize[asBCInfo[asBC_CALLSYS].type] +
  3289. asBCTypeSize[asBCInfo[asBC_RET].type];
  3290. if( ep.includeJitInstructions )
  3291. bcLength += asBCTypeSize[asBCInfo[asBC_JitEntry].type];
  3292. if( templateType->flags & asOBJ_VALUE )
  3293. bcLength += asBCTypeSize[asBCInfo[asBC_SwapPtr].type];
  3294. func->scriptData->byteCode.SetLength(bcLength);
  3295. asDWORD *bc = func->scriptData->byteCode.AddressOf();
  3296. if( ep.includeJitInstructions )
  3297. {
  3298. *(asBYTE*)bc = asBC_JitEntry;
  3299. *(asPWORD*)(bc+1) = 0;
  3300. bc += asBCTypeSize[asBCInfo[asBC_JitEntry].type];
  3301. }
  3302. *(asBYTE*)bc = asBC_OBJTYPE;
  3303. *(asPWORD*)(bc+1) = (asPWORD)ot;
  3304. bc += asBCTypeSize[asBCInfo[asBC_OBJTYPE].type];
  3305. if( templateType->flags & asOBJ_VALUE )
  3306. {
  3307. // Swap the object pointer with the object type
  3308. *(asBYTE*)bc = asBC_SwapPtr;
  3309. bc += asBCTypeSize[asBCInfo[asBC_SwapPtr].type];
  3310. }
  3311. *(asBYTE*)bc = asBC_CALLSYS;
  3312. *(asDWORD*)(bc+1) = factoryId;
  3313. bc += asBCTypeSize[asBCInfo[asBC_CALLSYS].type];
  3314. *(asBYTE*)bc = asBC_RET;
  3315. *(((asWORD*)bc)+1) = (asWORD)func->GetSpaceNeededForArguments() + (func->objectType ? AS_PTR_SIZE : 0);
  3316. func->AddReferences();
  3317. func->scriptData->stackNeeded = AS_PTR_SIZE;
  3318. // Tell the virtual machine not to clean up the object on exception
  3319. func->dontCleanUpOnException = true;
  3320. func->JITCompile();
  3321. // Need to translate the list pattern too so the VM and compiler will know the correct type of the members
  3322. if( factory->listPattern )
  3323. {
  3324. asSListPatternNode *n = factory->listPattern;
  3325. asSListPatternNode *last = 0;
  3326. while( n )
  3327. {
  3328. asSListPatternNode *newNode = n->Duplicate();
  3329. if( newNode->type == asLPT_TYPE )
  3330. {
  3331. asSListPatternDataTypeNode *typeNode = reinterpret_cast<asSListPatternDataTypeNode*>(newNode);
  3332. typeNode->dataType = DetermineTypeForTemplate(typeNode->dataType, templateType, ot);
  3333. }
  3334. if( last )
  3335. last->next = newNode;
  3336. else
  3337. func->listPattern = newNode;
  3338. last = newNode;
  3339. n = n->next;
  3340. }
  3341. }
  3342. return func;
  3343. }
  3344. bool asCScriptEngine::RequireTypeReplacement(asCDataType &type, asCObjectType *templateType)
  3345. {
  3346. if( type.GetTypeInfo() == templateType ) return true;
  3347. if( type.GetTypeInfo() && (type.GetTypeInfo()->flags & asOBJ_TEMPLATE_SUBTYPE) ) return true;
  3348. if( type.GetTypeInfo() && (type.GetTypeInfo()->flags & asOBJ_TEMPLATE) )
  3349. {
  3350. asCObjectType *ot = CastToObjectType(type.GetTypeInfo());
  3351. for( asUINT n = 0; n < ot->templateSubTypes.GetLength(); n++ )
  3352. if( ot->templateSubTypes[n].GetTypeInfo() &&
  3353. ot->templateSubTypes[n].GetTypeInfo()->flags & asOBJ_TEMPLATE_SUBTYPE )
  3354. return true;
  3355. }
  3356. if (type.GetTypeInfo() && (type.GetTypeInfo()->flags & asOBJ_FUNCDEF) && CastToFuncdefType(type.GetTypeInfo())->parentClass == templateType)
  3357. return true;
  3358. return false;
  3359. }
  3360. bool asCScriptEngine::GenerateNewTemplateFunction(asCObjectType *templateType, asCObjectType *ot, asCScriptFunction *func, asCScriptFunction **newFunc)
  3361. {
  3362. // Due to the objectType it is always required to generate a new function,
  3363. // even if none of the function arguments needs to be changed.
  3364. /*
  3365. // TODO: Can we store the new function in some other optimized way to avoid
  3366. // duplicating all information just because of the different objectType member?
  3367. bool needNewFunc = false;
  3368. if( RequireTypeReplacement(func->returnType, templateType) )
  3369. needNewFunc = true;
  3370. else
  3371. {
  3372. for( asUINT p = 0; p < func->parameterTypes.GetLength(); p++ )
  3373. {
  3374. if( RequireTypeReplacement(func->parameterTypes[p], templateType) )
  3375. {
  3376. needNewFunc = true;
  3377. break;
  3378. }
  3379. }
  3380. }
  3381. if( !needNewFunc )
  3382. return false;
  3383. */
  3384. asCScriptFunction *func2 = asNEW(asCScriptFunction)(this, 0, func->funcType);
  3385. if( func2 == 0 )
  3386. {
  3387. // Out of memory
  3388. return false;
  3389. }
  3390. func2->name = func->name;
  3391. func2->returnType = DetermineTypeForTemplate(func->returnType, templateType, ot);
  3392. func2->parameterTypes.SetLength(func->parameterTypes.GetLength());
  3393. for (asUINT p = 0; p < func->parameterTypes.GetLength(); p++)
  3394. func2->parameterTypes[p] = DetermineTypeForTemplate(func->parameterTypes[p], templateType, ot);
  3395. for (asUINT n = 0; n < func->defaultArgs.GetLength(); n++)
  3396. if (func->defaultArgs[n])
  3397. func2->defaultArgs.PushLast(asNEW(asCString)(*func->defaultArgs[n]));
  3398. else
  3399. func2->defaultArgs.PushLast(0);
  3400. // TODO: template: Must be careful when instantiating templates for garbage collected types
  3401. // If the template hasn't been registered with the behaviours, it shouldn't
  3402. // permit instantiation of garbage collected types that in turn may refer to
  3403. // this instance.
  3404. func2->parameterNames = func->parameterNames;
  3405. func2->inOutFlags = func->inOutFlags;
  3406. func2->traits = func->traits;
  3407. func2->SetReadOnly(func->IsReadOnly());
  3408. func2->objectType = ot;
  3409. func2->objectType->AddRefInternal();
  3410. func2->sysFuncIntf = asNEW(asSSystemFunctionInterface)(*func->sysFuncIntf);
  3411. // Adjust the clean up instructions
  3412. if( func2->sysFuncIntf->callConv == ICC_GENERIC_FUNC ||
  3413. func2->sysFuncIntf->callConv == ICC_GENERIC_METHOD )
  3414. PrepareSystemFunctionGeneric(func2, func2->sysFuncIntf, this);
  3415. else
  3416. PrepareSystemFunction(func2, func2->sysFuncIntf, this);
  3417. func2->id = GetNextScriptFunctionId();
  3418. AddScriptFunction(func2);
  3419. // Return the new function
  3420. *newFunc = func2;
  3421. return true;
  3422. }
  3423. asCFuncdefType *asCScriptEngine::GenerateNewTemplateFuncdef(asCObjectType *templateType, asCObjectType *ot, asCFuncdefType *func)
  3424. {
  3425. // TODO: Only generate the new funcdef if it used the template subtypes.
  3426. // Remember to also update the clean up in asCObjectType::DestroyInternal so it doesn't delete
  3427. // child funcdefs that have not been created specificially for the template instance.
  3428. // Perhaps a new funcdef is always needed, since the funcdef will have a reference to the
  3429. // parent class (in this case the template instance).
  3430. asCScriptFunction *func2 = asNEW(asCScriptFunction)(this, 0, func->funcdef->funcType);
  3431. if (func2 == 0)
  3432. {
  3433. // Out of memory
  3434. return 0;
  3435. }
  3436. func2->name = func->name;
  3437. func2->returnType = DetermineTypeForTemplate(func->funcdef->returnType, templateType, ot);
  3438. func2->parameterTypes.SetLength(func->funcdef->parameterTypes.GetLength());
  3439. for (asUINT p = 0; p < func->funcdef->parameterTypes.GetLength(); p++)
  3440. func2->parameterTypes[p] = DetermineTypeForTemplate(func->funcdef->parameterTypes[p], templateType, ot);
  3441. // TODO: template: Must be careful when instantiating templates for garbage collected types
  3442. // If the template hasn't been registered with the behaviours, it shouldn't
  3443. // permit instantiation of garbage collected types that in turn may refer to
  3444. // this instance.
  3445. func2->inOutFlags = func->funcdef->inOutFlags;
  3446. func2->SetReadOnly(func->funcdef->IsReadOnly());
  3447. asASSERT(func->funcdef->objectType == 0);
  3448. asASSERT(func->funcdef->sysFuncIntf == 0);
  3449. func2->id = GetNextScriptFunctionId();
  3450. AddScriptFunction(func2);
  3451. asCFuncdefType *fdt2 = asNEW(asCFuncdefType)(this, func2);
  3452. funcDefs.PushLast(fdt2); // don't increase refCount as the constructor already set it to 1
  3453. // Return the new function
  3454. return fdt2;
  3455. }
  3456. void asCScriptEngine::CallObjectMethod(void *obj, int func) const
  3457. {
  3458. asCScriptFunction *s = scriptFunctions[func];
  3459. asASSERT( s != 0 );
  3460. CallObjectMethod(obj, s->sysFuncIntf, s);
  3461. }
  3462. void asCScriptEngine::CallObjectMethod(void *obj, asSSystemFunctionInterface *i, asCScriptFunction *s) const
  3463. {
  3464. #if defined(__GNUC__) || defined(AS_PSVITA)
  3465. if( i->callConv == ICC_GENERIC_METHOD )
  3466. {
  3467. asCGeneric gen(const_cast<asCScriptEngine*>(this), s, obj, 0);
  3468. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3469. f(&gen);
  3470. }
  3471. else if( i->callConv == ICC_THISCALL || i->callConv == ICC_VIRTUAL_THISCALL )
  3472. {
  3473. // For virtual thiscalls we must call the method as a true class method
  3474. // so that the compiler will lookup the function address in the vftable
  3475. union
  3476. {
  3477. asSIMPLEMETHOD_t mthd;
  3478. struct
  3479. {
  3480. asFUNCTION_t func;
  3481. asPWORD baseOffset; // Same size as the pointer
  3482. } f;
  3483. } p;
  3484. obj = (void*) ((char*) obj + i->compositeOffset);
  3485. if(i->isCompositeIndirect)
  3486. obj = *((void**)obj);
  3487. p.f.func = (asFUNCTION_t)(i->func);
  3488. p.f.baseOffset = asPWORD(i->baseOffset);
  3489. void (asCSimpleDummy::*f)() = p.mthd;
  3490. (((asCSimpleDummy*)obj)->*f)();
  3491. }
  3492. else /*if( i->callConv == ICC_CDECL_OBJLAST || i->callConv == ICC_CDECL_OBJFIRST )*/
  3493. {
  3494. void (*f)(void *) = (void (*)(void *))(i->func);
  3495. f(obj);
  3496. }
  3497. #else
  3498. #ifndef AS_NO_CLASS_METHODS
  3499. if( i->callConv == ICC_THISCALL )
  3500. {
  3501. union
  3502. {
  3503. asSIMPLEMETHOD_t mthd;
  3504. asFUNCTION_t func;
  3505. } p;
  3506. p.func = (asFUNCTION_t)(i->func);
  3507. void (asCSimpleDummy::*f)() = p.mthd;
  3508. obj = (void*) ((char*) obj + i->compositeOffset);
  3509. if(i->isCompositeIndirect)
  3510. obj = *((void**)obj);
  3511. obj = (void*)(asPWORD(obj) + i->baseOffset);
  3512. (((asCSimpleDummy*)obj)->*f)();
  3513. }
  3514. else
  3515. #endif
  3516. if( i->callConv == ICC_GENERIC_METHOD )
  3517. {
  3518. asCGeneric gen(const_cast<asCScriptEngine*>(this), s, obj, 0);
  3519. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3520. f(&gen);
  3521. }
  3522. else /*if( i->callConv == ICC_CDECL_OBJLAST || i->callConv == ICC_CDECL_OBJFIRST )*/
  3523. {
  3524. void (*f)(void *) = (void (*)(void *))(i->func);
  3525. f(obj);
  3526. }
  3527. #endif
  3528. }
  3529. bool asCScriptEngine::CallObjectMethodRetBool(void *obj, int func) const
  3530. {
  3531. asCScriptFunction *s = scriptFunctions[func];
  3532. asASSERT( s != 0 );
  3533. asSSystemFunctionInterface *i = s->sysFuncIntf;
  3534. #if defined(__GNUC__) || defined(AS_PSVITA)
  3535. if( i->callConv == ICC_GENERIC_METHOD )
  3536. {
  3537. asCGeneric gen(const_cast<asCScriptEngine*>(this), s, obj, 0);
  3538. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3539. f(&gen);
  3540. return *(bool*)gen.GetReturnPointer();
  3541. }
  3542. else if( i->callConv == ICC_THISCALL || i->callConv == ICC_VIRTUAL_THISCALL )
  3543. {
  3544. // For virtual thiscalls we must call the method as a true class method so that the compiler will lookup the function address in the vftable
  3545. union
  3546. {
  3547. asSIMPLEMETHOD_t mthd;
  3548. struct
  3549. {
  3550. asFUNCTION_t func;
  3551. asPWORD baseOffset;
  3552. } f;
  3553. } p;
  3554. obj = (void*) ((char*) obj + i->compositeOffset);
  3555. if(i->isCompositeIndirect)
  3556. obj = *((void**)obj);
  3557. p.f.func = (asFUNCTION_t)(i->func);
  3558. p.f.baseOffset = asPWORD(i->baseOffset);
  3559. bool (asCSimpleDummy::*f)() = (bool (asCSimpleDummy::*)())(p.mthd);
  3560. return (((asCSimpleDummy*)obj)->*f)();
  3561. }
  3562. else /*if( i->callConv == ICC_CDECL_OBJLAST || i->callConv == ICC_CDECL_OBJFIRST )*/
  3563. {
  3564. bool (*f)(void *) = (bool (*)(void *))(i->func);
  3565. return f(obj);
  3566. }
  3567. #else
  3568. #ifndef AS_NO_CLASS_METHODS
  3569. if( i->callConv == ICC_THISCALL )
  3570. {
  3571. union
  3572. {
  3573. asSIMPLEMETHOD_t mthd;
  3574. asFUNCTION_t func;
  3575. } p;
  3576. p.func = (asFUNCTION_t)(i->func);
  3577. bool (asCSimpleDummy::*f)() = (bool (asCSimpleDummy::*)())p.mthd;
  3578. obj = (void*) ((char*) obj + i->compositeOffset);
  3579. if(i->isCompositeIndirect)
  3580. obj = *((void**)obj);
  3581. obj = (void*)(asPWORD(obj) + i->baseOffset);
  3582. return (((asCSimpleDummy*)obj)->*f)();
  3583. }
  3584. else
  3585. #endif
  3586. if( i->callConv == ICC_GENERIC_METHOD )
  3587. {
  3588. asCGeneric gen(const_cast<asCScriptEngine*>(this), s, obj, 0);
  3589. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3590. f(&gen);
  3591. return *(bool*)gen.GetReturnPointer();
  3592. }
  3593. else /*if( i->callConv == ICC_CDECL_OBJLAST || i->callConv == ICC_CDECL_OBJFIRST )*/
  3594. {
  3595. bool (*f)(void *) = (bool (*)(void *))(i->func);
  3596. return f(obj);
  3597. }
  3598. #endif
  3599. }
  3600. int asCScriptEngine::CallObjectMethodRetInt(void *obj, int func) const
  3601. {
  3602. asCScriptFunction *s = scriptFunctions[func];
  3603. asASSERT( s != 0 );
  3604. asSSystemFunctionInterface *i = s->sysFuncIntf;
  3605. #if defined(__GNUC__) || defined(AS_PSVITA)
  3606. if( i->callConv == ICC_GENERIC_METHOD )
  3607. {
  3608. asCGeneric gen(const_cast<asCScriptEngine*>(this), s, obj, 0);
  3609. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3610. f(&gen);
  3611. return *(int*)gen.GetReturnPointer();
  3612. }
  3613. else if( i->callConv == ICC_THISCALL || i->callConv == ICC_VIRTUAL_THISCALL )
  3614. {
  3615. // For virtual thiscalls we must call the method as a true class method so that the compiler will lookup the function address in the vftable
  3616. union
  3617. {
  3618. asSIMPLEMETHOD_t mthd;
  3619. struct
  3620. {
  3621. asFUNCTION_t func;
  3622. asPWORD baseOffset;
  3623. } f;
  3624. } p;
  3625. p.f.func = (asFUNCTION_t)(i->func);
  3626. p.f.baseOffset = asPWORD(i->baseOffset);
  3627. obj = (void*) ((char*) obj + i->compositeOffset);
  3628. if(i->isCompositeIndirect)
  3629. obj = *((void**)obj);
  3630. int (asCSimpleDummy::*f)() = (int (asCSimpleDummy::*)())(p.mthd);
  3631. return (((asCSimpleDummy*)obj)->*f)();
  3632. }
  3633. else /*if( i->callConv == ICC_CDECL_OBJLAST || i->callConv == ICC_CDECL_OBJFIRST )*/
  3634. {
  3635. int (*f)(void *) = (int (*)(void *))(i->func);
  3636. return f(obj);
  3637. }
  3638. #else
  3639. #ifndef AS_NO_CLASS_METHODS
  3640. if( i->callConv == ICC_THISCALL )
  3641. {
  3642. union
  3643. {
  3644. asSIMPLEMETHOD_t mthd;
  3645. asFUNCTION_t func;
  3646. } p;
  3647. p.func = (asFUNCTION_t)(i->func);
  3648. int (asCSimpleDummy::*f)() = (int (asCSimpleDummy::*)())p.mthd;
  3649. obj = (void*) ((char*) obj + i->compositeOffset);
  3650. if(i->isCompositeIndirect)
  3651. obj = *((void**)obj);
  3652. obj = (void*)(asPWORD(obj) + i->baseOffset);
  3653. return (((asCSimpleDummy*)obj)->*f)();
  3654. }
  3655. else
  3656. #endif
  3657. if( i->callConv == ICC_GENERIC_METHOD )
  3658. {
  3659. asCGeneric gen(const_cast<asCScriptEngine*>(this), s, obj, 0);
  3660. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3661. f(&gen);
  3662. return *(int*)gen.GetReturnPointer();
  3663. }
  3664. else /*if( i->callConv == ICC_CDECL_OBJLAST || i->callConv == ICC_CDECL_OBJFIRST )*/
  3665. {
  3666. int (*f)(void *) = (int (*)(void *))(i->func);
  3667. return f(obj);
  3668. }
  3669. #endif
  3670. }
  3671. void *asCScriptEngine::CallObjectMethodRetPtr(void *obj, int func) const
  3672. {
  3673. asCScriptFunction *s = scriptFunctions[func];
  3674. asASSERT( s != 0 );
  3675. asSSystemFunctionInterface *i = s->sysFuncIntf;
  3676. #if defined(__GNUC__) || defined(AS_PSVITA)
  3677. if( i->callConv == ICC_GENERIC_METHOD )
  3678. {
  3679. asCGeneric gen(const_cast<asCScriptEngine*>(this), s, obj, 0);
  3680. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3681. f(&gen);
  3682. return *(void**)gen.GetReturnPointer();
  3683. }
  3684. else if( i->callConv == ICC_THISCALL || i->callConv == ICC_VIRTUAL_THISCALL )
  3685. {
  3686. // For virtual thiscalls we must call the method as a true class method so that the compiler will lookup the function address in the vftable
  3687. union
  3688. {
  3689. asSIMPLEMETHOD_t mthd;
  3690. struct
  3691. {
  3692. asFUNCTION_t func;
  3693. asPWORD baseOffset;
  3694. } f;
  3695. } p;
  3696. p.f.func = (asFUNCTION_t)(i->func);
  3697. p.f.baseOffset = asPWORD(i->baseOffset);
  3698. obj = (void*) ((char*) obj + i->compositeOffset);
  3699. if(i->isCompositeIndirect)
  3700. obj = *((void**)obj);
  3701. void *(asCSimpleDummy::*f)() = (void *(asCSimpleDummy::*)())(p.mthd);
  3702. return (((asCSimpleDummy*)obj)->*f)();
  3703. }
  3704. else /*if( i->callConv == ICC_CDECL_OBJLAST || i->callConv == ICC_CDECL_OBJFIRST )*/
  3705. {
  3706. void *(*f)(void *) = (void *(*)(void *))(i->func);
  3707. return f(obj);
  3708. }
  3709. #else
  3710. #ifndef AS_NO_CLASS_METHODS
  3711. if( i->callConv == ICC_THISCALL )
  3712. {
  3713. union
  3714. {
  3715. asSIMPLEMETHOD_t mthd;
  3716. asFUNCTION_t func;
  3717. } p;
  3718. p.func = (asFUNCTION_t)(i->func);
  3719. void *(asCSimpleDummy::*f)() = (void *(asCSimpleDummy::*)())p.mthd;
  3720. obj = (void*) ((char*) obj + i->compositeOffset);
  3721. if(i->isCompositeIndirect)
  3722. obj = *((void**)obj);
  3723. obj = (void*)(asPWORD(obj) + i->baseOffset);
  3724. return (((asCSimpleDummy*)obj)->*f)();
  3725. }
  3726. else
  3727. #endif
  3728. if( i->callConv == ICC_GENERIC_METHOD )
  3729. {
  3730. asCGeneric gen(const_cast<asCScriptEngine*>(this), s, obj, 0);
  3731. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3732. f(&gen);
  3733. return *(void **)gen.GetReturnPointer();
  3734. }
  3735. else /*if( i->callConv == ICC_CDECL_OBJLAST || i->callConv == ICC_CDECL_OBJFIRST )*/
  3736. {
  3737. void *(*f)(void *) = (void *(*)(void *))(i->func);
  3738. return f(obj);
  3739. }
  3740. #endif
  3741. }
  3742. void *asCScriptEngine::CallObjectMethodRetPtr(void *obj, int param1, asCScriptFunction *func) const
  3743. {
  3744. asASSERT( obj != 0 );
  3745. asASSERT( func != 0 );
  3746. asSSystemFunctionInterface *i = func->sysFuncIntf;
  3747. #ifndef AS_NO_CLASS_METHODS
  3748. if( i->callConv == ICC_THISCALL || i->callConv == ICC_VIRTUAL_THISCALL )
  3749. {
  3750. #if defined(__GNUC__) || defined(AS_PSVITA)
  3751. // For virtual thiscalls we must call the method as a true class method so that the compiler will lookup the function address in the vftable
  3752. union
  3753. {
  3754. asSIMPLEMETHOD_t mthd;
  3755. struct
  3756. {
  3757. asFUNCTION_t func;
  3758. asPWORD baseOffset;
  3759. } f;
  3760. } p;
  3761. p.f.func = (asFUNCTION_t)(i->func);
  3762. p.f.baseOffset = asPWORD(i->baseOffset);
  3763. obj = (void*) ((char*) obj + i->compositeOffset);
  3764. if(i->isCompositeIndirect)
  3765. obj = *((void**)obj);
  3766. void *(asCSimpleDummy::*f)(int) = (void *(asCSimpleDummy::*)(int))(p.mthd);
  3767. return (((asCSimpleDummy*)obj)->*f)(param1);
  3768. #else
  3769. union
  3770. {
  3771. asSIMPLEMETHOD_t mthd;
  3772. asFUNCTION_t func;
  3773. } p;
  3774. p.func = (asFUNCTION_t)(i->func);
  3775. void *(asCSimpleDummy::*f)(int) = (void *(asCSimpleDummy::*)(int))p.mthd;
  3776. obj = (void*) ((char*) obj + i->compositeOffset);
  3777. if(i->isCompositeIndirect)
  3778. obj = *((void**)obj);
  3779. obj = (void*)(asPWORD(obj) + i->baseOffset);
  3780. return (((asCSimpleDummy*)obj)->*f)(param1);
  3781. #endif
  3782. }
  3783. else
  3784. #endif
  3785. if( i->callConv == ICC_GENERIC_METHOD )
  3786. {
  3787. asCGeneric gen(const_cast<asCScriptEngine*>(this), func, obj, reinterpret_cast<asDWORD*>(&param1));
  3788. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3789. f(&gen);
  3790. return *(void **)gen.GetReturnPointer();
  3791. }
  3792. else if( i->callConv == ICC_CDECL_OBJLAST )
  3793. {
  3794. void *(*f)(int, void *) = (void *(*)(int, void *))(i->func);
  3795. return f(param1, obj);
  3796. }
  3797. else /*if( i->callConv == ICC_CDECL_OBJFIRST )*/
  3798. {
  3799. void *(*f)(void *, int) = (void *(*)(void *, int))(i->func);
  3800. return f(obj, param1);
  3801. }
  3802. }
  3803. void *asCScriptEngine::CallGlobalFunctionRetPtr(int func) const
  3804. {
  3805. asCScriptFunction *s = scriptFunctions[func];
  3806. asASSERT( s != 0 );
  3807. return CallGlobalFunctionRetPtr(s->sysFuncIntf, s);
  3808. }
  3809. void *asCScriptEngine::CallGlobalFunctionRetPtr(int func, void *param1) const
  3810. {
  3811. asCScriptFunction *s = scriptFunctions[func];
  3812. asASSERT( s != 0 );
  3813. return CallGlobalFunctionRetPtr(s->sysFuncIntf, s, param1);
  3814. }
  3815. void *asCScriptEngine::CallGlobalFunctionRetPtr(asSSystemFunctionInterface *i, asCScriptFunction *s) const
  3816. {
  3817. if( i->callConv == ICC_CDECL )
  3818. {
  3819. void *(*f)() = (void *(*)())(i->func);
  3820. return f();
  3821. }
  3822. else if( i->callConv == ICC_STDCALL )
  3823. {
  3824. typedef void *(STDCALL *func_t)();
  3825. func_t f = (func_t)(i->func);
  3826. return f();
  3827. }
  3828. else
  3829. {
  3830. asCGeneric gen(const_cast<asCScriptEngine*>(this), s, 0, 0);
  3831. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3832. f(&gen);
  3833. return *(void**)gen.GetReturnPointer();
  3834. }
  3835. }
  3836. void *asCScriptEngine::CallGlobalFunctionRetPtr(asSSystemFunctionInterface *i, asCScriptFunction *s, void *param1) const
  3837. {
  3838. if( i->callConv == ICC_CDECL )
  3839. {
  3840. void *(*f)(void *) = (void *(*)(void *))(i->func);
  3841. return f(param1);
  3842. }
  3843. else if( i->callConv == ICC_STDCALL )
  3844. {
  3845. typedef void *(STDCALL *func_t)(void *);
  3846. func_t f = (func_t)(i->func);
  3847. return f(param1);
  3848. }
  3849. else
  3850. {
  3851. asCGeneric gen(const_cast<asCScriptEngine*>(this), s, 0, (asDWORD*)&param1);
  3852. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3853. f(&gen);
  3854. return *(void**)gen.GetReturnPointer();
  3855. }
  3856. }
  3857. void asCScriptEngine::CallObjectMethod(void *obj, void *param, int func) const
  3858. {
  3859. asCScriptFunction *s = scriptFunctions[func];
  3860. asASSERT( s != 0 );
  3861. CallObjectMethod(obj, param, s->sysFuncIntf, s);
  3862. }
  3863. void asCScriptEngine::CallObjectMethod(void *obj, void *param, asSSystemFunctionInterface *i, asCScriptFunction *s) const
  3864. {
  3865. #if defined(__GNUC__) || defined(AS_PSVITA)
  3866. if( i->callConv == ICC_CDECL_OBJLAST )
  3867. {
  3868. void (*f)(void *, void *) = (void (*)(void *, void *))(i->func);
  3869. f(param, obj);
  3870. }
  3871. else if( i->callConv == ICC_GENERIC_METHOD )
  3872. {
  3873. asCGeneric gen(const_cast<asCScriptEngine*>(this), s, obj, (asDWORD*)&param);
  3874. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3875. f(&gen);
  3876. }
  3877. else if( i->callConv == ICC_VIRTUAL_THISCALL || i->callConv == ICC_THISCALL )
  3878. {
  3879. // For virtual thiscalls we must call the method as a true class method
  3880. // so that the compiler will lookup the function address in the vftable
  3881. union
  3882. {
  3883. asSIMPLEMETHOD_t mthd;
  3884. struct
  3885. {
  3886. asFUNCTION_t func;
  3887. asPWORD baseOffset; // Same size as the pointer
  3888. } f;
  3889. } p;
  3890. p.f.func = (asFUNCTION_t)(i->func);
  3891. p.f.baseOffset = asPWORD(i->baseOffset);
  3892. obj = (void*) ((char*) obj + i->compositeOffset);
  3893. if(i->isCompositeIndirect)
  3894. obj = *((void**)obj);
  3895. void (asCSimpleDummy::*f)(void*) = (void (asCSimpleDummy::*)(void*))(p.mthd);
  3896. (((asCSimpleDummy*)obj)->*f)(param);
  3897. }
  3898. else /*if( i->callConv == ICC_CDECL_OBJFIRST */
  3899. {
  3900. void (*f)(void *, void *) = (void (*)(void *, void *))(i->func);
  3901. f(obj, param);
  3902. }
  3903. #else
  3904. #ifndef AS_NO_CLASS_METHODS
  3905. if( i->callConv == ICC_THISCALL )
  3906. {
  3907. union
  3908. {
  3909. asSIMPLEMETHOD_t mthd;
  3910. asFUNCTION_t func;
  3911. } p;
  3912. p.func = (asFUNCTION_t)(i->func);
  3913. void (asCSimpleDummy::*f)(void *) = (void (asCSimpleDummy::*)(void *))(p.mthd);
  3914. obj = (void*) ((char*) obj + i->compositeOffset);
  3915. if(i->isCompositeIndirect)
  3916. obj = *((void**)obj);
  3917. obj = (void*)(asPWORD(obj) + i->baseOffset);
  3918. (((asCSimpleDummy*)obj)->*f)(param);
  3919. }
  3920. else
  3921. #endif
  3922. if( i->callConv == ICC_CDECL_OBJLAST )
  3923. {
  3924. void (*f)(void *, void *) = (void (*)(void *, void *))(i->func);
  3925. f(param, obj);
  3926. }
  3927. else if( i->callConv == ICC_GENERIC_METHOD )
  3928. {
  3929. asCGeneric gen(const_cast<asCScriptEngine*>(this), s, obj, (asDWORD*)&param);
  3930. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3931. f(&gen);
  3932. }
  3933. else /*if( i->callConv == ICC_CDECL_OBJFIRST )*/
  3934. {
  3935. void (*f)(void *, void *) = (void (*)(void *, void *))(i->func);
  3936. f(obj, param);
  3937. }
  3938. #endif
  3939. }
  3940. void asCScriptEngine::CallGlobalFunction(void *param1, void *param2, asSSystemFunctionInterface *i, asCScriptFunction *s) const
  3941. {
  3942. if( i->callConv == ICC_CDECL )
  3943. {
  3944. void (*f)(void *, void *) = (void (*)(void *, void *))(i->func);
  3945. f(param1, param2);
  3946. }
  3947. else if( i->callConv == ICC_STDCALL )
  3948. {
  3949. typedef void (STDCALL *func_t)(void *, void *);
  3950. func_t f = (func_t)(i->func);
  3951. f(param1, param2);
  3952. }
  3953. else
  3954. {
  3955. // We must guarantee the order of the arguments which is why we copy them to this
  3956. // array. Otherwise the compiler may put them anywhere it likes, or even keep them
  3957. // in the registers which causes problem.
  3958. void *params[2] = {param1, param2};
  3959. asCGeneric gen(const_cast<asCScriptEngine*>(this), s, 0, (asDWORD*)&params);
  3960. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3961. f(&gen);
  3962. }
  3963. }
  3964. bool asCScriptEngine::CallGlobalFunctionRetBool(void *param1, void *param2, asSSystemFunctionInterface *i, asCScriptFunction *s) const
  3965. {
  3966. if( i->callConv == ICC_CDECL )
  3967. {
  3968. bool (*f)(void *, void *) = (bool (*)(void *, void *))(i->func);
  3969. return f(param1, param2);
  3970. }
  3971. else if( i->callConv == ICC_STDCALL )
  3972. {
  3973. typedef bool (STDCALL *func_t)(void *, void *);
  3974. func_t f = (func_t)(i->func);
  3975. return f(param1, param2);
  3976. }
  3977. else
  3978. {
  3979. // TODO: When simulating a 64bit environment by defining AS_64BIT_PTR on a 32bit platform this code
  3980. // fails, because the stack given to asCGeneric is not prepared with two 64bit arguments.
  3981. // We must guarantee the order of the arguments which is why we copy them to this
  3982. // array. Otherwise the compiler may put them anywhere it likes, or even keep them
  3983. // in the registers which causes problem.
  3984. void *params[2] = {param1, param2};
  3985. asCGeneric gen(const_cast<asCScriptEngine*>(this), s, 0, (asDWORD*)params);
  3986. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3987. f(&gen);
  3988. return *(bool*)gen.GetReturnPointer();
  3989. }
  3990. }
  3991. void *asCScriptEngine::CallAlloc(const asCObjectType *type) const
  3992. {
  3993. // Allocate 4 bytes as the smallest size. Otherwise CallSystemFunction may try to
  3994. // copy a DWORD onto a smaller memory block, in case the object type is return in registers.
  3995. // Pad to the next even 4 bytes to avoid asBC_CPY writing outside of allocated buffer for registered POD types
  3996. asUINT size = type->size;
  3997. if( size & 0x3 )
  3998. size += 4 - (size & 0x3);
  3999. #ifndef WIP_16BYTE_ALIGN
  4000. #if defined(AS_DEBUG)
  4001. return ((asALLOCFUNCDEBUG_t)userAlloc)(size, __FILE__, __LINE__);
  4002. #else
  4003. return userAlloc(size);
  4004. #endif
  4005. #else
  4006. #if defined(AS_DEBUG)
  4007. return ((asALLOCALIGNEDFUNCDEBUG_t)userAllocAligned)(size, type->alignment, __FILE__, __LINE__);
  4008. #else
  4009. return userAllocAligned(size, type->alignment);
  4010. #endif
  4011. #endif
  4012. }
  4013. void asCScriptEngine::CallFree(void *obj) const
  4014. {
  4015. #ifndef WIP_16BYTE_ALIGN
  4016. userFree(obj);
  4017. #else
  4018. userFreeAligned(obj);
  4019. #endif
  4020. }
  4021. // interface
  4022. int asCScriptEngine::NotifyGarbageCollectorOfNewObject(void *obj, asITypeInfo *type)
  4023. {
  4024. return gc.AddScriptObjectToGC(obj, static_cast<asCObjectType*>(type));
  4025. }
  4026. // interface
  4027. int asCScriptEngine::GetObjectInGC(asUINT idx, asUINT *seqNbr, void **obj, asITypeInfo **type)
  4028. {
  4029. return gc.GetObjectInGC(idx, seqNbr, obj, type);
  4030. }
  4031. // interface
  4032. int asCScriptEngine::GarbageCollect(asDWORD flags, asUINT iterations)
  4033. {
  4034. int r = gc.GarbageCollect(flags, iterations);
  4035. if( r == 0 )
  4036. {
  4037. // Delete any modules that have been discarded previously but not
  4038. // removed due to being referred to by objects in the garbage collector
  4039. DeleteDiscardedModules();
  4040. }
  4041. return r;
  4042. }
  4043. // interface
  4044. void asCScriptEngine::GetGCStatistics(asUINT *currentSize, asUINT *totalDestroyed, asUINT *totalDetected, asUINT *newObjects, asUINT *totalNewDestroyed) const
  4045. {
  4046. gc.GetStatistics(currentSize, totalDestroyed, totalDetected, newObjects, totalNewDestroyed);
  4047. }
  4048. // interface
  4049. void asCScriptEngine::GCEnumCallback(void *reference)
  4050. {
  4051. gc.GCEnumCallback(reference);
  4052. }
  4053. // interface
  4054. void asCScriptEngine::ForwardGCEnumReferences(void *ref, asITypeInfo *type)
  4055. {
  4056. asCTypeInfo *t = reinterpret_cast<asCTypeInfo*>(type);
  4057. if ((t->flags & asOBJ_VALUE) && (t->flags & asOBJ_GC))
  4058. {
  4059. CallObjectMethod(ref, this, CastToObjectType(t)->beh.gcEnumReferences);
  4060. }
  4061. }
  4062. // interface
  4063. void asCScriptEngine::ForwardGCReleaseReferences(void *ref, asITypeInfo *type)
  4064. {
  4065. asCTypeInfo *t = reinterpret_cast<asCTypeInfo*>(type);
  4066. if ((t->flags & asOBJ_VALUE) && (t->flags & asOBJ_GC))
  4067. {
  4068. CallObjectMethod(ref, this, CastToObjectType(t)->beh.gcReleaseAllReferences);
  4069. }
  4070. }
  4071. // interface
  4072. void asCScriptEngine::SetCircularRefDetectedCallback(asCIRCULARREFFUNC_t callback, void *param)
  4073. {
  4074. gc.circularRefDetectCallbackFunc = callback;
  4075. gc.circularRefDetectCallbackParam = param;
  4076. }
  4077. int asCScriptEngine::GetTypeIdFromDataType(const asCDataType &dtIn) const
  4078. {
  4079. if( dtIn.IsNullHandle() ) return asTYPEID_VOID;
  4080. if( dtIn.GetTypeInfo() == 0 )
  4081. {
  4082. // Primitives have pre-fixed typeIds
  4083. switch( dtIn.GetTokenType() )
  4084. {
  4085. case ttVoid: return asTYPEID_VOID;
  4086. case ttBool: return asTYPEID_BOOL;
  4087. case ttInt8: return asTYPEID_INT8;
  4088. case ttInt16: return asTYPEID_INT16;
  4089. case ttInt: return asTYPEID_INT32;
  4090. case ttInt64: return asTYPEID_INT64;
  4091. case ttUInt8: return asTYPEID_UINT8;
  4092. case ttUInt16: return asTYPEID_UINT16;
  4093. case ttUInt: return asTYPEID_UINT32;
  4094. case ttUInt64: return asTYPEID_UINT64;
  4095. case ttFloat: return asTYPEID_FLOAT;
  4096. case ttDouble: return asTYPEID_DOUBLE;
  4097. default:
  4098. // All types should be covered by the above. The variable type is not really a type
  4099. asASSERT(dtIn.GetTokenType() == ttQuestion);
  4100. return -1;
  4101. }
  4102. }
  4103. int typeId = -1;
  4104. asCTypeInfo *ot = dtIn.GetTypeInfo();
  4105. asASSERT(ot != &functionBehaviours);
  4106. // Object's hold the typeId themselves
  4107. typeId = ot->typeId;
  4108. if( typeId == -1 )
  4109. {
  4110. ACQUIREEXCLUSIVE(engineRWLock);
  4111. // Make sure another thread didn't determine the typeId while we were waiting for the lock
  4112. if( ot->typeId == -1 )
  4113. {
  4114. typeId = typeIdSeqNbr++;
  4115. if( ot->flags & asOBJ_SCRIPT_OBJECT ) typeId |= asTYPEID_SCRIPTOBJECT;
  4116. else if( ot->flags & asOBJ_TEMPLATE ) typeId |= asTYPEID_TEMPLATE;
  4117. else if( ot->flags & asOBJ_ENUM ) {} // TODO: Should we have a specific bit for this?
  4118. else typeId |= asTYPEID_APPOBJECT;
  4119. ot->typeId = typeId;
  4120. mapTypeIdToTypeInfo.Insert(typeId, ot);
  4121. }
  4122. RELEASEEXCLUSIVE(engineRWLock);
  4123. }
  4124. // Add flags according to the requested type
  4125. if( dtIn.GetTypeInfo() && !(dtIn.GetTypeInfo()->flags & asOBJ_ASHANDLE) )
  4126. {
  4127. // The ASHANDLE types behave like handles, but are really
  4128. // value types so the typeId is never returned as a handle
  4129. if( dtIn.IsObjectHandle() )
  4130. typeId |= asTYPEID_OBJHANDLE;
  4131. if( dtIn.IsHandleToConst() )
  4132. typeId |= asTYPEID_HANDLETOCONST;
  4133. }
  4134. return typeId;
  4135. }
  4136. asCDataType asCScriptEngine::GetDataTypeFromTypeId(int typeId) const
  4137. {
  4138. int baseId = typeId & (asTYPEID_MASK_OBJECT | asTYPEID_MASK_SEQNBR);
  4139. if( typeId <= asTYPEID_DOUBLE )
  4140. {
  4141. eTokenType type[] = {ttVoid, ttBool, ttInt8, ttInt16, ttInt, ttInt64, ttUInt8, ttUInt16, ttUInt, ttUInt64, ttFloat, ttDouble};
  4142. return asCDataType::CreatePrimitive(type[typeId], false);
  4143. }
  4144. // First check if the typeId is an object type
  4145. asCTypeInfo *ot = 0;
  4146. ACQUIRESHARED(engineRWLock);
  4147. asSMapNode<int,asCTypeInfo*> *cursor = 0;
  4148. if( mapTypeIdToTypeInfo.MoveTo(&cursor, baseId) )
  4149. ot = mapTypeIdToTypeInfo.GetValue(cursor);
  4150. RELEASESHARED(engineRWLock);
  4151. if( ot )
  4152. {
  4153. asCDataType dt = asCDataType::CreateType(ot, false);
  4154. if( typeId & asTYPEID_OBJHANDLE )
  4155. dt.MakeHandle(true, true);
  4156. if( typeId & asTYPEID_HANDLETOCONST )
  4157. dt.MakeHandleToConst(true);
  4158. return dt;
  4159. }
  4160. return asCDataType();
  4161. }
  4162. asCObjectType *asCScriptEngine::GetObjectTypeFromTypeId(int typeId) const
  4163. {
  4164. asCDataType dt = GetDataTypeFromTypeId(typeId);
  4165. return CastToObjectType(dt.GetTypeInfo());
  4166. }
  4167. void asCScriptEngine::RemoveFromTypeIdMap(asCTypeInfo *type)
  4168. {
  4169. ACQUIREEXCLUSIVE(engineRWLock);
  4170. asSMapNode<int,asCTypeInfo*> *cursor = 0;
  4171. mapTypeIdToTypeInfo.MoveFirst(&cursor);
  4172. while( cursor )
  4173. {
  4174. if(mapTypeIdToTypeInfo.GetValue(cursor) == type )
  4175. {
  4176. mapTypeIdToTypeInfo.Erase(cursor);
  4177. break;
  4178. }
  4179. mapTypeIdToTypeInfo.MoveNext(&cursor, cursor);
  4180. }
  4181. RELEASEEXCLUSIVE(engineRWLock);
  4182. }
  4183. // interface
  4184. asITypeInfo *asCScriptEngine::GetTypeInfoByDecl(const char *decl) const
  4185. {
  4186. asCDataType dt;
  4187. // This cast is ok, because we are not changing anything in the engine
  4188. asCBuilder bld(const_cast<asCScriptEngine*>(this), 0);
  4189. // Don't write parser errors to the message callback
  4190. bld.silent = true;
  4191. int r = bld.ParseDataType(decl, &dt, defaultNamespace);
  4192. if (r < 0)
  4193. return 0;
  4194. return dt.GetTypeInfo();
  4195. }
  4196. // interface
  4197. int asCScriptEngine::GetTypeIdByDecl(const char *decl) const
  4198. {
  4199. asCDataType dt;
  4200. // This cast is ok, because we are not changing anything in the engine
  4201. asCBuilder bld(const_cast<asCScriptEngine*>(this), 0);
  4202. // Don't write parser errors to the message callback
  4203. bld.silent = true;
  4204. int r = bld.ParseDataType(decl, &dt, defaultNamespace);
  4205. if( r < 0 )
  4206. return asINVALID_TYPE;
  4207. return GetTypeIdFromDataType(dt);
  4208. }
  4209. // interface
  4210. const char *asCScriptEngine::GetTypeDeclaration(int typeId, bool includeNamespace) const
  4211. {
  4212. asCDataType dt = GetDataTypeFromTypeId(typeId);
  4213. asCString *tempString = &asCThreadManager::GetLocalData()->string;
  4214. *tempString = dt.Format(defaultNamespace, includeNamespace);
  4215. return tempString->AddressOf();
  4216. }
  4217. // interface
  4218. int asCScriptEngine::GetSizeOfPrimitiveType(int typeId) const
  4219. {
  4220. asCDataType dt = GetDataTypeFromTypeId(typeId);
  4221. if( !dt.IsPrimitive() ) return 0;
  4222. return dt.GetSizeInMemoryBytes();
  4223. }
  4224. // interface
  4225. int asCScriptEngine::RefCastObject(void *obj, asITypeInfo *fromType, asITypeInfo *toType, void **newPtr, bool useOnlyImplicitCast)
  4226. {
  4227. if( newPtr == 0 ) return asINVALID_ARG;
  4228. *newPtr = 0;
  4229. if( fromType == 0 || toType == 0 ) return asINVALID_ARG;
  4230. // A null-pointer can always be cast to another type, so it will always be successful
  4231. if( obj == 0 )
  4232. return asSUCCESS;
  4233. if( fromType == toType )
  4234. {
  4235. *newPtr = obj;
  4236. AddRefScriptObject(*newPtr, toType);
  4237. return asSUCCESS;
  4238. }
  4239. // Check for funcdefs
  4240. if ((fromType->GetFlags() & asOBJ_FUNCDEF) && (toType->GetFlags() & asOBJ_FUNCDEF))
  4241. {
  4242. asCFuncdefType *fromFunc = CastToFuncdefType(reinterpret_cast<asCTypeInfo*>(fromType));
  4243. asCFuncdefType *toFunc = CastToFuncdefType(reinterpret_cast<asCTypeInfo*>(toType));
  4244. if (fromFunc && toFunc && fromFunc->funcdef->IsSignatureExceptNameEqual(toFunc->funcdef))
  4245. {
  4246. *newPtr = obj;
  4247. AddRefScriptObject(*newPtr, toType);
  4248. return asSUCCESS;
  4249. }
  4250. return asSUCCESS;
  4251. }
  4252. // Look for ref cast behaviours
  4253. asCScriptFunction *universalCastFunc = 0;
  4254. asCObjectType *from = CastToObjectType(reinterpret_cast< asCTypeInfo*>(fromType));
  4255. if( from == 0 ) return asINVALID_ARG;
  4256. for( asUINT n = 0; n < from->methods.GetLength(); n++ )
  4257. {
  4258. asCScriptFunction *func = scriptFunctions[from->methods[n]];
  4259. if( func->name == "opImplCast" ||
  4260. (!useOnlyImplicitCast && func->name == "opCast") )
  4261. {
  4262. if( func->returnType.GetTypeInfo() == toType )
  4263. {
  4264. *newPtr = CallObjectMethodRetPtr(obj, func->id);
  4265. // The ref cast behaviour returns a handle with incremented
  4266. // ref counter, so there is no need to call AddRef explicitly
  4267. // unless the function is registered with autohandle
  4268. if( func->sysFuncIntf->returnAutoHandle )
  4269. AddRefScriptObject(*newPtr, toType);
  4270. return asSUCCESS;
  4271. }
  4272. else if( func->returnType.GetTokenType() == ttVoid &&
  4273. func->parameterTypes.GetLength() == 1 &&
  4274. func->parameterTypes[0].GetTokenType() == ttQuestion )
  4275. {
  4276. universalCastFunc = func;
  4277. }
  4278. }
  4279. }
  4280. // One last chance if the object has a void opCast(?&out) behaviour
  4281. if( universalCastFunc )
  4282. {
  4283. // TODO: Add proper error handling
  4284. asIScriptContext *ctx = RequestContext();
  4285. ctx->Prepare(universalCastFunc);
  4286. ctx->SetObject(obj);
  4287. ctx->SetArgVarType(0, newPtr, toType->GetTypeId() | asTYPEID_OBJHANDLE);
  4288. ctx->Execute();
  4289. ReturnContext(ctx);
  4290. // The opCast(?&out) method already incremented the
  4291. // refCount so there is no need to do it manually
  4292. return asSUCCESS;
  4293. }
  4294. // For script classes and interfaces there is a quick route
  4295. if( (fromType->GetFlags() & asOBJ_SCRIPT_OBJECT) && (toType->GetFlags() & asOBJ_SCRIPT_OBJECT) )
  4296. {
  4297. if( fromType == toType )
  4298. {
  4299. *newPtr = obj;
  4300. reinterpret_cast<asCScriptObject*>(*newPtr)->AddRef();
  4301. return asSUCCESS;
  4302. }
  4303. // Up casts to base class or interface can be done implicitly
  4304. if( fromType->DerivesFrom(toType) ||
  4305. fromType->Implements(toType) )
  4306. {
  4307. *newPtr = obj;
  4308. reinterpret_cast<asCScriptObject*>(*newPtr)->AddRef();
  4309. return asSUCCESS;
  4310. }
  4311. // Down casts to derived class or from interface can only be done explicitly
  4312. if( !useOnlyImplicitCast )
  4313. {
  4314. // Get the true type of the object so the explicit cast can evaluate all possibilities
  4315. asITypeInfo *trueType = reinterpret_cast<asCScriptObject*>(obj)->GetObjectType();
  4316. if (trueType->DerivesFrom(toType) ||
  4317. trueType->Implements(toType))
  4318. {
  4319. *newPtr = obj;
  4320. reinterpret_cast<asCScriptObject*>(*newPtr)->AddRef();
  4321. return asSUCCESS;
  4322. }
  4323. }
  4324. }
  4325. // The cast is not available, but it is still a success
  4326. return asSUCCESS;
  4327. }
  4328. // interface
  4329. void *asCScriptEngine::CreateScriptObject(const asITypeInfo *type)
  4330. {
  4331. if( type == 0 ) return 0;
  4332. asCObjectType *objType = CastToObjectType(const_cast<asCTypeInfo*>(reinterpret_cast<const asCTypeInfo*>(type)));
  4333. if (objType == 0) return 0;
  4334. void *ptr = 0;
  4335. // Check that there is a default factory for ref types
  4336. if( objType->beh.factory == 0 && (objType->flags & asOBJ_REF) )
  4337. {
  4338. // TODO: How to report the reason the object couldn't be created, without writing to the message callback? optional argument with return code?
  4339. // TODO: Warn about the invalid call to message callback. Make it an optional, so the warning can be turned off
  4340. // asCString str;
  4341. // str.Format(TXT_FAILED_IN_FUNC_s_s_d, "CreateScriptObject", errorNames[-asNO_FUNCTION], asNO_FUNCTION);
  4342. // WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  4343. return 0;
  4344. }
  4345. // Construct the object
  4346. if( objType->flags & asOBJ_SCRIPT_OBJECT )
  4347. {
  4348. // Call the script class' default factory with a context
  4349. ptr = ScriptObjectFactory(objType, this);
  4350. }
  4351. else if( (objType->flags & asOBJ_TEMPLATE) && (objType->flags & asOBJ_REF) )
  4352. {
  4353. // The registered factory that takes the object type is moved
  4354. // to the construct behaviour when the type is instantiated
  4355. #ifdef AS_NO_EXCEPTIONS
  4356. ptr = CallGlobalFunctionRetPtr(objType->beh.construct, objType);
  4357. #else
  4358. try
  4359. {
  4360. ptr = CallGlobalFunctionRetPtr(objType->beh.construct, objType);
  4361. }
  4362. catch (...)
  4363. {
  4364. asCContext *ctx = reinterpret_cast<asCContext*>(asGetActiveContext());
  4365. if (ctx)
  4366. ctx->HandleAppException();
  4367. }
  4368. #endif
  4369. }
  4370. else if( objType->flags & asOBJ_REF )
  4371. {
  4372. // Call the default factory directly
  4373. #ifdef AS_NO_EXCEPTIONS
  4374. ptr = CallGlobalFunctionRetPtr(objType->beh.factory);
  4375. #else
  4376. try
  4377. {
  4378. ptr = CallGlobalFunctionRetPtr(objType->beh.factory);
  4379. }
  4380. catch(...)
  4381. {
  4382. asCContext *ctx = reinterpret_cast<asCContext*>(asGetActiveContext());
  4383. if( ctx )
  4384. ctx->HandleAppException();
  4385. }
  4386. #endif
  4387. }
  4388. else
  4389. {
  4390. // Make sure there is a default constructor or that it is a POD type
  4391. if( objType->beh.construct == 0 && !(objType->flags & asOBJ_POD) )
  4392. {
  4393. // TODO: How to report the reason the object couldn't be created, without writing to the message callback? optional argument with return code?
  4394. // TODO: Warn about the invalid call to message callback. Make it an optional, so the warning can be turned off
  4395. // asCString str;
  4396. // str.Format(TXT_FAILED_IN_FUNC_s_s_d, "CreateScriptObject", errorNames[-asNO_FUNCTION], asNO_FUNCTION);
  4397. // WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  4398. return 0;
  4399. }
  4400. // Manually allocate the memory, then call the default constructor
  4401. ptr = CallAlloc(objType);
  4402. int funcIndex = objType->beh.construct;
  4403. if (funcIndex)
  4404. {
  4405. if (objType->flags & asOBJ_TEMPLATE)
  4406. {
  4407. // Templates of value types create script functions as the constructors
  4408. CallScriptObjectMethod(ptr, funcIndex);
  4409. }
  4410. else
  4411. {
  4412. #ifdef AS_NO_EXCEPTIONS
  4413. CallObjectMethod(ptr, funcIndex);
  4414. #else
  4415. try
  4416. {
  4417. CallObjectMethod(ptr, funcIndex);
  4418. }
  4419. catch (...)
  4420. {
  4421. asCContext *ctx = reinterpret_cast<asCContext*>(asGetActiveContext());
  4422. if (ctx)
  4423. ctx->HandleAppException();
  4424. // Free the memory
  4425. CallFree(ptr);
  4426. ptr = 0;
  4427. }
  4428. #endif
  4429. }
  4430. }
  4431. }
  4432. return ptr;
  4433. }
  4434. // internal
  4435. int asCScriptEngine::CallScriptObjectMethod(void *obj, int funcId)
  4436. {
  4437. asIScriptContext *ctx = 0;
  4438. int r = 0;
  4439. bool isNested = false;
  4440. // Use nested call in the context if there is an active context
  4441. ctx = asGetActiveContext();
  4442. if (ctx)
  4443. {
  4444. // It may not always be possible to reuse the current context,
  4445. // in which case we'll have to create a new one any way.
  4446. if (ctx->GetEngine() == this && ctx->PushState() == asSUCCESS)
  4447. isNested = true;
  4448. else
  4449. ctx = 0;
  4450. }
  4451. if (ctx == 0)
  4452. {
  4453. // Request a context from the engine
  4454. ctx = RequestContext();
  4455. if (ctx == 0)
  4456. {
  4457. // TODO: How to best report this failure?
  4458. return asERROR;
  4459. }
  4460. }
  4461. r = ctx->Prepare(scriptFunctions[funcId]);
  4462. if (r < 0)
  4463. {
  4464. if (isNested)
  4465. ctx->PopState();
  4466. else
  4467. ReturnContext(ctx);
  4468. // TODO: How to best report this failure?
  4469. return asERROR;
  4470. }
  4471. // Set the object
  4472. ctx->SetObject(obj);
  4473. for (;;)
  4474. {
  4475. r = ctx->Execute();
  4476. // We can't allow this execution to be suspended
  4477. // so resume the execution immediately
  4478. if (r != asEXECUTION_SUSPENDED)
  4479. break;
  4480. }
  4481. if (r != asEXECUTION_FINISHED)
  4482. {
  4483. if (isNested)
  4484. {
  4485. ctx->PopState();
  4486. // If the execution was aborted or an exception occurred,
  4487. // then we should forward that to the outer execution.
  4488. if (r == asEXECUTION_EXCEPTION)
  4489. {
  4490. // TODO: How to improve this exception
  4491. ctx->SetException(TXT_EXCEPTION_IN_NESTED_CALL);
  4492. }
  4493. else if (r == asEXECUTION_ABORTED)
  4494. ctx->Abort();
  4495. }
  4496. else
  4497. ReturnContext(ctx);
  4498. // TODO: How to best report the error?
  4499. return asERROR;
  4500. }
  4501. if (isNested)
  4502. ctx->PopState();
  4503. else
  4504. ReturnContext(ctx);
  4505. return asSUCCESS;
  4506. }
  4507. // interface
  4508. void *asCScriptEngine::CreateUninitializedScriptObject(const asITypeInfo *type)
  4509. {
  4510. // This function only works for script classes. Registered types cannot be created this way.
  4511. if( type == 0 || !(type->GetFlags() & asOBJ_SCRIPT_OBJECT) )
  4512. return 0;
  4513. asCObjectType *objType = CastToObjectType(const_cast<asCTypeInfo*>(reinterpret_cast<const asCTypeInfo*>(type)));
  4514. if (objType == 0)
  4515. return 0;
  4516. // Construct the object, but do not call the actual constructor that initializes the members
  4517. // The initialization will be done by the application afterwards, e.g. through serialization.
  4518. asCScriptObject *obj = reinterpret_cast<asCScriptObject*>(CallAlloc(objType));
  4519. // Pre-initialize the memory so there are no invalid pointers
  4520. ScriptObject_ConstructUnitialized(objType, obj);
  4521. return obj;
  4522. }
  4523. // interface
  4524. void *asCScriptEngine::CreateScriptObjectCopy(void *origObj, const asITypeInfo *type)
  4525. {
  4526. if( origObj == 0 || type == 0 ) return 0;
  4527. const asCObjectType* ot = CastToObjectType(const_cast<asCTypeInfo*>(reinterpret_cast<const asCTypeInfo*>(type)));
  4528. if (ot == 0) return 0;
  4529. void *newObj = 0;
  4530. if ((ot->flags & asOBJ_SCRIPT_OBJECT) && ot->beh.copyfactory)
  4531. {
  4532. // Call the script class' default factory with a context
  4533. newObj = ScriptObjectCopyFactory(ot, origObj, this);
  4534. }
  4535. else if (ot->beh.copyfactory)
  4536. {
  4537. // Call the copy factory which will allocate the memory then copy the original object
  4538. #ifdef AS_NO_EXCEPTIONS
  4539. newObj = CallGlobalFunctionRetPtr(ot->beh.copyfactory, origObj);
  4540. #else
  4541. try
  4542. {
  4543. newObj = CallGlobalFunctionRetPtr(ot->beh.copyfactory, origObj);
  4544. }
  4545. catch (...)
  4546. {
  4547. asCContext *ctx = reinterpret_cast<asCContext*>(asGetActiveContext());
  4548. if (ctx)
  4549. ctx->HandleAppException();
  4550. }
  4551. #endif
  4552. }
  4553. else if(ot->beh.copyconstruct )
  4554. {
  4555. // Manually allocate the memory, then call the copy constructor
  4556. newObj = CallAlloc(ot);
  4557. #ifdef AS_NO_EXCEPTIONS
  4558. CallObjectMethod(newObj, origObj, ot->beh.copyconstruct);
  4559. #else
  4560. try
  4561. {
  4562. CallObjectMethod(newObj, origObj, ot->beh.copyconstruct);
  4563. }
  4564. catch(...)
  4565. {
  4566. asCContext *ctx = reinterpret_cast<asCContext*>(asGetActiveContext());
  4567. if( ctx )
  4568. ctx->HandleAppException();
  4569. // Free the memory
  4570. CallFree(newObj);
  4571. newObj = 0;
  4572. }
  4573. #endif
  4574. }
  4575. else
  4576. {
  4577. // Allocate the object and then do a value assign
  4578. newObj = CreateScriptObject(type);
  4579. if( newObj == 0 ) return 0;
  4580. AssignScriptObject(newObj, origObj, type);
  4581. }
  4582. return newObj;
  4583. }
  4584. // internal
  4585. void asCScriptEngine::ConstructScriptObjectCopy(void *mem, void *obj, asCObjectType *type)
  4586. {
  4587. if( type == 0 || mem == 0 || obj == 0 ) return;
  4588. // This function is only meant to be used for value types
  4589. asASSERT( type->flags & asOBJ_VALUE );
  4590. // Call the copy constructor if available, else call the default constructor followed by the opAssign
  4591. int funcIndex = type->beh.copyconstruct;
  4592. if( funcIndex )
  4593. {
  4594. CallObjectMethod(mem, obj, funcIndex);
  4595. }
  4596. else
  4597. {
  4598. funcIndex = type->beh.construct;
  4599. if( funcIndex )
  4600. CallObjectMethod(mem, funcIndex);
  4601. AssignScriptObject(mem, obj, type);
  4602. }
  4603. }
  4604. // interface
  4605. int asCScriptEngine::AssignScriptObject(void *dstObj, void *srcObj, const asITypeInfo *type)
  4606. {
  4607. // TODO: Warn about invalid call in message stream (make it optional)
  4608. if( type == 0 || dstObj == 0 || srcObj == 0 ) return asINVALID_ARG;
  4609. const asCObjectType *objType = CastToObjectType(const_cast<asCTypeInfo*>(reinterpret_cast<const asCTypeInfo*>(type)));
  4610. if (objType == 0) return asINVALID_ARG;
  4611. // If value assign for ref types has been disabled, then don't do anything if the type is a ref type
  4612. if (ep.disallowValueAssignForRefType && (objType->flags & asOBJ_REF) && !(objType->flags & asOBJ_SCOPED))
  4613. {
  4614. asIScriptContext *ctx = asGetActiveContext();
  4615. if (ctx)
  4616. ctx->SetException("Cannot do value assignment");
  4617. return asNOT_SUPPORTED;
  4618. }
  4619. // Must not copy if the opAssign is not available and the object is not a POD object
  4620. if (objType->beh.copy)
  4621. {
  4622. asCScriptFunction* func = scriptFunctions[objType->beh.copy];
  4623. if (func->funcType == asFUNC_SYSTEM)
  4624. CallObjectMethod(dstObj, srcObj, objType->beh.copy);
  4625. else
  4626. {
  4627. // Call the script class' opAssign method
  4628. asASSERT(objType->flags & asOBJ_SCRIPT_OBJECT);
  4629. reinterpret_cast<asCScriptObject*>(dstObj)->CopyFrom(reinterpret_cast<asCScriptObject*>(srcObj));
  4630. }
  4631. }
  4632. else if (objType->size && (objType->flags & asOBJ_POD))
  4633. {
  4634. memcpy(dstObj, srcObj, objType->size);
  4635. }
  4636. else
  4637. {
  4638. asIScriptContext* ctx = asGetActiveContext();
  4639. if (ctx)
  4640. ctx->SetException("Cannot do value assignment");
  4641. return asNOT_SUPPORTED;
  4642. }
  4643. return asSUCCESS;
  4644. }
  4645. // interface
  4646. void asCScriptEngine::AddRefScriptObject(void *obj, const asITypeInfo *type)
  4647. {
  4648. // Make sure it is not a null pointer
  4649. if( obj == 0 || type == 0 ) return;
  4650. const asCTypeInfo *ti = reinterpret_cast<const asCTypeInfo*>(type);
  4651. if (ti->flags & asOBJ_FUNCDEF)
  4652. {
  4653. CallObjectMethod(obj, functionBehaviours.beh.addref);
  4654. }
  4655. else
  4656. {
  4657. asCObjectType *objType = CastToObjectType(const_cast<asCTypeInfo*>(ti));
  4658. if (objType && objType->beh.addref)
  4659. {
  4660. // Call the addref behaviour
  4661. CallObjectMethod(obj, objType->beh.addref);
  4662. }
  4663. }
  4664. }
  4665. // interface
  4666. void asCScriptEngine::ReleaseScriptObject(void *obj, const asITypeInfo *type)
  4667. {
  4668. // Make sure it is not a null pointer
  4669. if( obj == 0 || type == 0 ) return;
  4670. const asCTypeInfo *ti = reinterpret_cast<const asCTypeInfo*>(type);
  4671. if (ti->flags & asOBJ_FUNCDEF)
  4672. {
  4673. CallObjectMethod(obj, functionBehaviours.beh.release);
  4674. }
  4675. else
  4676. {
  4677. asCObjectType *objType = CastToObjectType(const_cast<asCTypeInfo*>(ti));
  4678. if (objType && objType->flags & asOBJ_REF)
  4679. {
  4680. asASSERT((objType->flags & asOBJ_NOCOUNT) || objType->beh.release);
  4681. if (objType->beh.release)
  4682. {
  4683. // Call the release behaviour
  4684. CallObjectMethod(obj, objType->beh.release);
  4685. }
  4686. }
  4687. else if( objType )
  4688. {
  4689. // Call the destructor
  4690. if (objType->beh.destruct)
  4691. CallObjectMethod(obj, objType->beh.destruct);
  4692. else if (objType->flags & asOBJ_LIST_PATTERN)
  4693. DestroyList((asBYTE*)obj, objType);
  4694. // We'll have to trust that the memory for the object was allocated with CallAlloc.
  4695. // This is true if the object was created in the context, or with CreateScriptObject.
  4696. // Then free the memory
  4697. CallFree(obj);
  4698. }
  4699. }
  4700. }
  4701. // interface
  4702. int asCScriptEngine::BeginConfigGroup(const char *groupName)
  4703. {
  4704. // Make sure the group name doesn't already exist
  4705. for( asUINT n = 0; n < configGroups.GetLength(); n++ )
  4706. {
  4707. if( configGroups[n]->groupName == groupName )
  4708. return asNAME_TAKEN;
  4709. }
  4710. if( currentGroup != &defaultGroup )
  4711. return asNOT_SUPPORTED;
  4712. asCConfigGroup *group = asNEW(asCConfigGroup)();
  4713. if( group == 0 )
  4714. return asOUT_OF_MEMORY;
  4715. group->groupName = groupName;
  4716. configGroups.PushLast(group);
  4717. currentGroup = group;
  4718. return 0;
  4719. }
  4720. // interface
  4721. int asCScriptEngine::EndConfigGroup()
  4722. {
  4723. // Raise error if trying to end the default config
  4724. if( currentGroup == &defaultGroup )
  4725. return asERROR;
  4726. currentGroup = &defaultGroup;
  4727. return 0;
  4728. }
  4729. // interface
  4730. int asCScriptEngine::RemoveConfigGroup(const char *groupName)
  4731. {
  4732. // It is not allowed to remove a group that is still in use.
  4733. // It would be possible to change the code in such a way that
  4734. // the group could be removed even though it was still in use,
  4735. // but that would cause severe negative impact on runtime
  4736. // performance, since the VM would then have to be able handle
  4737. // situations where the types, functions, and global variables
  4738. // can be removed at any time.
  4739. for( asUINT n = 0; n < configGroups.GetLength(); n++ )
  4740. {
  4741. if( configGroups[n]->groupName == groupName )
  4742. {
  4743. asCConfigGroup *group = configGroups[n];
  4744. // Remove any unused generated template instances
  4745. // before verifying if the config group is still in use.
  4746. // RemoveTemplateInstanceType() checks if the instance is in use
  4747. for( asUINT g = generatedTemplateTypes.GetLength(); g-- > 0; )
  4748. RemoveTemplateInstanceType(generatedTemplateTypes[g]);
  4749. // Make sure the group isn't referenced by anyone
  4750. if( group->refCount > 0 )
  4751. return asCONFIG_GROUP_IS_IN_USE;
  4752. // Verify if any objects registered in this group is still alive
  4753. if( group->HasLiveObjects() )
  4754. return asCONFIG_GROUP_IS_IN_USE;
  4755. // Remove the group from the list
  4756. if( n == configGroups.GetLength() - 1 )
  4757. configGroups.PopLast();
  4758. else
  4759. configGroups[n] = configGroups.PopLast();
  4760. // Remove the configurations registered with this group
  4761. group->RemoveConfiguration(this);
  4762. asDELETE(group,asCConfigGroup);
  4763. }
  4764. }
  4765. return 0;
  4766. }
  4767. asCConfigGroup *asCScriptEngine::FindConfigGroupForFunction(int funcId) const
  4768. {
  4769. for( asUINT n = 0; n < configGroups.GetLength(); n++ )
  4770. {
  4771. // Check global functions
  4772. asUINT m;
  4773. for( m = 0; m < configGroups[n]->scriptFunctions.GetLength(); m++ )
  4774. {
  4775. if( configGroups[n]->scriptFunctions[m]->id == funcId )
  4776. return configGroups[n];
  4777. }
  4778. }
  4779. return 0;
  4780. }
  4781. asCConfigGroup *asCScriptEngine::FindConfigGroupForGlobalVar(int gvarId) const
  4782. {
  4783. for( asUINT n = 0; n < configGroups.GetLength(); n++ )
  4784. {
  4785. for( asUINT m = 0; m < configGroups[n]->globalProps.GetLength(); m++ )
  4786. {
  4787. if( int(configGroups[n]->globalProps[m]->id) == gvarId )
  4788. return configGroups[n];
  4789. }
  4790. }
  4791. return 0;
  4792. }
  4793. asCConfigGroup *asCScriptEngine::FindConfigGroupForTypeInfo(const asCTypeInfo *objType) const
  4794. {
  4795. for( asUINT n = 0; n < configGroups.GetLength(); n++ )
  4796. {
  4797. for( asUINT m = 0; m < configGroups[n]->types.GetLength(); m++ )
  4798. {
  4799. if( configGroups[n]->types[m] == objType )
  4800. return configGroups[n];
  4801. }
  4802. }
  4803. return 0;
  4804. }
  4805. asCConfigGroup *asCScriptEngine::FindConfigGroupForFuncDef(const asCFuncdefType *funcDef) const
  4806. {
  4807. for( asUINT n = 0; n < configGroups.GetLength(); n++ )
  4808. {
  4809. asCFuncdefType *f = const_cast<asCFuncdefType*>(funcDef);
  4810. if( configGroups[n]->types.Exists(f) )
  4811. return configGroups[n];
  4812. }
  4813. return 0;
  4814. }
  4815. // interface
  4816. asDWORD asCScriptEngine::SetDefaultAccessMask(asDWORD defaultMask)
  4817. {
  4818. asDWORD old = defaultAccessMask;
  4819. defaultAccessMask = defaultMask;
  4820. return old;
  4821. }
  4822. int asCScriptEngine::GetNextScriptFunctionId()
  4823. {
  4824. // This function only returns the next function id that
  4825. // should be used. It doesn't update the internal arrays.
  4826. if( freeScriptFunctionIds.GetLength() )
  4827. return freeScriptFunctionIds[freeScriptFunctionIds.GetLength()-1];
  4828. return (int)scriptFunctions.GetLength();
  4829. }
  4830. void asCScriptEngine::AddScriptFunction(asCScriptFunction *func)
  4831. {
  4832. // Update the internal arrays with the function id that is now used
  4833. if( freeScriptFunctionIds.GetLength() && freeScriptFunctionIds[freeScriptFunctionIds.GetLength()-1] == func->id )
  4834. freeScriptFunctionIds.PopLast();
  4835. if( asUINT(func->id) == scriptFunctions.GetLength() )
  4836. scriptFunctions.PushLast(func);
  4837. else
  4838. {
  4839. // The slot should be empty or already set with the function, which happens if an existing shared function is reused
  4840. asASSERT( scriptFunctions[func->id] == 0 || scriptFunctions[func->id] == func );
  4841. scriptFunctions[func->id] = func;
  4842. }
  4843. }
  4844. void asCScriptEngine::RemoveScriptFunction(asCScriptFunction *func)
  4845. {
  4846. if( func == 0 || func->id < 0 ) return;
  4847. int id = func->id & ~FUNC_IMPORTED;
  4848. if( func->funcType == asFUNC_IMPORTED )
  4849. {
  4850. if( id >= (int)importedFunctions.GetLength() ) return;
  4851. if( importedFunctions[id] )
  4852. {
  4853. // Remove the function from the list of script functions
  4854. if( id == (int)importedFunctions.GetLength() - 1 )
  4855. {
  4856. importedFunctions.PopLast();
  4857. }
  4858. else
  4859. {
  4860. importedFunctions[id] = 0;
  4861. freeImportedFunctionIdxs.PushLast(id);
  4862. }
  4863. }
  4864. }
  4865. else
  4866. {
  4867. if( id >= (int)scriptFunctions.GetLength() ) return;
  4868. asASSERT( func == scriptFunctions[id] );
  4869. if( scriptFunctions[id] )
  4870. {
  4871. // Remove the function from the list of script functions
  4872. if( id == (int)scriptFunctions.GetLength() - 1 )
  4873. {
  4874. scriptFunctions.PopLast();
  4875. }
  4876. else
  4877. {
  4878. scriptFunctions[id] = 0;
  4879. freeScriptFunctionIds.PushLast(id);
  4880. }
  4881. // Is the function used as signature id?
  4882. if( func->signatureId == id )
  4883. {
  4884. // Remove the signature id
  4885. signatureIds.RemoveValue(func);
  4886. // Update all functions using the signature id
  4887. int newSigId = 0;
  4888. for( asUINT n = 0; n < scriptFunctions.GetLength(); n++ )
  4889. {
  4890. if( scriptFunctions[n] && scriptFunctions[n]->signatureId == id )
  4891. {
  4892. if( newSigId == 0 )
  4893. {
  4894. newSigId = scriptFunctions[n]->id;
  4895. signatureIds.PushLast(scriptFunctions[n]);
  4896. }
  4897. scriptFunctions[n]->signatureId = newSigId;
  4898. }
  4899. }
  4900. }
  4901. }
  4902. }
  4903. }
  4904. // internal
  4905. void asCScriptEngine::RemoveFuncdef(asCFuncdefType *funcdef)
  4906. {
  4907. funcDefs.RemoveValue(funcdef);
  4908. }
  4909. // interface
  4910. int asCScriptEngine::RegisterFuncdef(const char *decl)
  4911. {
  4912. if( decl == 0 ) return ConfigError(asINVALID_ARG, "RegisterFuncdef", decl, 0);
  4913. // Parse the function declaration
  4914. asCScriptFunction *func = asNEW(asCScriptFunction)(this, 0, asFUNC_FUNCDEF);
  4915. if( func == 0 )
  4916. return ConfigError(asOUT_OF_MEMORY, "RegisterFuncdef", decl, 0);
  4917. asCBuilder bld(this, 0);
  4918. asCObjectType *parentClass = 0;
  4919. int r = bld.ParseFunctionDeclaration(0, decl, func, false, 0, 0, defaultNamespace, 0, &parentClass);
  4920. if( r < 0 )
  4921. {
  4922. // Set as dummy function before deleting
  4923. func->funcType = asFUNC_DUMMY;
  4924. asDELETE(func,asCScriptFunction);
  4925. return ConfigError(asINVALID_DECLARATION, "RegisterFuncdef", decl, 0);
  4926. }
  4927. // Check name conflicts
  4928. r = bld.CheckNameConflict(func->name.AddressOf(), 0, 0, defaultNamespace, true, false, false);
  4929. if( r < 0 )
  4930. {
  4931. asDELETE(func,asCScriptFunction);
  4932. return ConfigError(asNAME_TAKEN, "RegisterFuncdef", decl, 0);
  4933. }
  4934. func->id = GetNextScriptFunctionId();
  4935. AddScriptFunction(func);
  4936. asCFuncdefType *fdt = asNEW(asCFuncdefType)(this, func);
  4937. funcDefs.PushLast(fdt); // doesn't increase refcount
  4938. registeredFuncDefs.PushLast(fdt); // doesn't increase refcount
  4939. allRegisteredTypes.Insert(asSNameSpaceNamePair(fdt->nameSpace, fdt->name), fdt); // constructor already set the ref count to 1
  4940. currentGroup->types.PushLast(fdt);
  4941. if (parentClass)
  4942. {
  4943. parentClass->childFuncDefs.PushLast(fdt);
  4944. fdt->parentClass = parentClass;
  4945. // Check if the method restricts that use of the template to value types or reference types
  4946. if (parentClass->flags & asOBJ_TEMPLATE)
  4947. {
  4948. r = SetTemplateRestrictions(parentClass, func, "RegisterFuncdef", decl);
  4949. if (r < 0)
  4950. return r;
  4951. }
  4952. }
  4953. // If parameter type from other groups are used, add references
  4954. currentGroup->AddReferencesForFunc(this, func);
  4955. // Return the type id as success
  4956. return GetTypeIdFromDataType(asCDataType::CreateType(fdt, false));
  4957. }
  4958. // interface
  4959. asUINT asCScriptEngine::GetFuncdefCount() const
  4960. {
  4961. return asUINT(registeredFuncDefs.GetLength());
  4962. }
  4963. // interface
  4964. asITypeInfo *asCScriptEngine::GetFuncdefByIndex(asUINT index) const
  4965. {
  4966. if( index >= registeredFuncDefs.GetLength() )
  4967. return 0;
  4968. return registeredFuncDefs[index];
  4969. }
  4970. // internal
  4971. asCFuncdefType *asCScriptEngine::FindMatchingFuncdef(asCScriptFunction *func, asCModule *module)
  4972. {
  4973. asCFuncdefType *funcDef = func->funcdefType;
  4974. if (funcDef == 0)
  4975. {
  4976. // Check if there is any matching funcdefs already in the engine that can be reused
  4977. for (asUINT n = 0; n < funcDefs.GetLength(); n++)
  4978. {
  4979. if (funcDefs[n]->funcdef->IsSignatureExceptNameEqual(func))
  4980. {
  4981. if (func->IsShared() && !funcDefs[n]->funcdef->IsShared())
  4982. continue;
  4983. funcDef = funcDefs[n];
  4984. break;
  4985. }
  4986. }
  4987. }
  4988. if (funcDef == 0)
  4989. {
  4990. // Create a matching funcdef
  4991. asCScriptFunction *fd = asNEW(asCScriptFunction)(this, 0, asFUNC_FUNCDEF);
  4992. fd->name = func->name;
  4993. fd->nameSpace = func->nameSpace;
  4994. fd->SetShared(func->IsShared());
  4995. fd->returnType = func->returnType;
  4996. fd->parameterTypes = func->parameterTypes;
  4997. fd->inOutFlags = func->inOutFlags;
  4998. funcDef = asNEW(asCFuncdefType)(this, fd);
  4999. funcDefs.PushLast(funcDef); // doesn't increase the refCount
  5000. fd->id = GetNextScriptFunctionId();
  5001. AddScriptFunction(fd);
  5002. if (module)
  5003. {
  5004. // Add the new funcdef to the module so it will
  5005. // be available when saving the bytecode
  5006. funcDef->module = module;
  5007. module->AddFuncDef(funcDef); // the refCount was already accounted for in the constructor
  5008. }
  5009. // Observe, if the funcdef is created without informing a module a reference will be stored in the
  5010. // engine's funcDefs array, but it will not be owned by any module. This means that it will live on
  5011. // until the engine is released.
  5012. }
  5013. if (funcDef && module && funcDef->module && funcDef->module != module)
  5014. {
  5015. // Unless this is a registered funcDef the returned funcDef must
  5016. // be stored as part of the module for saving/loading bytecode
  5017. if (!module->m_funcDefs.Exists(funcDef))
  5018. {
  5019. module->AddFuncDef(funcDef);
  5020. funcDef->AddRefInternal();
  5021. }
  5022. else
  5023. {
  5024. asASSERT(funcDef->IsShared());
  5025. }
  5026. }
  5027. return funcDef;
  5028. }
  5029. // interface
  5030. // TODO: typedef: Accept complex types for the typedefs
  5031. int asCScriptEngine::RegisterTypedef(const char *type, const char *decl)
  5032. {
  5033. if( type == 0 ) return ConfigError(asINVALID_NAME, "RegisterTypedef", type, decl);
  5034. // Verify if the name has been registered as a type already
  5035. // TODO: Must check against registered funcdefs too
  5036. if( GetRegisteredType(type, defaultNamespace) )
  5037. // Let the application recover from this error, for example if the same typedef is registered twice
  5038. return asALREADY_REGISTERED;
  5039. // Grab the data type
  5040. size_t tokenLen;
  5041. eTokenType token;
  5042. asCDataType dataType;
  5043. // Create the data type
  5044. token = tok.GetToken(decl, strlen(decl), &tokenLen);
  5045. switch(token)
  5046. {
  5047. case ttBool:
  5048. case ttInt:
  5049. case ttInt8:
  5050. case ttInt16:
  5051. case ttInt64:
  5052. case ttUInt:
  5053. case ttUInt8:
  5054. case ttUInt16:
  5055. case ttUInt64:
  5056. case ttFloat:
  5057. case ttDouble:
  5058. if( strlen(decl) != tokenLen )
  5059. {
  5060. return ConfigError(asINVALID_TYPE, "RegisterTypedef", type, decl);
  5061. }
  5062. break;
  5063. default:
  5064. return ConfigError(asINVALID_TYPE, "RegisterTypedef", type, decl);
  5065. }
  5066. dataType = asCDataType::CreatePrimitive(token, false);
  5067. // Make sure the name is not a reserved keyword
  5068. token = tok.GetToken(type, strlen(type), &tokenLen);
  5069. if( token != ttIdentifier || strlen(type) != tokenLen )
  5070. return ConfigError(asINVALID_NAME, "RegisterTypedef", type, decl);
  5071. asCBuilder bld(this, 0);
  5072. int r = bld.CheckNameConflict(type, 0, 0, defaultNamespace, true, false, false);
  5073. if( r < 0 )
  5074. return ConfigError(asNAME_TAKEN, "RegisterTypedef", type, decl);
  5075. // Don't have to check against members of object
  5076. // types as they are allowed to use the names
  5077. // Put the data type in the list
  5078. asCTypedefType *td = asNEW(asCTypedefType)(this);
  5079. if( td == 0 )
  5080. return ConfigError(asOUT_OF_MEMORY, "RegisterTypedef", type, decl);
  5081. td->flags = asOBJ_TYPEDEF;
  5082. td->size = dataType.GetSizeInMemoryBytes();
  5083. td->name = type;
  5084. td->nameSpace = defaultNamespace;
  5085. td->aliasForType = dataType;
  5086. allRegisteredTypes.Insert(asSNameSpaceNamePair(td->nameSpace, td->name), td);
  5087. registeredTypeDefs.PushLast(td);
  5088. currentGroup->types.PushLast(td);
  5089. return GetTypeIdByDecl(type);
  5090. }
  5091. // interface
  5092. asUINT asCScriptEngine::GetTypedefCount() const
  5093. {
  5094. return asUINT(registeredTypeDefs.GetLength());
  5095. }
  5096. // interface
  5097. asITypeInfo *asCScriptEngine::GetTypedefByIndex(asUINT index) const
  5098. {
  5099. if( index >= registeredTypeDefs.GetLength() )
  5100. return 0;
  5101. return registeredTypeDefs[index];
  5102. }
  5103. // interface
  5104. int asCScriptEngine::RegisterEnum(const char *name)
  5105. {
  5106. // Check the name
  5107. if( NULL == name )
  5108. return ConfigError(asINVALID_NAME, "RegisterEnum", name, 0);
  5109. // Verify if the name has been registered as a type already
  5110. if( GetRegisteredType(name, defaultNamespace) )
  5111. return asALREADY_REGISTERED;
  5112. // Use builder to parse the datatype
  5113. asCDataType dt;
  5114. asCBuilder bld(this, 0);
  5115. bool oldMsgCallback = msgCallback; msgCallback = false;
  5116. int r = bld.ParseDataType(name, &dt, defaultNamespace);
  5117. msgCallback = oldMsgCallback;
  5118. if( r >= 0 )
  5119. {
  5120. // If it is not in the defaultNamespace then the type was successfully parsed because
  5121. // it is declared in a parent namespace which shouldn't be treated as an error
  5122. if( dt.GetTypeInfo() && dt.GetTypeInfo()->nameSpace == defaultNamespace )
  5123. return ConfigError(asERROR, "RegisterEnum", name, 0);
  5124. }
  5125. // Make sure the name is not a reserved keyword
  5126. size_t tokenLen;
  5127. int token = tok.GetToken(name, strlen(name), &tokenLen);
  5128. if( token != ttIdentifier || strlen(name) != tokenLen )
  5129. return ConfigError(asINVALID_NAME, "RegisterEnum", name, 0);
  5130. r = bld.CheckNameConflict(name, 0, 0, defaultNamespace, true, false, false);
  5131. if( r < 0 )
  5132. return ConfigError(asNAME_TAKEN, "RegisterEnum", name, 0);
  5133. asCEnumType *st = asNEW(asCEnumType)(this);
  5134. if( st == 0 )
  5135. return ConfigError(asOUT_OF_MEMORY, "RegisterEnum", name, 0);
  5136. asCDataType dataType;
  5137. dataType.CreatePrimitive(ttInt, false);
  5138. st->flags = asOBJ_ENUM | asOBJ_SHARED;
  5139. st->size = 4;
  5140. st->name = name;
  5141. st->nameSpace = defaultNamespace;
  5142. allRegisteredTypes.Insert(asSNameSpaceNamePair(st->nameSpace, st->name), st);
  5143. registeredEnums.PushLast(st);
  5144. currentGroup->types.PushLast(st);
  5145. return GetTypeIdByDecl(name);
  5146. }
  5147. // interface
  5148. int asCScriptEngine::RegisterEnumValue(const char *typeName, const char *valueName, int value)
  5149. {
  5150. // Verify that the correct config group is used
  5151. if( currentGroup->FindType(typeName) == 0 )
  5152. return ConfigError(asWRONG_CONFIG_GROUP, "RegisterEnumValue", typeName, valueName);
  5153. asCDataType dt;
  5154. int r;
  5155. asCBuilder bld(this, 0);
  5156. r = bld.ParseDataType(typeName, &dt, defaultNamespace);
  5157. if( r < 0 )
  5158. return ConfigError(r, "RegisterEnumValue", typeName, valueName);
  5159. // Store the enum value
  5160. asCEnumType *ot = CastToEnumType(dt.GetTypeInfo());
  5161. if( ot == 0 )
  5162. return ConfigError(asINVALID_TYPE, "RegisterEnumValue", typeName, valueName);
  5163. if( NULL == valueName )
  5164. return ConfigError(asINVALID_NAME, "RegisterEnumValue", typeName, valueName);
  5165. asUINT tokenLen = 0;
  5166. asETokenClass tokenClass = ParseToken(valueName, 0, &tokenLen);
  5167. if( tokenClass != asTC_IDENTIFIER || tokenLen != strlen(valueName) )
  5168. return ConfigError(asINVALID_NAME, "RegisterEnumValue", typeName, valueName);
  5169. for( unsigned int n = 0; n < ot->enumValues.GetLength(); n++ )
  5170. {
  5171. if( ot->enumValues[n]->name == valueName )
  5172. return ConfigError(asALREADY_REGISTERED, "RegisterEnumValue", typeName, valueName);
  5173. }
  5174. asSEnumValue *e = asNEW(asSEnumValue);
  5175. if( e == 0 )
  5176. return ConfigError(asOUT_OF_MEMORY, "RegisterEnumValue", typeName, valueName);
  5177. e->name = valueName;
  5178. e->value = value;
  5179. ot->enumValues.PushLast(e);
  5180. return asSUCCESS;
  5181. }
  5182. // interface
  5183. asUINT asCScriptEngine::GetEnumCount() const
  5184. {
  5185. return registeredEnums.GetLength();
  5186. }
  5187. // interface
  5188. asITypeInfo *asCScriptEngine::GetEnumByIndex(asUINT index) const
  5189. {
  5190. if( index >= registeredEnums.GetLength() )
  5191. return 0;
  5192. return registeredEnums[index];
  5193. }
  5194. // interface
  5195. asUINT asCScriptEngine::GetObjectTypeCount() const
  5196. {
  5197. return asUINT(registeredObjTypes.GetLength());
  5198. }
  5199. // interface
  5200. asITypeInfo *asCScriptEngine::GetObjectTypeByIndex(asUINT index) const
  5201. {
  5202. if( index >= registeredObjTypes.GetLength() )
  5203. return 0;
  5204. return registeredObjTypes[index];
  5205. }
  5206. // interface
  5207. asITypeInfo *asCScriptEngine::GetTypeInfoByName(const char *in_name) const
  5208. {
  5209. asCString name;
  5210. asSNameSpace *ns = 0;
  5211. if( DetermineNameAndNamespace(in_name, defaultNamespace, name, ns) < 0 )
  5212. return 0;
  5213. while (ns)
  5214. {
  5215. // Check the object types
  5216. for (asUINT n = 0; n < registeredObjTypes.GetLength(); n++)
  5217. {
  5218. if (registeredObjTypes[n]->name == name &&
  5219. registeredObjTypes[n]->nameSpace == ns)
  5220. return registeredObjTypes[n];
  5221. }
  5222. // Perhaps it is a template type? In this case
  5223. // the returned type will be the generic type
  5224. for (asUINT n = 0; n < registeredTemplateTypes.GetLength(); n++)
  5225. {
  5226. if (registeredTemplateTypes[n]->name == name &&
  5227. registeredTemplateTypes[n]->nameSpace == ns)
  5228. return registeredTemplateTypes[n];
  5229. }
  5230. // Check the enum types
  5231. for (asUINT n = 0; n < registeredEnums.GetLength(); n++)
  5232. {
  5233. if (registeredEnums[n]->name == name &&
  5234. registeredEnums[n]->nameSpace == ns)
  5235. return registeredEnums[n];
  5236. }
  5237. // Check the typedefs
  5238. for (asUINT n = 0; n < registeredTypeDefs.GetLength();n++)
  5239. {
  5240. if (registeredTypeDefs[n]->name == name &&
  5241. registeredTypeDefs[n]->nameSpace == ns)
  5242. return registeredTypeDefs[n];
  5243. }
  5244. // Recursively search parent namespace
  5245. ns = GetParentNameSpace(ns);
  5246. }
  5247. return 0;
  5248. }
  5249. // internal
  5250. int asCScriptEngine::DetermineNameAndNamespace(const char *in_name, asSNameSpace *implicitNs, asCString &out_name, asSNameSpace *&out_ns) const
  5251. {
  5252. if( in_name == 0 )
  5253. return asINVALID_ARG;
  5254. asCString name = in_name;
  5255. asCString scope;
  5256. asSNameSpace *ns = implicitNs;
  5257. // Check if the given name contains a scope
  5258. int pos = name.FindLast("::");
  5259. if( pos >= 0 )
  5260. {
  5261. scope = name.SubString(0, pos);
  5262. name = name.SubString(pos+2);
  5263. if( pos == 0 )
  5264. {
  5265. // The scope is '::' so the search must start in the global namespace
  5266. ns = nameSpaces[0];
  5267. }
  5268. else if( scope.SubString(0, 2) == "::" )
  5269. {
  5270. // The scope starts with '::' so the given scope is fully qualified
  5271. ns = FindNameSpace(scope.SubString(2).AddressOf());
  5272. }
  5273. else
  5274. {
  5275. // The scope doesn't start with '::' so it is relative to the current namespace
  5276. if( implicitNs->name == "" )
  5277. ns = FindNameSpace(scope.AddressOf());
  5278. else
  5279. ns = FindNameSpace((implicitNs->name + "::" + scope).AddressOf());
  5280. }
  5281. }
  5282. out_name = name;
  5283. out_ns = ns;
  5284. return 0;
  5285. }
  5286. // interface
  5287. asITypeInfo *asCScriptEngine::GetTypeInfoById(int typeId) const
  5288. {
  5289. asCDataType dt = GetDataTypeFromTypeId(typeId);
  5290. // Is the type id valid?
  5291. if (!dt.IsValid()) return 0;
  5292. return dt.GetTypeInfo();
  5293. }
  5294. // interface
  5295. asIScriptFunction *asCScriptEngine::GetFunctionById(int funcId) const
  5296. {
  5297. return GetScriptFunction(funcId);
  5298. }
  5299. // internal
  5300. bool asCScriptEngine::IsTemplateType(const char *name) const
  5301. {
  5302. // Only look in the list of template types (not instance types)
  5303. for( unsigned int n = 0; n < registeredTemplateTypes.GetLength(); n++ )
  5304. {
  5305. asCObjectType *type = registeredTemplateTypes[n];
  5306. if( type && type->name == name )
  5307. return true;
  5308. }
  5309. return false;
  5310. }
  5311. // internal
  5312. int asCScriptEngine::GetScriptSectionNameIndex(const char *name)
  5313. {
  5314. ACQUIREEXCLUSIVE(engineRWLock);
  5315. // TODO: These names are only released when the engine is freed. The assumption is that
  5316. // the same script section names will be reused instead of there always being new
  5317. // names. Is this assumption valid? Do we need to add reference counting?
  5318. // Store the script section names for future reference
  5319. for( asUINT n = 0; n < scriptSectionNames.GetLength(); n++ )
  5320. {
  5321. if( scriptSectionNames[n]->Compare(name) == 0 )
  5322. {
  5323. RELEASEEXCLUSIVE(engineRWLock);
  5324. return n;
  5325. }
  5326. }
  5327. asCString *str = asNEW(asCString)(name);
  5328. if( str )
  5329. scriptSectionNames.PushLast(str);
  5330. int r = int(scriptSectionNames.GetLength()-1);
  5331. RELEASEEXCLUSIVE(engineRWLock);
  5332. return r;
  5333. }
  5334. // interface
  5335. void asCScriptEngine::SetEngineUserDataCleanupCallback(asCLEANENGINEFUNC_t callback, asPWORD type)
  5336. {
  5337. ACQUIREEXCLUSIVE(engineRWLock);
  5338. for( asUINT n = 0; n < cleanEngineFuncs.GetLength(); n++ )
  5339. {
  5340. if( cleanEngineFuncs[n].type == type )
  5341. {
  5342. cleanEngineFuncs[n].cleanFunc = callback;
  5343. RELEASEEXCLUSIVE(engineRWLock);
  5344. return;
  5345. }
  5346. }
  5347. SEngineClean otc = {type, callback};
  5348. cleanEngineFuncs.PushLast(otc);
  5349. RELEASEEXCLUSIVE(engineRWLock);
  5350. }
  5351. // interface
  5352. void asCScriptEngine::SetModuleUserDataCleanupCallback(asCLEANMODULEFUNC_t callback, asPWORD type)
  5353. {
  5354. ACQUIREEXCLUSIVE(engineRWLock);
  5355. for( asUINT n = 0; n < cleanModuleFuncs.GetLength(); n++ )
  5356. {
  5357. if( cleanModuleFuncs[n].type == type )
  5358. {
  5359. cleanModuleFuncs[n].cleanFunc = callback;
  5360. RELEASEEXCLUSIVE(engineRWLock);
  5361. return;
  5362. }
  5363. }
  5364. SModuleClean otc = {type, callback};
  5365. cleanModuleFuncs.PushLast(otc);
  5366. RELEASEEXCLUSIVE(engineRWLock);
  5367. }
  5368. // interface
  5369. void asCScriptEngine::SetContextUserDataCleanupCallback(asCLEANCONTEXTFUNC_t callback, asPWORD type)
  5370. {
  5371. ACQUIREEXCLUSIVE(engineRWLock);
  5372. for( asUINT n = 0; n < cleanContextFuncs.GetLength(); n++ )
  5373. {
  5374. if( cleanContextFuncs[n].type == type )
  5375. {
  5376. cleanContextFuncs[n].cleanFunc = callback;
  5377. RELEASEEXCLUSIVE(engineRWLock);
  5378. return;
  5379. }
  5380. }
  5381. SContextClean otc = {type, callback};
  5382. cleanContextFuncs.PushLast(otc);
  5383. RELEASEEXCLUSIVE(engineRWLock);
  5384. }
  5385. // interface
  5386. void asCScriptEngine::SetFunctionUserDataCleanupCallback(asCLEANFUNCTIONFUNC_t callback, asPWORD type)
  5387. {
  5388. ACQUIREEXCLUSIVE(engineRWLock);
  5389. for( asUINT n = 0; n < cleanFunctionFuncs.GetLength(); n++ )
  5390. {
  5391. if( cleanFunctionFuncs[n].type == type )
  5392. {
  5393. cleanFunctionFuncs[n].cleanFunc = callback;
  5394. RELEASEEXCLUSIVE(engineRWLock);
  5395. return;
  5396. }
  5397. }
  5398. SFunctionClean otc = {type, callback};
  5399. cleanFunctionFuncs.PushLast(otc);
  5400. RELEASEEXCLUSIVE(engineRWLock);
  5401. }
  5402. // interface
  5403. void asCScriptEngine::SetTypeInfoUserDataCleanupCallback(asCLEANTYPEINFOFUNC_t callback, asPWORD type)
  5404. {
  5405. ACQUIREEXCLUSIVE(engineRWLock);
  5406. for( asUINT n = 0; n < cleanTypeInfoFuncs.GetLength(); n++ )
  5407. {
  5408. if( cleanTypeInfoFuncs[n].type == type )
  5409. {
  5410. cleanTypeInfoFuncs[n].cleanFunc = callback;
  5411. RELEASEEXCLUSIVE(engineRWLock);
  5412. return;
  5413. }
  5414. }
  5415. STypeInfoClean otc = {type, callback};
  5416. cleanTypeInfoFuncs.PushLast(otc);
  5417. RELEASEEXCLUSIVE(engineRWLock);
  5418. }
  5419. // interface
  5420. void asCScriptEngine::SetScriptObjectUserDataCleanupCallback(asCLEANSCRIPTOBJECTFUNC_t callback, asPWORD type)
  5421. {
  5422. ACQUIREEXCLUSIVE(engineRWLock);
  5423. for( asUINT n = 0; n < cleanScriptObjectFuncs.GetLength(); n++ )
  5424. {
  5425. if( cleanScriptObjectFuncs[n].type == type )
  5426. {
  5427. cleanScriptObjectFuncs[n].cleanFunc = callback;
  5428. RELEASEEXCLUSIVE(engineRWLock);
  5429. return;
  5430. }
  5431. }
  5432. SScriptObjClean soc = {type, callback};
  5433. cleanScriptObjectFuncs.PushLast(soc);
  5434. RELEASEEXCLUSIVE(engineRWLock);
  5435. }
  5436. // interface
  5437. int asCScriptEngine::SetTranslateAppExceptionCallback(asSFuncPtr callback, void *param, int callConv)
  5438. {
  5439. #ifdef AS_NO_EXCEPTIONS
  5440. return asNOT_SUPPORTED;
  5441. #else
  5442. if (callback.ptr.f.func == 0)
  5443. {
  5444. // Clear the callback
  5445. translateExceptionCallback = false;
  5446. return asSUCCESS;
  5447. }
  5448. // Detect the new callback
  5449. translateExceptionCallback = true;
  5450. translateExceptionCallbackObj = param;
  5451. bool isObj = false;
  5452. if ((unsigned)callConv == asCALL_GENERIC || (unsigned)callConv == asCALL_THISCALL_OBJFIRST || (unsigned)callConv == asCALL_THISCALL_OBJLAST)
  5453. return asNOT_SUPPORTED;
  5454. if ((unsigned)callConv >= asCALL_THISCALL)
  5455. {
  5456. isObj = true;
  5457. if (param == 0)
  5458. {
  5459. translateExceptionCallback = false;
  5460. return asINVALID_ARG;
  5461. }
  5462. }
  5463. int r = DetectCallingConvention(isObj, callback, callConv, 0, &translateExceptionCallbackFunc);
  5464. if (r < 0)
  5465. translateExceptionCallback = false;
  5466. return r;
  5467. #endif
  5468. }
  5469. // internal
  5470. asCObjectType *asCScriptEngine::GetListPatternType(int listPatternFuncId)
  5471. {
  5472. // Get the object type either from the constructor's object for value types
  5473. // or from the factory's return type for reference types
  5474. asCObjectType *ot = scriptFunctions[listPatternFuncId]->objectType;
  5475. if( ot == 0 )
  5476. ot = CastToObjectType(scriptFunctions[listPatternFuncId]->returnType.GetTypeInfo());
  5477. asASSERT( ot );
  5478. // Check if this object type already has a list pattern type
  5479. for( asUINT n = 0; n < listPatternTypes.GetLength(); n++ )
  5480. {
  5481. if( listPatternTypes[n]->templateSubTypes[0].GetTypeInfo() == ot )
  5482. return listPatternTypes[n];
  5483. }
  5484. // Create a new list pattern type for the given object type
  5485. asCObjectType *lpt = asNEW(asCObjectType)(this);
  5486. lpt->templateSubTypes.PushLast(asCDataType::CreateType(ot, false));
  5487. lpt->flags = asOBJ_LIST_PATTERN;
  5488. listPatternTypes.PushLast(lpt);
  5489. return lpt;
  5490. }
  5491. // internal
  5492. void asCScriptEngine::DestroyList(asBYTE *buffer, const asCObjectType *listPatternType)
  5493. {
  5494. asASSERT( listPatternType && (listPatternType->flags & asOBJ_LIST_PATTERN) );
  5495. // Get the list pattern from the listFactory function
  5496. // TODO: runtime optimize: Store the used list factory in the listPatternType itself
  5497. // TODO: runtime optimize: Keep a flag to indicate if there is really a need to free anything
  5498. asCObjectType *ot = CastToObjectType(listPatternType->templateSubTypes[0].GetTypeInfo());
  5499. asCScriptFunction *listFactory = scriptFunctions[ot->beh.listFactory];
  5500. asASSERT( listFactory );
  5501. asSListPatternNode *node = listFactory->listPattern;
  5502. DestroySubList(buffer, node);
  5503. asASSERT( node->type == asLPT_END );
  5504. }
  5505. // internal
  5506. void asCScriptEngine::DestroySubList(asBYTE *&buffer, asSListPatternNode *&node)
  5507. {
  5508. asASSERT( node->type == asLPT_START );
  5509. int count = 0;
  5510. node = node->next;
  5511. while( node )
  5512. {
  5513. if( node->type == asLPT_REPEAT || node->type == asLPT_REPEAT_SAME )
  5514. {
  5515. // Align the offset to 4 bytes boundary
  5516. if( (asPWORD(buffer) & 0x3) )
  5517. buffer += 4 - (asPWORD(buffer) & 0x3);
  5518. // Determine how many times the pattern repeat
  5519. count = *(asUINT*)buffer;
  5520. buffer += 4;
  5521. if( count == 0 )
  5522. {
  5523. // Skip the sub pattern that was expected to be repeated, otherwise
  5524. // we'll try to delete things that don't exist in the buffer
  5525. node = node->next;
  5526. if( node->type == asLPT_START )
  5527. {
  5528. int subCount = 1;
  5529. do
  5530. {
  5531. node = node->next;
  5532. if( node->type == asLPT_START )
  5533. subCount++;
  5534. else if( node->type == asLPT_END )
  5535. subCount--;
  5536. } while( subCount > 0 );
  5537. return;
  5538. }
  5539. }
  5540. }
  5541. else if( node->type == asLPT_TYPE )
  5542. {
  5543. // If we're not in a repeat iteration, then only 1 value should be destroyed
  5544. if( count <= 0 )
  5545. count = 1;
  5546. asCDataType dt = reinterpret_cast<asSListPatternDataTypeNode*>(node)->dataType;
  5547. bool isVarType = dt.GetTokenType() == ttQuestion;
  5548. while( count-- )
  5549. {
  5550. if( isVarType )
  5551. {
  5552. // Align the offset to 4 bytes boundary
  5553. if( (asPWORD(buffer) & 0x3) )
  5554. buffer += 4 - (asPWORD(buffer) & 0x3);
  5555. int typeId = *(int*)buffer;
  5556. buffer += 4;
  5557. dt = GetDataTypeFromTypeId(typeId);
  5558. }
  5559. asCTypeInfo *ti = dt.GetTypeInfo();
  5560. if( ti && (ti->flags & asOBJ_ENUM) == 0 )
  5561. {
  5562. // Free all instances of this type
  5563. if( ti->flags & asOBJ_VALUE )
  5564. {
  5565. asUINT size = ti->GetSize();
  5566. // Align the offset to 4 bytes boundary
  5567. if( size >= 4 && (asPWORD(buffer) & 0x3) )
  5568. buffer += 4 - (asPWORD(buffer) & 0x3);
  5569. asCObjectType *ot = CastToObjectType(ti);
  5570. if( ot && ot->beh.destruct )
  5571. {
  5572. // Only call the destructor if the object has been created
  5573. // We'll assume the object has been created if any byte in
  5574. // the memory is different from 0.
  5575. // TODO: This is not really correct, as bytes may have been
  5576. // modified by the constructor, but then an exception
  5577. // thrown aborting the initialization. The engine
  5578. // really should be keeping track of which objects has
  5579. // been successfully initialized.
  5580. for( asUINT n = 0; n < size; n++ )
  5581. {
  5582. if( buffer[n] != 0 )
  5583. {
  5584. void *ptr = (void*)buffer;
  5585. CallObjectMethod(ptr, ot->beh.destruct);
  5586. break;
  5587. }
  5588. }
  5589. }
  5590. // Advance the pointer in the buffer
  5591. buffer += size;
  5592. }
  5593. else
  5594. {
  5595. // Align the offset to 4 bytes boundary
  5596. if( asPWORD(buffer) & 0x3 )
  5597. buffer += 4 - (asPWORD(buffer) & 0x3);
  5598. // Call the release behaviour
  5599. void *ptr = *(void**)buffer;
  5600. if( ptr )
  5601. ReleaseScriptObject(ptr, ti);
  5602. buffer += AS_PTR_SIZE*4;
  5603. }
  5604. }
  5605. else
  5606. {
  5607. asUINT size = dt.GetSizeInMemoryBytes();
  5608. // Align the offset to 4 bytes boundary
  5609. if( size >= 4 && (asPWORD(buffer) & 0x3) )
  5610. buffer += 4 - (asPWORD(buffer) & 0x3);
  5611. // Advance the buffer
  5612. buffer += size;
  5613. }
  5614. }
  5615. }
  5616. else if( node->type == asLPT_START )
  5617. {
  5618. // If we're not in a repeat iteration, then only 1 value should be destroyed
  5619. if( count <= 0 )
  5620. count = 1;
  5621. while( count-- )
  5622. {
  5623. asSListPatternNode *subList = node;
  5624. DestroySubList(buffer, subList);
  5625. asASSERT( subList->type == asLPT_END );
  5626. if( count == 0 )
  5627. node = subList;
  5628. }
  5629. }
  5630. else if( node->type == asLPT_END )
  5631. {
  5632. return;
  5633. }
  5634. else
  5635. {
  5636. asASSERT( false );
  5637. }
  5638. node = node->next;
  5639. }
  5640. }
  5641. // internal
  5642. asSNameSpace *asCScriptEngine::GetParentNameSpace(asSNameSpace *ns) const
  5643. {
  5644. if( ns == 0 ) return 0;
  5645. if( ns == nameSpaces[0] ) return 0;
  5646. asCString scope = ns->name;
  5647. int pos = scope.FindLast("::");
  5648. if( pos >= 0 )
  5649. {
  5650. scope = scope.SubString(0, pos);
  5651. return FindNameSpace(scope.AddressOf());
  5652. }
  5653. return nameSpaces[0];
  5654. }
  5655. END_AS_NAMESPACE