| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378 |
- /*
- AngelCode Scripting Library
- Copyright (c) 2003-2011 Andreas Jonsson
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any
- damages arising from the use of this software.
- Permission is granted to anyone to use this software for any
- purpose, including commercial applications, and to alter it and
- redistribute it freely, subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you
- must not claim that you wrote the original software. If you use
- this software in a product, an acknowledgment in the product
- documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and
- must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source
- distribution.
- The original version of this library can be located at:
- http://www.angelcode.com/angelscript/
- Andreas Jonsson
- [email protected]
- */
- // Modified by Lasse Öörni for Urho3D
- //
- // as_scriptengine.cpp
- //
- // The implementation of the script engine interface
- //
- #include <stdlib.h>
- #include "as_config.h"
- #include "as_scriptengine.h"
- #include "as_builder.h"
- #include "as_context.h"
- #include "as_string_util.h"
- #include "as_tokenizer.h"
- #include "as_texts.h"
- #include "as_module.h"
- #include "as_callfunc.h"
- #include "as_generic.h"
- #include "as_scriptobject.h"
- #include "as_compiler.h"
- BEGIN_AS_NAMESPACE
- extern "C"
- {
- AS_API const char * asGetLibraryVersion()
- {
- #ifdef _DEBUG
- return ANGELSCRIPT_VERSION_STRING " DEBUG";
- #else
- return ANGELSCRIPT_VERSION_STRING;
- #endif
- }
- AS_API const char * asGetLibraryOptions()
- {
- const char *string = " "
- // Options
- #ifdef AS_MAX_PORTABILITY
- "AS_MAX_PORTABILITY "
- #endif
- #ifdef AS_DEBUG
- "AS_DEBUG "
- #endif
- #ifdef AS_NO_CLASS_METHODS
- "AS_NO_CLASS_METHODS "
- #endif
- #ifdef AS_USE_DOUBLE_AS_FLOAT
- "AS_USE_DOUBLE_AS_FLOAT "
- #endif
- #ifdef AS_64BIT_PTR
- "AS_64BIT_PTR "
- #endif
- #ifdef AS_NO_THREADS
- "AS_NO_THREADS "
- #endif
- #ifdef AS_NO_ATOMIC
- "AS_NO_ATOMIC "
- #endif
- // Target system
- #ifdef AS_WIN
- "AS_WIN "
- #endif
- #ifdef AS_LINUX
- "AS_LINUX "
- #endif
- #ifdef AS_MAC
- "AS_MAC "
- #endif
- #ifdef AS_BSD
- "AS_BSD "
- #endif
- #ifdef AS_XBOX
- "AS_XBOX "
- #endif
- #ifdef AS_XBOX360
- "AS_XBOX360 "
- #endif
- #ifdef AS_PSP
- "AS_PSP "
- #endif
- #ifdef AS_PS2
- "AS_PS2 "
- #endif
- #ifdef AS_PS3
- "AS_PS3 "
- #endif
- #ifdef AS_DC
- "AS_DC "
- #endif
- #ifdef AS_GC
- "AS_GC "
- #endif
- #ifdef AS_WII
- "AS_WII "
- #endif
- #ifdef AS_IPHONE
- "AS_IPHONE "
- #endif
- #ifdef AS_ANDROID
- "AS_ANDROID "
- #endif
- #ifdef AS_HAIKU
- "AS_HAIKU "
- #endif
- #ifdef AS_ILLUMOS
- "AS_ILLUMOS "
- #endif
- // CPU family
- #ifdef AS_PPC
- "AS_PPC "
- #endif
- #ifdef AS_PPC_64
- "AS_PPC_64 "
- #endif
- #ifdef AS_X86
- "AS_X86 "
- #endif
- #ifdef AS_MIPS
- "AS_MIPS "
- #endif
- #ifdef AS_SH4
- "AS_SH4 "
- #endif
- #ifdef AS_XENON
- "AS_XENON "
- #endif
- #ifdef AS_ARM
- "AS_ARM "
- #endif
- #ifdef AS_X64_GCC
- "AS_X64_GCC "
- #endif
- #ifdef AS_X64_MSVC
- "AS_X64_MSVC "
- #endif
- ;
- return string;
- }
- AS_API asIScriptEngine *asCreateScriptEngine(asDWORD version)
- {
- // Verify the version that the application expects
- if( (version/10000) != (ANGELSCRIPT_VERSION/10000) )
- return 0;
- if( (version/100)%100 != (ANGELSCRIPT_VERSION/100)%100 )
- return 0;
- if( (version%100) > (ANGELSCRIPT_VERSION%100) )
- return 0;
- // Verify the size of the types
- asASSERT( sizeof(asBYTE) == 1 );
- asASSERT( sizeof(asWORD) == 2 );
- asASSERT( sizeof(asDWORD) == 4 );
- asASSERT( sizeof(asQWORD) == 8 );
- asASSERT( sizeof(asPWORD) == sizeof(void*) );
- // Verify the boolean type
- asASSERT( sizeof(bool) == AS_SIZEOF_BOOL );
- asASSERT( true == VALUE_OF_BOOLEAN_TRUE );
- // Verify endianess
- #ifdef AS_BIG_ENDIAN
- asASSERT( *(asDWORD*)"\x00\x01\x02\x03" == 0x00010203 );
- asASSERT( *(asQWORD*)"\x00\x01\x02\x03\x04\x05\x06\x07" == I64(0x0001020304050607) );
- #else
- asASSERT( *(asDWORD*)"\x00\x01\x02\x03" == 0x03020100 );
- asASSERT( *(asQWORD*)"\x00\x01\x02\x03\x04\x05\x06\x07" == I64(0x0706050403020100) );
- #endif
- return asNEW(asCScriptEngine)();
- }
- int asCScriptEngine::SetEngineProperty(asEEngineProp property, asPWORD value)
- {
- switch( property )
- {
- case asEP_ALLOW_UNSAFE_REFERENCES:
- ep.allowUnsafeReferences = value ? true : false;
- break;
- case asEP_OPTIMIZE_BYTECODE:
- ep.optimizeByteCode = value ? true : false;
- break;
- case asEP_COPY_SCRIPT_SECTIONS:
- ep.copyScriptSections = value ? true : false;
- break;
- case asEP_MAX_STACK_SIZE:
- // The size is given in bytes, but we only store dwords
- ep.maximumContextStackSize = (int)value/4;
- if( initialContextStackSize > ep.maximumContextStackSize )
- initialContextStackSize = ep.maximumContextStackSize;
- break;
- case asEP_USE_CHARACTER_LITERALS:
- ep.useCharacterLiterals = value ? true : false;
- break;
- case asEP_ALLOW_MULTILINE_STRINGS:
- ep.allowMultilineStrings = value ? true : false;
- break;
- case asEP_ALLOW_IMPLICIT_HANDLE_TYPES:
- ep.allowImplicitHandleTypes = value ? true : false;
- break;
- case asEP_BUILD_WITHOUT_LINE_CUES:
- ep.buildWithoutLineCues = value ? true : false;
- break;
- case asEP_INIT_GLOBAL_VARS_AFTER_BUILD:
- ep.initGlobalVarsAfterBuild = value ? true : false;
- break;
- case asEP_REQUIRE_ENUM_SCOPE:
- ep.requireEnumScope = value ? true : false;
- break;
- case asEP_SCRIPT_SCANNER:
- if( value <= 1 )
- ep.scanner = (int)value;
- else
- return asINVALID_ARG;
- break;
- case asEP_INCLUDE_JIT_INSTRUCTIONS:
- ep.includeJitInstructions = value ? true : false;
- break;
- case asEP_STRING_ENCODING:
- if( value <= 1 )
- ep.stringEncoding = (int)value;
- else
- return asINVALID_ARG;
- break;
- case asEP_PROPERTY_ACCESSOR_MODE:
- if( value <= 2 )
- ep.propertyAccessorMode = (int)value;
- else
- return asINVALID_ARG;
- break;
- case asEP_EXPAND_DEF_ARRAY_TO_TMPL:
- ep.expandDefaultArrayToTemplate = value ? true : false;
- break;
- case asEP_AUTO_GARBAGE_COLLECT:
- ep.autoGarbageCollect = value ? true : false;
- break;
- case asEP_DISALLOW_GLOBAL_VARS:
- ep.disallowGlobalVars = value ? true : false;
- break;
- default:
- return asINVALID_ARG;
- }
- return asSUCCESS;
- }
- asPWORD asCScriptEngine::GetEngineProperty(asEEngineProp property) const
- {
- switch( property )
- {
- case asEP_ALLOW_UNSAFE_REFERENCES:
- return ep.allowUnsafeReferences;
- case asEP_OPTIMIZE_BYTECODE:
- return ep.optimizeByteCode;
- case asEP_COPY_SCRIPT_SECTIONS:
- return ep.copyScriptSections;
- case asEP_MAX_STACK_SIZE:
- return ep.maximumContextStackSize*4;
- case asEP_USE_CHARACTER_LITERALS:
- return ep.useCharacterLiterals;
- case asEP_ALLOW_MULTILINE_STRINGS:
- return ep.allowMultilineStrings;
- case asEP_ALLOW_IMPLICIT_HANDLE_TYPES:
- return ep.allowImplicitHandleTypes;
- case asEP_BUILD_WITHOUT_LINE_CUES:
- return ep.buildWithoutLineCues;
- case asEP_INIT_GLOBAL_VARS_AFTER_BUILD:
- return ep.initGlobalVarsAfterBuild;
- case asEP_REQUIRE_ENUM_SCOPE:
- return ep.requireEnumScope;
- case asEP_SCRIPT_SCANNER:
- return ep.scanner;
- case asEP_INCLUDE_JIT_INSTRUCTIONS:
- return ep.includeJitInstructions;
- case asEP_STRING_ENCODING:
- return ep.stringEncoding;
- case asEP_PROPERTY_ACCESSOR_MODE:
- return ep.propertyAccessorMode;
- case asEP_EXPAND_DEF_ARRAY_TO_TMPL:
- return ep.expandDefaultArrayToTemplate;
- case asEP_AUTO_GARBAGE_COLLECT:
- return ep.autoGarbageCollect;
- case asEP_DISALLOW_GLOBAL_VARS:
- return ep.disallowGlobalVars;
- }
- return 0;
- }
- } // extern "C"
- asCScriptEngine::asCScriptEngine()
- {
- // Instanciate the thread manager
- ENTERCRITICALSECTION(engineCritical);
- if( threadManager == 0 )
- threadManager = asNEW(asCThreadManager);
- else
- threadManager->AddRef();
- LEAVECRITICALSECTION(engineCritical);
- // Engine properties
- {
- ep.allowUnsafeReferences = false;
- ep.optimizeByteCode = true;
- ep.copyScriptSections = true;
- ep.maximumContextStackSize = 0; // no limit
- ep.useCharacterLiterals = false;
- ep.allowMultilineStrings = false;
- ep.allowImplicitHandleTypes = false;
- // TODO: optimize: Maybe this should be turned off by default? If a debugger is not used
- // then this is just slowing down the execution. The exception handler
- // should still be able to determine the line number from the bytecode
- // position.
- ep.buildWithoutLineCues = false;
- ep.initGlobalVarsAfterBuild = true;
- ep.requireEnumScope = false;
- ep.scanner = 1; // utf8. 0 = ascii
- ep.includeJitInstructions = false;
- ep.stringEncoding = 0; // utf8. 1 = utf16
- ep.propertyAccessorMode = 2; // 0 = disable, 1 = app registered only, 2 = app and script created
- ep.expandDefaultArrayToTemplate = false;
- ep.autoGarbageCollect = true;
- ep.disallowGlobalVars = false;
- }
- gc.engine = this;
- refCount.set(1);
- stringFactory = 0;
- configFailed = false;
- isPrepared = false;
- isBuilding = false;
- lastModule = 0;
- // User data
- userData = 0;
- cleanEngineFunc = 0;
- cleanModuleFunc = 0;
- cleanContextFunc = 0;
- cleanFunctionFunc = 0;
- cleanObjectTypeFunc = 0;
- initialContextStackSize = 1024; // 4 KB (1024 * sizeof(asDWORD)
- typeIdSeqNbr = 0;
- currentGroup = &defaultGroup;
- defaultAccessMask = 1;
- msgCallback = 0;
- jitCompiler = 0;
- // Reserve function id 0 for no function
- scriptFunctions.PushLast(0);
- // Make sure typeId for the built-in primitives are defined according to asETypeIdFlags
- int id;
- id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttVoid, false)); asASSERT( id == asTYPEID_VOID );
- id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttBool, false)); asASSERT( id == asTYPEID_BOOL );
- id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttInt8, false)); asASSERT( id == asTYPEID_INT8 );
- id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttInt16, false)); asASSERT( id == asTYPEID_INT16 );
- id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttInt, false)); asASSERT( id == asTYPEID_INT32 );
- id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttInt64, false)); asASSERT( id == asTYPEID_INT64 );
- id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttUInt8, false)); asASSERT( id == asTYPEID_UINT8 );
- id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttUInt16, false)); asASSERT( id == asTYPEID_UINT16 );
- id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttUInt, false)); asASSERT( id == asTYPEID_UINT32 );
- id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttUInt64, false)); asASSERT( id == asTYPEID_UINT64 );
- id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttFloat, false)); asASSERT( id == asTYPEID_FLOAT );
- id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttDouble, false)); asASSERT( id == asTYPEID_DOUBLE );
- defaultArrayObjectType = 0;
- RegisterScriptObject(this);
- RegisterScriptFunction(this);
- RegisterObjectTypeGCBehaviours(this);
- asCGlobalProperty::RegisterGCBehaviours(this);
- }
- asCScriptEngine::~asCScriptEngine()
- {
- asASSERT(refCount.get() == 0);
- asUINT n;
- // The modules must be deleted first, as they may use
- // object types from the config groups
- for( n = (asUINT)scriptModules.GetLength(); n-- > 0; )
- {
- if( scriptModules[n] )
- {
- asDELETE(scriptModules[n],asCModule);
- }
- }
- scriptModules.SetLength(0);
- GarbageCollect(asGC_FULL_CYCLE);
- // Delete the functions for template types that may references object types
- for( n = 0; n < templateTypes.GetLength(); n++ )
- {
- if( templateTypes[n] )
- {
- asUINT f;
- // Delete the factory stubs first
- for( f = 0; f < templateTypes[n]->beh.factories.GetLength(); f++ )
- {
- scriptFunctions[templateTypes[n]->beh.factories[f]]->Release();
- }
- templateTypes[n]->beh.factories.Allocate(0, false);
- // The list factory is not stored in the list with the rest of the factories
- if( templateTypes[n]->beh.listFactory )
- {
- scriptFunctions[templateTypes[n]->beh.listFactory]->Release();
- templateTypes[n]->beh.listFactory = 0;
- }
- // Delete the specialized functions
- for( f = 1; f < templateTypes[n]->beh.operators.GetLength(); f += 2 )
- {
- if( scriptFunctions[templateTypes[n]->beh.operators[f]]->objectType == templateTypes[n] )
- {
- scriptFunctions[templateTypes[n]->beh.operators[f]]->Release();
- templateTypes[n]->beh.operators[f] = 0;
- }
- }
- for( f = 0; f < templateTypes[n]->methods.GetLength(); f++ )
- {
- if( scriptFunctions[templateTypes[n]->methods[f]]->objectType == templateTypes[n] )
- {
- scriptFunctions[templateTypes[n]->methods[f]]->Release();
- templateTypes[n]->methods[f] = 0;
- }
- }
- }
- }
- // Do one more garbage collect to free gc objects that were global variables
- GarbageCollect(asGC_FULL_CYCLE);
- FreeUnusedGlobalProperties();
- ClearUnusedTypes();
- // Break all relationship between remaining class types and functions
- for( n = 0; n < classTypes.GetLength(); n++ )
- {
- if( classTypes[n] )
- classTypes[n]->ReleaseAllFunctions();
- if( classTypes[n]->derivedFrom )
- {
- classTypes[n]->derivedFrom->Release();
- classTypes[n]->derivedFrom = 0;
- }
- }
- GarbageCollect(asGC_FULL_CYCLE);
- FreeUnusedGlobalProperties();
- ClearUnusedTypes();
- // There may be instances where one more gc cycle must be run
- GarbageCollect(asGC_FULL_CYCLE);
- ClearUnusedTypes();
- // If the application hasn't registered GC behaviours for all types
- // that can form circular references with script types, then there
- // may still be objects in the GC.
- gc.ReportUndestroyedObjects();
- asSMapNode<int,asCDataType*> *cursor = 0;
- while( mapTypeIdToDataType.MoveFirst(&cursor) )
- {
- asDELETE(mapTypeIdToDataType.GetValue(cursor),asCDataType);
- mapTypeIdToDataType.Erase(cursor);
- }
- // First remove what is not used, so that other groups can be deleted safely
- defaultGroup.RemoveConfiguration(this, true);
- while( configGroups.GetLength() )
- {
- // Delete config groups in the right order
- asCConfigGroup *grp = configGroups.PopLast();
- if( grp )
- {
- grp->RemoveConfiguration(this);
- asDELETE(grp,asCConfigGroup);
- }
- }
- // Remove what is remaining
- defaultGroup.RemoveConfiguration(this);
- for( n = 0; n < registeredGlobalProps.GetLength(); n++ )
- {
- if( registeredGlobalProps[n] )
- registeredGlobalProps[n]->Release();
- }
- registeredGlobalProps.SetLength(0);
- FreeUnusedGlobalProperties();
- for( n = 0; n < templateTypes.GetLength(); n++ )
- {
- if( templateTypes[n] )
- {
- // Clear the sub type before deleting the template type so that the sub type isn't freed to soon
- templateTypes[n]->templateSubType = asCDataType::CreateNullHandle();
- asDELETE(templateTypes[n],asCObjectType);
- }
- }
- templateTypes.SetLength(0);
- for( n = 0; n < objectTypes.GetLength(); n++ )
- {
- if( objectTypes[n] )
- {
- // Clear the sub type before deleting the template type so that the sub type isn't freed to soon
- objectTypes[n]->templateSubType = asCDataType::CreateNullHandle();
- asDELETE(objectTypes[n],asCObjectType);
- }
- }
- objectTypes.SetLength(0);
- for( n = 0; n < templateSubTypes.GetLength(); n++ )
- {
- if( templateSubTypes[n] )
- {
- asDELETE(templateSubTypes[n], asCObjectType);
- }
- }
- templateSubTypes.SetLength(0);
- registeredTypeDefs.SetLength(0);
- registeredEnums.SetLength(0);
- registeredObjTypes.SetLength(0);
- for( n = 0; n < registeredGlobalFuncs.GetLength(); n++ )
- {
- if( registeredGlobalFuncs[n] )
- registeredGlobalFuncs[n]->Release();
- }
- registeredGlobalFuncs.SetLength(0);
- scriptTypeBehaviours.ReleaseAllFunctions();
- functionBehaviours.ReleaseAllFunctions();
- objectTypeBehaviours.ReleaseAllFunctions();
- globalPropertyBehaviours.ReleaseAllFunctions();
- // Free string constants
- for( n = 0; n < stringConstants.GetLength(); n++ )
- {
- asDELETE(stringConstants[n],asCString);
- }
- stringConstants.SetLength(0);
- // Free the script section names
- for( n = 0; n < scriptSectionNames.GetLength(); n++ )
- {
- asDELETE(scriptSectionNames[n],asCString);
- }
- scriptSectionNames.SetLength(0);
- // Clean the user data
- if( userData && cleanEngineFunc )
- cleanEngineFunc(this);
- // Release the thread manager
- threadManager->Release();
- }
- // interface
- int asCScriptEngine::AddRef() const
- {
- return refCount.atomicInc();
- }
- // interface
- int asCScriptEngine::Release() const
- {
- int r = refCount.atomicDec();
- if( r == 0 )
- {
- asDELETE(const_cast<asCScriptEngine*>(this),asCScriptEngine);
- return 0;
- }
- return r;
- }
- // interface
- void *asCScriptEngine::SetUserData(void *data)
- {
- void *old = userData;
- userData = data;
- return old;
- }
- // interface
- void *asCScriptEngine::GetUserData() const
- {
- return userData;
- }
- // interface
- int asCScriptEngine::SetMessageCallback(const asSFuncPtr &callback, void *obj, asDWORD callConv)
- {
- msgCallback = true;
- msgCallbackObj = obj;
- bool isObj = false;
- if( (unsigned)callConv == asCALL_GENERIC )
- {
- msgCallback = false;
- return asNOT_SUPPORTED;
- }
- if( (unsigned)callConv >= asCALL_THISCALL )
- {
- isObj = true;
- if( obj == 0 )
- {
- msgCallback = false;
- return asINVALID_ARG;
- }
- }
- int r = DetectCallingConvention(isObj, callback, callConv, &msgCallbackFunc);
- if( r < 0 ) msgCallback = false;
- return r;
- }
- // interface
- int asCScriptEngine::ClearMessageCallback()
- {
- msgCallback = false;
- return 0;
- }
- // interface
- int asCScriptEngine::WriteMessage(const char *section, int row, int col, asEMsgType type, const char *message)
- {
- // Validate input parameters
- if( section == 0 ||
- message == 0 )
- return asINVALID_ARG;
- // If there is no callback then there's nothing to do
- if( !msgCallback )
- return 0;
- asSMessageInfo msg;
- msg.section = section;
- msg.row = row;
- msg.col = col;
- msg.type = type;
- msg.message = message;
- if( msgCallbackFunc.callConv < ICC_THISCALL )
- CallGlobalFunction(&msg, msgCallbackObj, &msgCallbackFunc, 0);
- else
- CallObjectMethod(msgCallbackObj, &msg, &msgCallbackFunc, 0);
- return 0;
- }
- int asCScriptEngine::SetJITCompiler(asIJITCompiler *compiler)
- {
- jitCompiler = compiler;
- return asSUCCESS;
- }
- asIJITCompiler *asCScriptEngine::GetJITCompiler() const
- {
- return jitCompiler;
- }
- // interface
- asETokenClass asCScriptEngine::ParseToken(const char *string, size_t stringLength, int *tokenLength) const
- {
- if( stringLength == 0 )
- stringLength = strlen(string);
- size_t len;
- asCTokenizer t(this);
- asETokenClass tc;
- t.GetToken(string, stringLength, &len, &tc);
- if( tokenLength )
- *tokenLength = (int)len;
- return tc;
- }
- // interface
- asIScriptModule *asCScriptEngine::GetModule(const char *module, asEGMFlags flag)
- {
- asCModule *mod = GetModule(module, false);
- if( flag == asGM_ALWAYS_CREATE )
- {
- if( mod != 0 )
- {
- asDELETE(mod, asCModule);
- }
- return GetModule(module, true);
- }
- if( mod == 0 && flag == asGM_CREATE_IF_NOT_EXISTS )
- {
- return GetModule(module, true);
- }
- return mod;
- }
- // interface
- int asCScriptEngine::DiscardModule(const char *module)
- {
- asCModule *mod = GetModule(module, false);
- if( mod == 0 ) return asNO_MODULE;
- asDELETE(mod, asCModule);
- FreeUnusedGlobalProperties();
- ClearUnusedTypes();
- if( ep.autoGarbageCollect )
- GarbageCollect();
- return 0;
- }
- void asCScriptEngine::ClearUnusedTypes()
- {
- // Build a list of all types to check for
- asCArray<asCObjectType*> types;
- types = classTypes;
- types.Concatenate(templateInstanceTypes);
- // Go through all modules
- asUINT n;
- for( n = 0; n < scriptModules.GetLength() && types.GetLength(); n++ )
- {
- asCModule *mod = scriptModules[n];
- if( mod )
- {
- // Functions/Methods/Globals are handled after this
- // Go through all type declarations
- asUINT m;
- for( m = 0; m < mod->classTypes.GetLength() && types.GetLength(); m++ )
- RemoveTypeAndRelatedFromList(types, mod->classTypes[m]);
- for( m = 0; m < mod->enumTypes.GetLength() && types.GetLength(); m++ )
- RemoveTypeAndRelatedFromList(types, mod->enumTypes[m]);
- for( m = 0; m < mod->typeDefs.GetLength() && types.GetLength(); m++ )
- RemoveTypeAndRelatedFromList(types, mod->typeDefs[m]);
- }
- }
- // Go through all function parameters and remove used types
- for( n = 0; n < scriptFunctions.GetLength() && types.GetLength(); n++ )
- {
- asCScriptFunction *func = scriptFunctions[n];
- if( func )
- {
- // Ignore factory stubs
- if( func->name == "factstub" )
- continue;
- asCObjectType *ot = func->returnType.GetObjectType();
- if( ot != 0 && ot != func->objectType )
- if( func->name != ot->name )
- RemoveTypeAndRelatedFromList(types, ot);
- for( asUINT p = 0; p < func->parameterTypes.GetLength(); p++ )
- {
- ot = func->parameterTypes[p].GetObjectType();
- if( ot != 0 && ot != func->objectType )
- if( func->name != ot->name )
- RemoveTypeAndRelatedFromList(types, ot);
- }
- }
- }
- // Go through all global properties
- for( n = 0; n < globalProperties.GetLength() && types.GetLength(); n++ )
- {
- if( globalProperties[n] && globalProperties[n]->type.GetObjectType() )
- RemoveTypeAndRelatedFromList(types, globalProperties[n]->type.GetObjectType());
- }
- // All that remains in the list after this can be discarded, since they are no longer used
- for(;;)
- {
- bool didClearTemplateInstanceType = false;
- for( n = 0; n < types.GetLength(); n++ )
- {
- // Template types and script classes will have two references for each factory stub
- int refCount = 0;
- if( (types[n]->flags & asOBJ_TEMPLATE) || (types[n]->flags & asOBJ_SCRIPT_OBJECT) )
- {
- refCount = 2*(int)types[n]->beh.factories.GetLength();
- if( types[n]->beh.listFactory )
- refCount += 2;
- }
- if( types[n]->GetRefCount() == refCount )
- {
- if( types[n]->flags & asOBJ_TEMPLATE )
- {
- didClearTemplateInstanceType = true;
- RemoveTemplateInstanceType(types[n]);
- }
- else
- {
- RemoveFromTypeIdMap(types[n]);
- asDELETE(types[n],asCObjectType);
- int i = classTypes.IndexOf(types[n]);
- if( i == (signed)classTypes.GetLength() - 1 )
- classTypes.PopLast();
- else
- classTypes[i] = classTypes.PopLast();
- }
- // Remove the type from the array
- if( n < types.GetLength() - 1 )
- types[n] = types.PopLast();
- else
- types.PopLast();
- n--;
- }
- }
- if( didClearTemplateInstanceType == false )
- break;
- }
- }
- void asCScriptEngine::RemoveTypeAndRelatedFromList(asCArray<asCObjectType*> &types, asCObjectType *ot)
- {
- // Remove the type from the list
- int i = types.IndexOf(ot);
- if( i == -1 ) return;
- if( i == (signed)types.GetLength() - 1 )
- types.PopLast();
- else
- types[i] = types.PopLast();
- // If the type is an template type, then remove all sub types as well
- if( ot->templateSubType.GetObjectType() )
- {
- while( ot->templateSubType.GetObjectType() )
- {
- ot = ot->templateSubType.GetObjectType();
- RemoveTypeAndRelatedFromList(types, ot);
- }
- return;
- }
- // If the type is a class, then remove all properties types as well
- if( ot->properties.GetLength() )
- {
- for( asUINT n = 0; n < ot->properties.GetLength(); n++ )
- RemoveTypeAndRelatedFromList(types, ot->properties[n]->type.GetObjectType());
- }
- }
- // internal
- int asCScriptEngine::GetFactoryIdByDecl(const asCObjectType *ot, const char *decl)
- {
- asCModule *mod = 0;
- // Is this a script class?
- if( ot->flags & asOBJ_SCRIPT_OBJECT && ot->size > 0 )
- mod = scriptFunctions[ot->beh.factory]->module;
- asCBuilder bld(this, mod);
- asCScriptFunction func(this, mod, asFUNC_DUMMY);
- int r = bld.ParseFunctionDeclaration(0, decl, &func, false);
- if( r < 0 )
- return asINVALID_DECLARATION;
- // Search for matching factory function
- int id = -1;
- for( size_t n = 0; n < ot->beh.factories.GetLength(); n++ )
- {
- asCScriptFunction *f = scriptFunctions[ot->beh.factories[n]];
- if( f->IsSignatureEqual(&func) )
- {
- id = ot->beh.factories[n];
- break;
- }
- }
- if( id == -1 ) return asNO_FUNCTION;
- return id;
- }
- // internal
- int asCScriptEngine::GetMethodIdByDecl(const asCObjectType *ot, const char *decl, asCModule *mod)
- {
- asCBuilder bld(this, mod);
- asCScriptFunction func(this, mod, asFUNC_DUMMY);
- // Set the object type so that the signature can be properly compared
- // This cast is OK, it will only be used for comparison
- func.objectType = const_cast<asCObjectType*>(ot);
- int r = bld.ParseFunctionDeclaration(func.objectType, decl, &func, false);
- if( r < 0 )
- return asINVALID_DECLARATION;
- // Search script functions for matching interface
- int id = -1;
- for( size_t n = 0; n < ot->methods.GetLength(); ++n )
- {
- if( func.IsSignatureEqual(scriptFunctions[ot->methods[n]]) )
- {
- if( id == -1 )
- id = ot->methods[n];
- else
- return asMULTIPLE_FUNCTIONS;
- }
- }
- if( id == -1 ) return asNO_FUNCTION;
- return id;
- }
- // Internal
- asCString asCScriptEngine::GetFunctionDeclaration(int funcId)
- {
- asCString str;
- asCScriptFunction *func = GetScriptFunction(funcId);
- if( func )
- str = func->GetDeclarationStr();
- return str;
- }
- asCScriptFunction *asCScriptEngine::GetScriptFunction(int funcId) const
- {
- if( funcId < 0 || funcId >= (int)scriptFunctions.GetLength() )
- return 0;
- return scriptFunctions[funcId];
- }
- asIScriptContext *asCScriptEngine::CreateContext()
- {
- asIScriptContext *ctx = 0;
- CreateContext(&ctx, false);
- return ctx;
- }
- int asCScriptEngine::CreateContext(asIScriptContext **context, bool isInternal)
- {
- *context = asNEW(asCContext)(this, !isInternal);
- // We need to make sure the engine has been
- // prepared before any context is executed
- PrepareEngine();
- return 0;
- }
- int asCScriptEngine::RegisterObjectProperty(const char *obj, const char *declaration, int byteOffset)
- {
- int r;
- asCDataType dt;
- asCBuilder bld(this, 0);
- r = bld.ParseDataType(obj, &dt);
- if( r < 0 )
- return ConfigError(r);
- // Verify that the correct config group is used
- if( currentGroup->FindType(dt.GetObjectType()->name.AddressOf()) == 0 )
- return ConfigError(asWRONG_CONFIG_GROUP);
- asCDataType type;
- asCString name;
- if( (r = bld.VerifyProperty(&dt, declaration, name, type)) < 0 )
- return ConfigError(r);
- // Store the property info
- if( dt.GetObjectType() == 0 )
- return ConfigError(asINVALID_OBJECT);
- asCObjectProperty *prop = asNEW(asCObjectProperty);
- prop->name = name;
- prop->type = type;
- prop->byteOffset = byteOffset;
- prop->isPrivate = false;
- prop->accessMask = defaultAccessMask;
- dt.GetObjectType()->properties.PushLast(prop);
- currentGroup->RefConfigGroup(FindConfigGroupForObjectType(type.GetObjectType()));
- return asSUCCESS;
- }
- int asCScriptEngine::RegisterInterface(const char *name)
- {
- if( name == 0 ) return ConfigError(asINVALID_NAME);
- // Verify if the name has been registered as a type already
- asUINT n;
- for( n = 0; n < objectTypes.GetLength(); n++ )
- {
- if( objectTypes[n] && objectTypes[n]->name == name )
- return asALREADY_REGISTERED;
- }
- // Use builder to parse the datatype
- asCDataType dt;
- asCBuilder bld(this, 0);
- bool oldMsgCallback = msgCallback; msgCallback = false;
- int r = bld.ParseDataType(name, &dt);
- msgCallback = oldMsgCallback;
- if( r >= 0 ) return ConfigError(asERROR);
- // Make sure the name is not a reserved keyword
- asCTokenizer t(this);
- size_t tokenLen;
- int token = t.GetToken(name, strlen(name), &tokenLen);
- if( token != ttIdentifier || strlen(name) != tokenLen )
- return ConfigError(asINVALID_NAME);
- r = bld.CheckNameConflict(name, 0, 0);
- if( r < 0 )
- return ConfigError(asNAME_TAKEN);
- // Don't have to check against members of object
- // types as they are allowed to use the names
- // Register the object type for the interface
- asCObjectType *st = asNEW(asCObjectType)(this);
- st->flags = asOBJ_REF | asOBJ_SCRIPT_OBJECT | asOBJ_SHARED;
- st->size = 0; // Cannot be instanciated
- st->name = name;
- // Use the default script class behaviours
- st->beh.factory = 0;
- st->beh.addref = scriptTypeBehaviours.beh.addref;
- scriptFunctions[st->beh.addref]->AddRef();
- st->beh.release = scriptTypeBehaviours.beh.release;
- scriptFunctions[st->beh.release]->AddRef();
- st->beh.copy = 0;
- objectTypes.PushLast(st);
- registeredObjTypes.PushLast(st);
- currentGroup->objTypes.PushLast(st);
- return asSUCCESS;
- }
- int asCScriptEngine::RegisterInterfaceMethod(const char *intf, const char *declaration)
- {
- // Verify that the correct config group is set.
- if( currentGroup->FindType(intf) == 0 )
- return ConfigError(asWRONG_CONFIG_GROUP);
- asCDataType dt;
- asCBuilder bld(this, 0);
- int r = bld.ParseDataType(intf, &dt);
- if( r < 0 )
- return ConfigError(r);
- asCScriptFunction *func = asNEW(asCScriptFunction)(this, 0, asFUNC_INTERFACE);
- func->objectType = dt.GetObjectType();
- r = bld.ParseFunctionDeclaration(func->objectType, declaration, func, false);
- if( r < 0 )
- {
- asDELETE(func,asCScriptFunction);
- return ConfigError(asINVALID_DECLARATION);
- }
- // Check name conflicts
- r = bld.CheckNameConflictMember(dt.GetObjectType(), func->name.AddressOf(), 0, 0, false);
- if( r < 0 )
- {
- asDELETE(func,asCScriptFunction);
- return ConfigError(asNAME_TAKEN);
- }
- func->id = GetNextScriptFunctionId();
- SetScriptFunction(func);
- func->objectType->methods.PushLast(func->id);
- // The refCount was already set to 1
- func->ComputeSignatureId();
- // If parameter type from other groups are used, add references
- // TODO: The code for adding references to config groups is repeated in a lot of places
- if( func->returnType.GetObjectType() )
- {
- asCConfigGroup *group = FindConfigGroupForObjectType(func->returnType.GetObjectType());
- currentGroup->RefConfigGroup(group);
- }
- for( asUINT n = 0; n < func->parameterTypes.GetLength(); n++ )
- {
- if( func->parameterTypes[n].GetObjectType() )
- {
- asCConfigGroup *group = FindConfigGroupForObjectType(func->parameterTypes[n].GetObjectType());
- currentGroup->RefConfigGroup(group);
- }
- }
- // Return function id as success
- return func->id;
- }
- int asCScriptEngine::RegisterObjectType(const char *name, int byteSize, asDWORD flags)
- {
- int r;
- isPrepared = false;
- // Verify flags
- // Must have either asOBJ_REF or asOBJ_VALUE
- if( flags & asOBJ_REF )
- {
- // Can optionally have the asOBJ_GC, asOBJ_NOHANDLE, asOBJ_SCOPED, or asOBJ_TEMPLATE flag set, but nothing else
- if( flags & ~(asOBJ_REF | asOBJ_GC | asOBJ_NOHANDLE | asOBJ_SCOPED | asOBJ_TEMPLATE) )
- return ConfigError(asINVALID_ARG);
- // flags are exclusive
- if( (flags & asOBJ_GC) && (flags & (asOBJ_NOHANDLE|asOBJ_SCOPED)) )
- return ConfigError(asINVALID_ARG);
- if( (flags & asOBJ_NOHANDLE) && (flags & (asOBJ_GC|asOBJ_SCOPED)) )
- return ConfigError(asINVALID_ARG);
- if( (flags & asOBJ_SCOPED) && (flags & (asOBJ_GC|asOBJ_NOHANDLE)) )
- return ConfigError(asINVALID_ARG);
- }
- else if( flags & asOBJ_VALUE )
- {
- // Cannot use reference flags
- // TODO: template: Should be possible to register a value type as template type
- if( flags & (asOBJ_REF | asOBJ_GC | asOBJ_SCOPED | asOBJ_TEMPLATE) )
- return ConfigError(asINVALID_ARG);
- // flags are exclusive
- if( (flags & asOBJ_POD) && (flags & asOBJ_ASHANDLE) )
- return ConfigError(asINVALID_ARG);
- // If the app type is given, we must validate the flags
- if( flags & asOBJ_APP_CLASS )
- {
- // Must not set the primitive or float flag
- if( flags & (asOBJ_APP_PRIMITIVE |
- asOBJ_APP_FLOAT) )
- return ConfigError(asINVALID_ARG);
- }
- else if( flags & asOBJ_APP_PRIMITIVE )
- {
- // Must not set the class flags nor the float flag
- if( flags & (asOBJ_APP_CLASS |
- asOBJ_APP_CLASS_CONSTRUCTOR |
- asOBJ_APP_CLASS_DESTRUCTOR |
- asOBJ_APP_CLASS_ASSIGNMENT |
- asOBJ_APP_CLASS_COPY_CONSTRUCTOR |
- asOBJ_APP_FLOAT |
- asOBJ_APP_CLASS_ALLINTS |
- asOBJ_APP_CLASS_ALLFLOATS) )
- return ConfigError(asINVALID_ARG);
- }
- else if( flags & asOBJ_APP_FLOAT )
- {
- // Must not set the class flags nor the primitive flag
- if( flags & (asOBJ_APP_CLASS |
- asOBJ_APP_CLASS_CONSTRUCTOR |
- asOBJ_APP_CLASS_DESTRUCTOR |
- asOBJ_APP_CLASS_ASSIGNMENT |
- asOBJ_APP_CLASS_COPY_CONSTRUCTOR |
- asOBJ_APP_PRIMITIVE |
- asOBJ_APP_CLASS_ALLINTS |
- asOBJ_APP_CLASS_ALLFLOATS) )
- return ConfigError(asINVALID_ARG);
- }
- else if( flags & (asOBJ_APP_CLASS_CONSTRUCTOR |
- asOBJ_APP_CLASS_DESTRUCTOR |
- asOBJ_APP_CLASS_ASSIGNMENT |
- asOBJ_APP_CLASS_COPY_CONSTRUCTOR |
- asOBJ_APP_CLASS_ALLINTS |
- asOBJ_APP_CLASS_ALLFLOATS) )
- {
- // Must not set the class properties, without the class flag
- return ConfigError(asINVALID_ARG);
- }
- }
- else
- return ConfigError(asINVALID_ARG);
- // Don't allow anything else than the defined flags
- if( flags - (flags & asOBJ_MASK_VALID_FLAGS) )
- return ConfigError(asINVALID_ARG);
- // Value types must have a defined size
- if( (flags & asOBJ_VALUE) && byteSize == 0 )
- {
- WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_VALUE_TYPE_MUST_HAVE_SIZE);
- return ConfigError(asINVALID_ARG);
- }
- // Verify type name
- if( name == 0 )
- return ConfigError(asINVALID_NAME);
- asCString typeName;
- asCBuilder bld(this, 0);
- if( flags & asOBJ_TEMPLATE )
- {
- asCString subtypeName;
- r = bld.ParseTemplateDecl(name, &typeName, &subtypeName);
- if( r < 0 )
- return r;
- // Verify that the template name hasn't been registered as a type already
- asUINT n;
- for( n = 0; n < objectTypes.GetLength(); n++ )
- {
- if( objectTypes[n] && objectTypes[n]->name == typeName )
- return asALREADY_REGISTERED;
- }
- asCObjectType *type = asNEW(asCObjectType)(this);
- type->name = typeName;
- type->size = byteSize;
- type->flags = flags;
- type->accessMask = defaultAccessMask;
- // Store it in the object types
- objectTypes.PushLast(type);
- // Define a template subtype
- asCObjectType *subtype = 0;
- for( n = 0; n < templateSubTypes.GetLength(); n++ )
- {
- if( templateSubTypes[n]->name == subtypeName )
- {
- subtype = templateSubTypes[n];
- break;
- }
- }
- if( subtype == 0 )
- {
- // Create the new subtype if not already existing
- subtype = asNEW(asCObjectType)(this);
- subtype->name = subtypeName;
- subtype->size = 0;
- subtype->flags = asOBJ_TEMPLATE_SUBTYPE;
- templateSubTypes.PushLast(subtype);
- subtype->AddRef();
- }
- type->templateSubType = asCDataType::CreateObject(subtype, false);
- subtype->AddRef();
- currentGroup->objTypes.PushLast(type);
- registeredObjTypes.PushLast(type);
- }
- else
- {
- typeName = name;
- // Verify if the name has been registered as a type already
- asUINT n;
- for( n = 0; n < objectTypes.GetLength(); n++ )
- {
- if( objectTypes[n] && objectTypes[n]->name == typeName )
- return asALREADY_REGISTERED;
- }
- for( n = 0; n < templateTypes.GetLength(); n++ )
- {
- if( templateTypes[n] && templateTypes[n]->name == typeName )
- return asALREADY_REGISTERED;
- }
- // Verify the most recently created template instance type
- asCObjectType *mostRecentTemplateInstanceType = 0;
- if( templateInstanceTypes.GetLength() )
- mostRecentTemplateInstanceType = templateInstanceTypes[templateInstanceTypes.GetLength()-1];
- // Use builder to parse the datatype
- asCDataType dt;
- bool oldMsgCallback = msgCallback; msgCallback = false;
- r = bld.ParseDataType(name, &dt);
- msgCallback = oldMsgCallback;
- // If the builder fails, then the type name
- // is new and it should be registered
- if( r < 0 )
- {
- // Make sure the name is not a reserved keyword
- asCTokenizer t(this);
- size_t tokenLen;
- int token = t.GetToken(name, typeName.GetLength(), &tokenLen);
- if( token != ttIdentifier || typeName.GetLength() != tokenLen )
- return ConfigError(asINVALID_NAME);
- int r = bld.CheckNameConflict(name, 0, 0);
- if( r < 0 )
- return ConfigError(asNAME_TAKEN);
- // Don't have to check against members of object
- // types as they are allowed to use the names
- // Put the data type in the list
- asCObjectType *type = asNEW(asCObjectType)(this);
- type->name = typeName;
- type->size = byteSize;
- type->flags = flags;
- type->accessMask = defaultAccessMask;
- objectTypes.PushLast(type);
- registeredObjTypes.PushLast(type);
- currentGroup->objTypes.PushLast(type);
- }
- else
- {
- // The application is registering a template specialization so we
- // need to replace the template instance type with the new type.
- // TODO: Template: We don't require the lower dimensions to be registered first for registered template types
- // int[][] must not be allowed to be registered
- // if int[] hasn't been registered first
- if( dt.GetSubType().IsTemplate() )
- return ConfigError(asLOWER_ARRAY_DIMENSION_NOT_REGISTERED);
- if( dt.IsReadOnly() ||
- dt.IsReference() )
- return ConfigError(asINVALID_TYPE);
- // Was the template instance type created before?
- if( templateInstanceTypes[templateInstanceTypes.GetLength()-1] == mostRecentTemplateInstanceType ||
- mostRecentTemplateInstanceType == dt.GetObjectType() )
- // TODO: Should have a better error message
- return ConfigError(asNOT_SUPPORTED);
- // TODO: Add this again. The type is used by the factory stubs so we need to discount that
- // Is the template instance type already being used?
- // if( dt.GetObjectType()->GetRefCount() > 1 )
- // return ConfigError(asNOT_SUPPORTED);
- // Put the data type in the list
- asCObjectType *type = asNEW(asCObjectType)(this);
- type->name = dt.GetObjectType()->name;
- type->templateSubType = dt.GetSubType();
- if( type->templateSubType.GetObjectType() ) type->templateSubType.GetObjectType()->AddRef();
- type->size = byteSize;
- type->flags = flags;
- type->accessMask = defaultAccessMask;
- templateTypes.PushLast(type);
- currentGroup->objTypes.PushLast(type);
- // Remove the template instance type, which will no longer be used.
- RemoveTemplateInstanceType(dt.GetObjectType());
- }
- }
- // Return the type id as the success (except for template types)
- if( flags & asOBJ_TEMPLATE )
- return asSUCCESS;
- return GetTypeIdByDecl(name);
- }
- // interface
- int asCScriptEngine::RegisterObjectBehaviour(const char *datatype, asEBehaviours behaviour, const char *decl, const asSFuncPtr &funcPointer, asDWORD callConv)
- {
- if( datatype == 0 ) return ConfigError(asINVALID_ARG);
- // Determine the object type
- asCBuilder bld(this, 0);
- asCDataType type;
- int r = bld.ParseDataType(datatype, &type);
- if( r < 0 )
- return ConfigError(r);
- if( type.GetObjectType() == 0 )
- return ConfigError(asINVALID_TYPE);
- if( type.IsReadOnly() || type.IsReference() )
- return ConfigError(asINVALID_TYPE);
- return RegisterBehaviourToObjectType(type.GetObjectType(), behaviour, decl, funcPointer, callConv);
- }
- // internal
- int asCScriptEngine::RegisterBehaviourToObjectType(asCObjectType *objectType, asEBehaviours behaviour, const char *decl, const asSFuncPtr &funcPointer, asDWORD callConv)
- {
- asSSystemFunctionInterface internal;
- if( behaviour == asBEHAVE_FACTORY ||
- behaviour == asBEHAVE_LIST_FACTORY ||
- behaviour == asBEHAVE_TEMPLATE_CALLBACK )
- {
- #ifdef AS_MAX_PORTABILITY
- if( callConv != asCALL_GENERIC )
- return ConfigError(asNOT_SUPPORTED);
- #endif
- int r = DetectCallingConvention(false, funcPointer, callConv, &internal);
- if( r < 0 )
- return ConfigError(r);
- }
- else
- {
- #ifdef AS_MAX_PORTABILITY
- if( callConv != asCALL_GENERIC )
- return ConfigError(asNOT_SUPPORTED);
- #else
- if( callConv != asCALL_THISCALL &&
- callConv != asCALL_CDECL_OBJLAST &&
- callConv != asCALL_CDECL_OBJFIRST &&
- callConv != asCALL_GENERIC )
- return ConfigError(asNOT_SUPPORTED);
- #endif
- int r = DetectCallingConvention(true, funcPointer, callConv, &internal);
- if( r < 0 )
- return ConfigError(r);
- }
- isPrepared = false;
- asSTypeBehaviour *beh = &objectType->beh;
- // Verify function declaration
- asCScriptFunction func(this, 0, asFUNC_DUMMY);
- asCBuilder bld(this, 0);
- int r = bld.ParseFunctionDeclaration(objectType, decl, &func, true, &internal.paramAutoHandles, &internal.returnAutoHandle);
- if( r < 0 )
- return ConfigError(asINVALID_DECLARATION);
- func.name.Format("_beh_%d_", behaviour);
- if( behaviour != asBEHAVE_FACTORY && behaviour != asBEHAVE_LIST_FACTORY )
- func.objectType = objectType;
- // Check if the method restricts that use of the template to value types or reference types
- if( objectType->flags & asOBJ_TEMPLATE )
- {
- if( func.returnType.GetObjectType() == objectType->templateSubType.GetObjectType() )
- {
- if( func.returnType.IsObjectHandle() )
- objectType->acceptValueSubType = false;
- else if( !func.returnType.IsReference() )
- objectType->acceptRefSubType = false;
- }
- for( asUINT n = 0; n < func.parameterTypes.GetLength(); n++ )
- {
- if( func.parameterTypes[n].GetObjectType() == objectType->templateSubType.GetObjectType() )
- {
- // TODO: If unsafe references are allowed, then inout references allow value types
- if( func.parameterTypes[n].IsObjectHandle() || (func.parameterTypes[n].IsReference() && func.inOutFlags[n] == asTM_INOUTREF) )
- objectType->acceptValueSubType = false;
- else if( !func.parameterTypes[n].IsReference() )
- objectType->acceptRefSubType = false;
- }
- }
- }
- if( behaviour == asBEHAVE_CONSTRUCT )
- {
- // TODO: Add asBEHAVE_IMPLICIT_CONSTRUCT
- // Verify that the return type is void
- if( func.returnType != asCDataType::CreatePrimitive(ttVoid, false) )
- return ConfigError(asINVALID_DECLARATION);
- if( objectType->flags & asOBJ_SCRIPT_OBJECT )
- {
- // The script object is a special case
- asASSERT(func.parameterTypes.GetLength() == 1);
- beh->construct = AddBehaviourFunction(func, internal);
- beh->factory = beh->construct;
- scriptFunctions[beh->factory]->AddRef();
- beh->constructors.PushLast(beh->construct);
- beh->factories.PushLast(beh->factory);
- func.id = beh->construct;
- }
- else
- {
- // Verify that it is a value type
- if( !(func.objectType->flags & asOBJ_VALUE) )
- {
- WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
- return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE);
- }
- // TODO: Add support for implicit constructors
- // TODO: Verify that the same constructor hasn't been registered already
- // Store all constructors in a list
- func.id = AddBehaviourFunction(func, internal);
- beh->constructors.PushLast(func.id);
- if( func.parameterTypes.GetLength() == 0 )
- {
- beh->construct = func.id;
- }
- else if( func.parameterTypes.GetLength() == 1 )
- {
- // Is this the copy constructor?
- asCDataType paramType = func.parameterTypes[0];
- // If the parameter is object, and const reference for input,
- // and same type as this class, then this is a copy constructor.
- if( paramType.IsObject() && paramType.IsReference() && paramType.IsReadOnly() && func.inOutFlags[0] == asTM_INREF && paramType.GetObjectType() == objectType )
- beh->copyconstruct = func.id;
- }
- }
- }
- else if( behaviour == asBEHAVE_DESTRUCT )
- {
- // Must be a value type
- if( !(func.objectType->flags & asOBJ_VALUE) )
- {
- WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
- return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE);
- }
- if( beh->destruct )
- return ConfigError(asALREADY_REGISTERED);
- // Verify that the return type is void
- if( func.returnType != asCDataType::CreatePrimitive(ttVoid, false) )
- return ConfigError(asINVALID_DECLARATION);
- // Verify that there are no parameters
- if( func.parameterTypes.GetLength() > 0 )
- return ConfigError(asINVALID_DECLARATION);
- func.id = beh->destruct = AddBehaviourFunction(func, internal);
- }
- else if( behaviour == asBEHAVE_FACTORY || behaviour == asBEHAVE_LIST_FACTORY )
- {
- // Must be a ref type and must not have asOBJ_NOHANDLE
- if( !(objectType->flags & asOBJ_REF) || (objectType->flags & asOBJ_NOHANDLE) )
- {
- WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
- return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE);
- }
- // Verify that the return type is a handle to the type
- if( func.returnType != asCDataType::CreateObjectHandle(objectType, false) )
- return ConfigError(asINVALID_DECLARATION);
- // TODO: Add support for implicit factories
- // TODO: Verify that the same factory function hasn't been registered already
- // The templates take a hidden parameter with the object type
- if( (objectType->flags & asOBJ_TEMPLATE) &&
- (func.parameterTypes.GetLength() == 0 ||
- !func.parameterTypes[0].IsReference()) )
- {
- return ConfigError(asINVALID_DECLARATION);
- }
- // Store all factory functions in a list
- func.id = AddBehaviourFunction(func, internal);
- // The list factory is a special factory and isn't stored together with the rest
- if( behaviour != asBEHAVE_LIST_FACTORY )
- beh->factories.PushLast(func.id);
- if( (func.parameterTypes.GetLength() == 0) ||
- (func.parameterTypes.GetLength() == 1 && (objectType->flags & asOBJ_TEMPLATE)) )
- {
- beh->factory = func.id;
- }
- else if( (func.parameterTypes.GetLength() == 1) ||
- (func.parameterTypes.GetLength() == 2 && (objectType->flags & asOBJ_TEMPLATE)) )
- {
- if( behaviour == asBEHAVE_LIST_FACTORY )
- beh->listFactory = func.id;
- else
- {
- // Is this the copy factory?
- asCDataType paramType = func.parameterTypes[func.parameterTypes.GetLength()-1];
- // If the parameter is object, and const reference for input,
- // and same type as this class, then this is a copy constructor.
- if( paramType.IsObject() && paramType.IsReference() && paramType.IsReadOnly() && func.inOutFlags[func.parameterTypes.GetLength()-1] == asTM_INREF && paramType.GetObjectType() == objectType )
- beh->copyfactory = func.id;
- }
- }
- }
- else if( behaviour == asBEHAVE_ADDREF )
- {
- // Must be a ref type and must not have asOBJ_NOHANDLE, nor asOBJ_SCOPED
- if( !(func.objectType->flags & asOBJ_REF) ||
- (func.objectType->flags & asOBJ_NOHANDLE) ||
- (func.objectType->flags & asOBJ_SCOPED) )
- {
- WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
- return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE);
- }
- if( beh->addref )
- return ConfigError(asALREADY_REGISTERED);
- // Verify that the return type is void
- if( func.returnType != asCDataType::CreatePrimitive(ttVoid, false) )
- return ConfigError(asINVALID_DECLARATION);
- // Verify that there are no parameters
- if( func.parameterTypes.GetLength() > 0 )
- return ConfigError(asINVALID_DECLARATION);
- func.id = beh->addref = AddBehaviourFunction(func, internal);
- }
- else if( behaviour == asBEHAVE_RELEASE )
- {
- // Must be a ref type and must not have asOBJ_NOHANDLE
- if( !(func.objectType->flags & asOBJ_REF) || (func.objectType->flags & asOBJ_NOHANDLE) )
- {
- WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
- return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE);
- }
- if( beh->release )
- return ConfigError(asALREADY_REGISTERED);
- // Verify that the return type is void
- if( func.returnType != asCDataType::CreatePrimitive(ttVoid, false) )
- return ConfigError(asINVALID_DECLARATION);
- // Verify that there are no parameters
- if( func.parameterTypes.GetLength() > 0 )
- return ConfigError(asINVALID_DECLARATION);
- func.id = beh->release = AddBehaviourFunction(func, internal);
- }
- else if( behaviour == asBEHAVE_TEMPLATE_CALLBACK )
- {
- // Must be a template type
- if( !(func.objectType->flags & asOBJ_TEMPLATE) )
- {
- WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
- return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE);
- }
- if( beh->templateCallback )
- return ConfigError(asALREADY_REGISTERED);
- // Verify that the return type is bool
- if( func.returnType != asCDataType::CreatePrimitive(ttBool, false) )
- return ConfigError(asINVALID_DECLARATION);
- // Verify that there is one parameters
- if( func.parameterTypes.GetLength() != 1 )
- return ConfigError(asINVALID_DECLARATION);
- func.id = beh->templateCallback = AddBehaviourFunction(func, internal);
- }
- else if( behaviour >= asBEHAVE_FIRST_GC &&
- behaviour <= asBEHAVE_LAST_GC )
- {
- // Only allow GC behaviours for types registered to be garbage collected
- if( !(func.objectType->flags & asOBJ_GC) )
- {
- WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
- return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE);
- }
- // Verify parameter count
- if( (behaviour == asBEHAVE_GETREFCOUNT ||
- behaviour == asBEHAVE_SETGCFLAG ||
- behaviour == asBEHAVE_GETGCFLAG) &&
- func.parameterTypes.GetLength() != 0 )
- return ConfigError(asINVALID_DECLARATION);
- if( (behaviour == asBEHAVE_ENUMREFS ||
- behaviour == asBEHAVE_RELEASEREFS) &&
- func.parameterTypes.GetLength() != 1 )
- return ConfigError(asINVALID_DECLARATION);
- // Verify return type
- if( behaviour == asBEHAVE_GETREFCOUNT &&
- func.returnType != asCDataType::CreatePrimitive(ttInt, false) )
- return ConfigError(asINVALID_DECLARATION);
- if( behaviour == asBEHAVE_GETGCFLAG &&
- func.returnType != asCDataType::CreatePrimitive(ttBool, false) )
- return ConfigError(asINVALID_DECLARATION);
- if( (behaviour == asBEHAVE_SETGCFLAG ||
- behaviour == asBEHAVE_ENUMREFS ||
- behaviour == asBEHAVE_RELEASEREFS) &&
- func.returnType != asCDataType::CreatePrimitive(ttVoid, false) )
- return ConfigError(asINVALID_DECLARATION);
- if( behaviour == asBEHAVE_GETREFCOUNT )
- func.id = beh->gcGetRefCount = AddBehaviourFunction(func, internal);
- else if( behaviour == asBEHAVE_SETGCFLAG )
- func.id = beh->gcSetFlag = AddBehaviourFunction(func, internal);
- else if( behaviour == asBEHAVE_GETGCFLAG )
- func.id = beh->gcGetFlag = AddBehaviourFunction(func, internal);
- else if( behaviour == asBEHAVE_ENUMREFS )
- func.id = beh->gcEnumReferences = AddBehaviourFunction(func, internal);
- else if( behaviour == asBEHAVE_RELEASEREFS )
- func.id = beh->gcReleaseAllReferences = AddBehaviourFunction(func, internal);
- }
- else if( behaviour == asBEHAVE_IMPLICIT_VALUE_CAST ||
- behaviour == asBEHAVE_VALUE_CAST )
- {
- // Verify parameter count
- if( func.parameterTypes.GetLength() != 0 )
- return ConfigError(asINVALID_DECLARATION);
- // Verify return type
- if( func.returnType.IsEqualExceptRefAndConst(asCDataType::CreatePrimitive(ttBool, false)) )
- return ConfigError(asNOT_SUPPORTED);
- if( func.returnType.IsEqualExceptRefAndConst(asCDataType::CreatePrimitive(ttVoid, false)) )
- return ConfigError(asINVALID_DECLARATION);
- // TODO: verify that the same cast is not registered already (const or non-const is treated the same for the return type)
- beh->operators.PushLast(behaviour);
- func.id = AddBehaviourFunction(func, internal);
- beh->operators.PushLast(func.id);
- }
- else if( behaviour == asBEHAVE_REF_CAST ||
- behaviour == asBEHAVE_IMPLICIT_REF_CAST )
- {
- // There are two allowed signatures
- // 1. obj @f()
- // 2. void f(?&out)
- if( !(func.parameterTypes.GetLength() == 0 && func.returnType.IsObjectHandle()) &&
- !(func.parameterTypes.GetLength() == 1 && func.parameterTypes[0].GetTokenType() == ttQuestion && func.inOutFlags[0] == asTM_OUTREF && func.returnType.GetTokenType() == ttVoid) )
- {
- return ConfigError(asINVALID_DECLARATION);
- }
- // TODO: verify that the same cast is not registered already (cosnt or non-const is treated the same for the return type)
- beh->operators.PushLast(behaviour);
- func.id = AddBehaviourFunction(func, internal);
- beh->operators.PushLast(func.id);
- }
- else
- {
- asASSERT(false);
- return ConfigError(asINVALID_ARG);
- }
- // Return function id as success
- return func.id;
- }
- int asCScriptEngine::VerifyVarTypeNotInFunction(asCScriptFunction *func)
- {
- // Don't allow var type in this function
- if( func->returnType.GetTokenType() == ttQuestion )
- return asINVALID_DECLARATION;
- for( unsigned int n = 0; n < func->parameterTypes.GetLength(); n++ )
- if( func->parameterTypes[n].GetTokenType() == ttQuestion )
- return asINVALID_DECLARATION;
- return 0;
- }
- int asCScriptEngine::AddBehaviourFunction(asCScriptFunction &func, asSSystemFunctionInterface &internal)
- {
- asUINT n;
- int id = GetNextScriptFunctionId();
- asSSystemFunctionInterface *newInterface = asNEW(asSSystemFunctionInterface);
- newInterface->func = internal.func;
- newInterface->baseOffset = internal.baseOffset;
- newInterface->callConv = internal.callConv;
- newInterface->scriptReturnSize = internal.scriptReturnSize;
- newInterface->hostReturnInMemory = internal.hostReturnInMemory;
- newInterface->hostReturnFloat = internal.hostReturnFloat;
- newInterface->hostReturnSize = internal.hostReturnSize;
- newInterface->paramSize = internal.paramSize;
- newInterface->takesObjByVal = internal.takesObjByVal;
- newInterface->paramAutoHandles = internal.paramAutoHandles;
- newInterface->returnAutoHandle = internal.returnAutoHandle;
- newInterface->hasAutoHandles = internal.hasAutoHandles;
- asCScriptFunction *f = asNEW(asCScriptFunction)(this, 0, asFUNC_SYSTEM);
- asASSERT(func.name != "" && func.name != "f");
- f->name = func.name;
- f->sysFuncIntf = newInterface;
- f->returnType = func.returnType;
- f->objectType = func.objectType;
- f->id = id;
- f->isReadOnly = func.isReadOnly;
- f->accessMask = defaultAccessMask;
- f->parameterTypes = func.parameterTypes;
- f->inOutFlags = func.inOutFlags;
- for( n = 0; n < func.defaultArgs.GetLength(); n++ )
- if( func.defaultArgs[n] )
- f->defaultArgs.PushLast(asNEW(asCString)(*func.defaultArgs[n]));
- else
- f->defaultArgs.PushLast(0);
- SetScriptFunction(f);
- // If parameter type from other groups are used, add references
- if( f->returnType.GetObjectType() )
- {
- asCConfigGroup *group = FindConfigGroupForObjectType(f->returnType.GetObjectType());
- currentGroup->RefConfigGroup(group);
- }
- for( n = 0; n < f->parameterTypes.GetLength(); n++ )
- {
- if( f->parameterTypes[n].GetObjectType() )
- {
- asCConfigGroup *group = FindConfigGroupForObjectType(f->parameterTypes[n].GetObjectType());
- currentGroup->RefConfigGroup(group);
- }
- }
- return id;
- }
- // interface
- int asCScriptEngine::RegisterGlobalProperty(const char *declaration, void *pointer)
- {
- asCDataType type;
- asCString name;
- int r;
- asCBuilder bld(this, 0);
- if( (r = bld.VerifyProperty(0, declaration, name, type)) < 0 )
- return ConfigError(r);
- // Don't allow registering references as global properties
- if( type.IsReference() )
- return ConfigError(asINVALID_TYPE);
- // Store the property info
- asCGlobalProperty *prop = AllocateGlobalProperty();
- prop->name = name;
- prop->type = type;
- prop->accessMask = defaultAccessMask;
- prop->SetRegisteredAddress(pointer);
-
- registeredGlobalProps.PushLast(prop);
- currentGroup->globalProps.PushLast(prop);
- // If from another group add reference
- if( type.GetObjectType() )
- {
- asCConfigGroup *group = FindConfigGroupForObjectType(type.GetObjectType());
- currentGroup->RefConfigGroup(group);
- }
- return asSUCCESS;
- }
- // internal
- asCGlobalProperty *asCScriptEngine::AllocateGlobalProperty()
- {
- asCGlobalProperty *prop = asNEW(asCGlobalProperty);
- // First check the availability of a free slot
- if( freeGlobalPropertyIds.GetLength() )
- {
- prop->id = freeGlobalPropertyIds.PopLast();
- globalProperties[prop->id] = prop;
- return prop;
- }
- prop->id = (asUINT)globalProperties.GetLength();
- globalProperties.PushLast(prop);
- return prop;
- }
- // internal
- void asCScriptEngine::FreeUnusedGlobalProperties()
- {
- for( asUINT n = 0; n < globalProperties.GetLength(); n++ )
- {
- if( globalProperties[n] && globalProperties[n]->GetRefCount() == 0 )
- {
- freeGlobalPropertyIds.PushLast(n);
- asDELETE(globalProperties[n], asCGlobalProperty);
- globalProperties[n] = 0;
- }
- }
- }
- // interface
- asUINT asCScriptEngine::GetGlobalPropertyCount() const
- {
- return registeredGlobalProps.GetLength();
- }
- // interface
- // TODO: If the typeId ever encodes the const flag, then the isConst parameter should be removed
- int asCScriptEngine::GetGlobalPropertyByIndex(asUINT index, const char **name, int *typeId, bool *isConst, const char **configGroup, void **pointer) const
- {
- if( index >= registeredGlobalProps.GetLength() )
- return asINVALID_ARG;
- if( name )
- *name = registeredGlobalProps[index]->name.AddressOf();
- if( configGroup )
- {
- asCConfigGroup *group = FindConfigGroupForGlobalVar(index);
- if( group )
- *configGroup = group->groupName.AddressOf();
- else
- *configGroup = 0;
- }
- if( typeId )
- *typeId = GetTypeIdFromDataType(registeredGlobalProps[index]->type);
- if( isConst )
- *isConst = registeredGlobalProps[index]->type.IsReadOnly();
- if( pointer )
- *pointer = registeredGlobalProps[index]->GetRegisteredAddress();
- return asSUCCESS;
- }
- // interface
- int asCScriptEngine::RegisterObjectMethod(const char *obj, const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv)
- {
- if( obj == 0 )
- return ConfigError(asINVALID_ARG);
- // Determine the object type
- asCDataType dt;
- asCBuilder bld(this, 0);
- int r = bld.ParseDataType(obj, &dt);
- if( r < 0 )
- return ConfigError(r);
- if( dt.GetObjectType() == 0 )
- return ConfigError(asINVALID_ARG);
- return RegisterMethodToObjectType(dt.GetObjectType(), declaration, funcPointer, callConv);
- }
- // internal
- int asCScriptEngine::RegisterMethodToObjectType(asCObjectType *objectType, const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv)
- {
- asSSystemFunctionInterface internal;
- int r = DetectCallingConvention(true, funcPointer, callConv, &internal);
- if( r < 0 )
- return ConfigError(r);
- // We only support these calling conventions for object methods
- #ifdef AS_MAX_PORTABILITY
- if( callConv != asCALL_GENERIC )
- return ConfigError(asNOT_SUPPORTED);
- #else
- if( callConv != asCALL_THISCALL &&
- callConv != asCALL_CDECL_OBJLAST &&
- callConv != asCALL_CDECL_OBJFIRST &&
- callConv != asCALL_GENERIC )
- return ConfigError(asNOT_SUPPORTED);
- #endif
- isPrepared = false;
- // Put the system function in the list of system functions
- asSSystemFunctionInterface *newInterface = asNEW(asSSystemFunctionInterface)(internal);
- asCScriptFunction *func = asNEW(asCScriptFunction)(this, 0, asFUNC_SYSTEM);
- func->sysFuncIntf = newInterface;
- func->objectType = objectType;
- asCBuilder bld(this, 0);
- r = bld.ParseFunctionDeclaration(func->objectType, declaration, func, true, &newInterface->paramAutoHandles, &newInterface->returnAutoHandle);
- if( r < 0 )
- {
- // Set as dummy function before deleting
- func->funcType = asFUNC_DUMMY;
- asDELETE(func,asCScriptFunction);
- return ConfigError(asINVALID_DECLARATION);
- }
- // Check name conflicts
- r = bld.CheckNameConflictMember(objectType, func->name.AddressOf(), 0, 0, false);
- if( r < 0 )
- {
- asDELETE(func,asCScriptFunction);
- return ConfigError(asNAME_TAKEN);
- }
- func->id = GetNextScriptFunctionId();
- func->objectType->methods.PushLast(func->id);
- func->accessMask = defaultAccessMask;
- SetScriptFunction(func);
- // TODO: This code is repeated in many places
- // If parameter type from other groups are used, add references
- if( func->returnType.GetObjectType() )
- {
- asCConfigGroup *group = FindConfigGroupForObjectType(func->returnType.GetObjectType());
- currentGroup->RefConfigGroup(group);
- }
- for( asUINT n = 0; n < func->parameterTypes.GetLength(); n++ )
- {
- if( func->parameterTypes[n].GetObjectType() )
- {
- asCConfigGroup *group = FindConfigGroupForObjectType(func->parameterTypes[n].GetObjectType());
- currentGroup->RefConfigGroup(group);
- }
- }
- // Check if the method restricts that use of the template to value types or reference types
- if( func->objectType->flags & asOBJ_TEMPLATE )
- {
- if( func->returnType.GetObjectType() == func->objectType->templateSubType.GetObjectType() )
- {
- if( func->returnType.IsObjectHandle() )
- func->objectType->acceptValueSubType = false;
- else if( !func->returnType.IsReference() )
- func->objectType->acceptRefSubType = false;
- }
- for( asUINT n = 0; n < func->parameterTypes.GetLength(); n++ )
- {
- if( func->parameterTypes[n].GetObjectType() == func->objectType->templateSubType.GetObjectType() )
- {
- // TODO: If unsafe references are allowed, then inout references allow value types
- if( func->parameterTypes[n].IsObjectHandle() || (func->parameterTypes[n].IsReference() && func->inOutFlags[n] == asTM_INOUTREF) )
- func->objectType->acceptValueSubType = false;
- else if( !func->parameterTypes[n].IsReference() )
- func->objectType->acceptRefSubType = false;
- }
- }
- }
- // TODO: beh.copy member will be removed, so this is not necessary
- // Is this the default copy behaviour?
- if( func->name == "opAssign" && func->parameterTypes.GetLength() == 1 && func->isReadOnly == false &&
- (objectType->flags & asOBJ_SCRIPT_OBJECT || func->parameterTypes[0].IsEqualExceptRefAndConst(asCDataType::CreateObject(func->objectType, false))) )
- {
- func->objectType->beh.copy = func->id;
- func->AddRef();
- }
- // Return the function id as success
- return func->id;
- }
- // interface
- int asCScriptEngine::RegisterGlobalFunction(const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv)
- {
- asSSystemFunctionInterface internal;
- int r = DetectCallingConvention(false, funcPointer, callConv, &internal);
- if( r < 0 )
- return ConfigError(r);
- #ifdef AS_MAX_PORTABILITY
- if( callConv != asCALL_GENERIC )
- return ConfigError(asNOT_SUPPORTED);
- #else
- if( callConv != asCALL_CDECL &&
- callConv != asCALL_STDCALL &&
- callConv != asCALL_GENERIC )
- return ConfigError(asNOT_SUPPORTED);
- #endif
- isPrepared = false;
- // Put the system function in the list of system functions
- asSSystemFunctionInterface *newInterface = asNEW(asSSystemFunctionInterface)(internal);
- asCScriptFunction *func = asNEW(asCScriptFunction)(this, 0, asFUNC_SYSTEM);
- func->sysFuncIntf = newInterface;
- asCBuilder bld(this, 0);
- r = bld.ParseFunctionDeclaration(0, declaration, func, true, &newInterface->paramAutoHandles, &newInterface->returnAutoHandle);
- if( r < 0 )
- {
- // Set as dummy function before deleting
- func->funcType = asFUNC_DUMMY;
- asDELETE(func,asCScriptFunction);
- return ConfigError(asINVALID_DECLARATION);
- }
- // Check name conflicts
- r = bld.CheckNameConflict(func->name.AddressOf(), 0, 0);
- if( r < 0 )
- {
- asDELETE(func,asCScriptFunction);
- return ConfigError(asNAME_TAKEN);
- }
- func->id = GetNextScriptFunctionId();
- SetScriptFunction(func);
- currentGroup->scriptFunctions.PushLast(func);
- func->accessMask = defaultAccessMask;
- registeredGlobalFuncs.PushLast(func);
- // If parameter type from other groups are used, add references
- if( func->returnType.GetObjectType() )
- {
- asCConfigGroup *group = FindConfigGroupForObjectType(func->returnType.GetObjectType());
- currentGroup->RefConfigGroup(group);
- }
- for( asUINT n = 0; n < func->parameterTypes.GetLength(); n++ )
- {
- if( func->parameterTypes[n].GetObjectType() )
- {
- asCConfigGroup *group = FindConfigGroupForObjectType(func->parameterTypes[n].GetObjectType());
- currentGroup->RefConfigGroup(group);
- }
- }
- // Return the function id as success
- return func->id;
- }
- // interface
- asUINT asCScriptEngine::GetGlobalFunctionCount() const
- {
- return registeredGlobalFuncs.GetLength();
- }
- // interface
- int asCScriptEngine::GetGlobalFunctionIdByIndex(asUINT index) const
- {
- if( index >= registeredGlobalFuncs.GetLength() )
- return asINVALID_ARG;
- return registeredGlobalFuncs[index]->id;
- }
- // interface
- asIScriptFunction *asCScriptEngine::GetGlobalFunctionByIndex(asUINT index) const
- {
- if( index >= registeredGlobalFuncs.GetLength() )
- return 0;
- return registeredGlobalFuncs[index];
- }
- // interface
- asIScriptFunction *asCScriptEngine::GetGlobalFunctionByDecl(const char *decl) const
- {
- asCBuilder bld(const_cast<asCScriptEngine*>(this), 0);
- asCScriptFunction func(const_cast<asCScriptEngine*>(this), 0, asFUNC_DUMMY);
- int r = bld.ParseFunctionDeclaration(0, decl, &func, false);
- if( r < 0 )
- return 0;
- // TODO: optimize: Improve linear search
- // Search registered functions for matching interface
- int id = -1;
- for( size_t n = 0; n < registeredGlobalFuncs.GetLength(); ++n )
- {
- if( registeredGlobalFuncs[n]->objectType == 0 &&
- func.name == registeredGlobalFuncs[n]->name &&
- func.returnType == registeredGlobalFuncs[n]->returnType &&
- func.parameterTypes.GetLength() == registeredGlobalFuncs[n]->parameterTypes.GetLength() )
- {
- bool match = true;
- for( size_t p = 0; p < func.parameterTypes.GetLength(); ++p )
- {
- if( func.parameterTypes[p] != registeredGlobalFuncs[n]->parameterTypes[p] )
- {
- match = false;
- break;
- }
- }
- if( match )
- {
- if( id == -1 )
- id = registeredGlobalFuncs[n]->id;
- else
- return 0; // Multiple matches
- }
- }
- }
- if( id < 0 ) return 0; // No matches
- return registeredGlobalFuncs[id];
- }
- asCObjectType *asCScriptEngine::GetObjectType(const char *type)
- {
- // TODO: optimize: Improve linear search
- for( asUINT n = 0; n < objectTypes.GetLength(); n++ )
- if( objectTypes[n] &&
- objectTypes[n]->name == type ) // TODO: template: Should we check the subtype in case of template instances?
- return objectTypes[n];
- return 0;
- }
- void asCScriptEngine::PrepareEngine()
- {
- if( isPrepared ) return;
- if( configFailed ) return;
- asUINT n;
- for( n = 0; n < scriptFunctions.GetLength(); n++ )
- {
- // Determine the host application interface
- if( scriptFunctions[n] && scriptFunctions[n]->funcType == asFUNC_SYSTEM )
- {
- if( scriptFunctions[n]->sysFuncIntf->callConv == ICC_GENERIC_FUNC ||
- scriptFunctions[n]->sysFuncIntf->callConv == ICC_GENERIC_METHOD )
- PrepareSystemFunctionGeneric(scriptFunctions[n], scriptFunctions[n]->sysFuncIntf, this);
- else
- PrepareSystemFunction(scriptFunctions[n], scriptFunctions[n]->sysFuncIntf, this);
- }
- }
- // Validate object type registrations
- for( n = 0; n < objectTypes.GetLength(); n++ )
- {
- if( objectTypes[n] && !(objectTypes[n]->flags & asOBJ_SCRIPT_OBJECT) )
- {
- bool missingBehaviour = false;
- const char *infoMsg = 0;
- // Verify that GC types have all behaviours
- if( objectTypes[n]->flags & asOBJ_GC )
- {
- if( objectTypes[n]->beh.addref == 0 ||
- objectTypes[n]->beh.release == 0 ||
- objectTypes[n]->beh.gcGetRefCount == 0 ||
- objectTypes[n]->beh.gcSetFlag == 0 ||
- objectTypes[n]->beh.gcGetFlag == 0 ||
- objectTypes[n]->beh.gcEnumReferences == 0 ||
- objectTypes[n]->beh.gcReleaseAllReferences == 0 )
- {
- infoMsg = TXT_GC_REQUIRE_ADD_REL_GC_BEHAVIOUR;
- missingBehaviour = true;
- }
- }
- // Verify that scoped ref types have the release behaviour
- else if( objectTypes[n]->flags & asOBJ_SCOPED )
- {
- if( objectTypes[n]->beh.release == 0 )
- {
- infoMsg = TXT_SCOPE_REQUIRE_REL_BEHAVIOUR;
- missingBehaviour = true;
- }
- }
- // Verify that ref types have add ref and release behaviours
- else if( (objectTypes[n]->flags & asOBJ_REF) &&
- !(objectTypes[n]->flags & asOBJ_NOHANDLE) )
- {
- if( objectTypes[n]->beh.addref == 0 ||
- objectTypes[n]->beh.release == 0 )
- {
- infoMsg = TXT_REF_REQUIRE_ADD_REL_BEHAVIOUR;
- missingBehaviour = true;
- }
- }
- // Verify that non-pod value types have the constructor and destructor registered
- else if( (objectTypes[n]->flags & asOBJ_VALUE) &&
- !(objectTypes[n]->flags & asOBJ_POD) )
- {
- if( objectTypes[n]->beh.construct == 0 ||
- objectTypes[n]->beh.destruct == 0 )
- {
- infoMsg = TXT_NON_POD_REQUIRE_CONSTR_DESTR_BEHAVIOUR;
- missingBehaviour = true;
- }
- }
- if( missingBehaviour )
- {
- asCString str;
- str.Format(TXT_TYPE_s_IS_MISSING_BEHAVIOURS, objectTypes[n]->name.AddressOf());
- WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
- WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, infoMsg);
- ConfigError(asINVALID_CONFIGURATION);
- }
- }
- }
- isPrepared = true;
- }
- int asCScriptEngine::ConfigError(int err)
- {
- configFailed = true;
- return err;
- }
- // interface
- int asCScriptEngine::RegisterDefaultArrayType(const char *type)
- {
- asCBuilder bld(this, 0);
- asCDataType dt;
- int r = bld.ParseDataType(type, &dt);
- if( r < 0 ) return r;
- if( dt.GetObjectType() == 0 ||
- !(dt.GetObjectType()->GetFlags() & asOBJ_TEMPLATE) )
- return asINVALID_TYPE;
- defaultArrayObjectType = dt.GetObjectType();
- defaultArrayObjectType->AddRef();
- return 0;
- }
- // interface
- int asCScriptEngine::GetDefaultArrayTypeId() const
- {
- if( defaultArrayObjectType )
- return GetTypeIdFromDataType(asCDataType::CreateObject(defaultArrayObjectType, false));
- return asINVALID_TYPE;
- }
- // interface
- int asCScriptEngine::RegisterStringFactory(const char *datatype, const asSFuncPtr &funcPointer, asDWORD callConv)
- {
- asSSystemFunctionInterface internal;
- int r = DetectCallingConvention(false, funcPointer, callConv, &internal);
- if( r < 0 )
- return ConfigError(r);
- #ifdef AS_MAX_PORTABILITY
- if( callConv != asCALL_GENERIC )
- return ConfigError(asNOT_SUPPORTED);
- #else
- if( callConv != asCALL_CDECL &&
- callConv != asCALL_STDCALL &&
- callConv != asCALL_GENERIC )
- return ConfigError(asNOT_SUPPORTED);
- #endif
- // Put the system function in the list of system functions
- asSSystemFunctionInterface *newInterface = asNEW(asSSystemFunctionInterface)(internal);
- asCScriptFunction *func = asNEW(asCScriptFunction)(this, 0, asFUNC_SYSTEM);
- func->name = "_string_factory_";
- func->sysFuncIntf = newInterface;
- asCBuilder bld(this, 0);
- asCDataType dt;
- r = bld.ParseDataType(datatype, &dt);
- if( r < 0 )
- {
- // Set as dummy before deleting
- func->funcType = asFUNC_DUMMY;
- asDELETE(func,asCScriptFunction);
- return ConfigError(asINVALID_TYPE);
- }
- func->returnType = dt;
- func->parameterTypes.PushLast(asCDataType::CreatePrimitive(ttInt, true));
- asCDataType parm1 = asCDataType::CreatePrimitive(ttUInt8, true);
- parm1.MakeReference(true);
- func->parameterTypes.PushLast(parm1);
- func->id = GetNextScriptFunctionId();
- SetScriptFunction(func);
- stringFactory = func;
- if( func->returnType.GetObjectType() )
- {
- asCConfigGroup *group = FindConfigGroupForObjectType(func->returnType.GetObjectType());
- if( group == 0 ) group = &defaultGroup;
- group->scriptFunctions.PushLast(func);
- }
- // Register function id as success
- return func->id;
- }
- // interface
- int asCScriptEngine::GetStringFactoryReturnTypeId() const
- {
- if( stringFactory == 0 )
- return asNO_FUNCTION;
- return GetTypeIdFromDataType(stringFactory->returnType);
- }
- // interface
- asCModule *asCScriptEngine::GetModule(const char *_name, bool create)
- {
- // Accept null as well as zero-length string
- const char *name = "";
- if( _name != 0 ) name = _name;
- if( lastModule && lastModule->name == name )
- return lastModule;
- // TODO: optimize: Improve linear search
- for( asUINT n = 0; n < scriptModules.GetLength(); ++n )
- if( scriptModules[n] && scriptModules[n]->name == name )
- {
- lastModule = scriptModules[n];
- return lastModule;
- }
- if( create )
- {
- asCModule *module = asNEW(asCModule)(name, this);
- scriptModules.PushLast(module);
- lastModule = module;
- return lastModule;
- }
- return 0;
- }
- asCModule *asCScriptEngine::GetModuleFromFuncId(int id)
- {
- if( id < 0 ) return 0;
- if( id >= (int)scriptFunctions.GetLength() ) return 0;
- asCScriptFunction *func = scriptFunctions[id];
- if( func == 0 ) return 0;
- return func->module;
- }
- // internal
- int asCScriptEngine::RequestBuild()
- {
- ENTERCRITICALSECTION(engineCritical);
- if( isBuilding )
- {
- LEAVECRITICALSECTION(engineCritical);
- return asBUILD_IN_PROGRESS;
- }
- isBuilding = true;
- LEAVECRITICALSECTION(engineCritical);
- return 0;
- }
- // internal
- void asCScriptEngine::BuildCompleted()
- {
- // Always free up pooled memory after a completed build
- memoryMgr.FreeUnusedMemory();
- isBuilding = false;
- }
- void asCScriptEngine::RemoveTemplateInstanceType(asCObjectType *t)
- {
- int n;
- // Destroy the factory stubs
- for( n = 0; n < (int)t->beh.factories.GetLength(); n++ )
- {
- // Make sure the factory stub isn't referencing this object anymore
- scriptFunctions[t->beh.factories[n]]->ReleaseAllHandles(this);
- scriptFunctions[t->beh.factories[n]]->Release();
- }
- t->beh.factories.SetLength(0);
- // Destroy the stub for the list factory too
- if( t->beh.listFactory )
- {
- scriptFunctions[t->beh.listFactory]->ReleaseAllHandles(this);
- scriptFunctions[t->beh.listFactory]->Release();
- t->beh.listFactory = 0;
- }
- // Destroy the specialized functions
- for( n = 1; n < (int)t->beh.operators.GetLength(); n += 2 )
- {
- if( t->beh.operators[n] && scriptFunctions[t->beh.operators[n]]->objectType == t )
- {
- scriptFunctions[t->beh.operators[n]]->Release();
- }
- }
- t->beh.operators.SetLength(0);
- // Start searching from the end of the list, as most of
- // the time it will be the last two types
- for( n = (int)templateTypes.GetLength()-1; n >= 0; n-- )
- {
- if( templateTypes[n] == t )
- {
- if( n == (signed)templateTypes.GetLength()-1 )
- templateTypes.PopLast();
- else
- templateTypes[n] = templateTypes.PopLast();
- }
- }
- for( n = (int)templateInstanceTypes.GetLength()-1; n >= 0; n-- )
- {
- if( templateInstanceTypes[n] == t )
- {
- if( n == (signed)templateInstanceTypes.GetLength()-1 )
- templateInstanceTypes.PopLast();
- else
- templateInstanceTypes[n] = templateInstanceTypes.PopLast();
- }
- }
- asDELETE(t,asCObjectType);
- }
- // internal
- asCObjectType *asCScriptEngine::GetTemplateInstanceType(asCObjectType *templateType, asCDataType &subType)
- {
- asUINT n;
- // Is there any template instance type or template specialization already with this subtype?
- for( n = 0; n < templateTypes.GetLength(); n++ )
- {
- if( templateTypes[n] &&
- templateTypes[n]->name == templateType->name &&
- templateTypes[n]->templateSubType == subType )
- return templateTypes[n];
- }
- // No previous template instance exists
- // Make sure the template has factories as it doesn't have a default factory
- if( templateType->beh.factories.GetLength() == 0 )
- return 0;
- // Make sure this template supports the subtype
- if( !templateType->acceptValueSubType && (subType.IsPrimitive() || (subType.GetObjectType()->flags & asOBJ_VALUE)) )
- return 0;
- if( !templateType->acceptRefSubType && (subType.IsObject() && (subType.GetObjectType()->flags & asOBJ_REF)) )
- return 0;
- // Create a new template instance type based on the templateType
- asCObjectType *ot = asNEW(asCObjectType)(this);
- ot->templateSubType = subType;
- ot->flags = templateType->flags;
- ot->size = templateType->size;
- ot->name = templateType->name;
- // Before filling in the methods, call the template instance callback behaviour to validate the type
- if( templateType->beh.templateCallback )
- {
- asCScriptFunction *callback = scriptFunctions[templateType->beh.templateCallback];
- if( !CallGlobalFunctionRetBool(ot, 0, callback->sysFuncIntf, callback) )
- {
- // The type cannot be instanciated
- ot->templateSubType = asCDataType();
- asDELETE(ot, asCObjectType);
- return 0;
- }
- }
- ot->methods = templateType->methods;
- for( n = 0; n < ot->methods.GetLength(); n++ )
- scriptFunctions[ot->methods[n]]->AddRef();
- // Store the real factory in the constructor. This is used by the CreateScriptObject function.
- // Otherwise it wouldn't be necessary to store the real factory ids.
- ot->beh.construct = templateType->beh.factory;
- ot->beh.constructors = templateType->beh.factories;
- for( n = 0; n < ot->beh.constructors.GetLength(); n++ )
- scriptFunctions[ot->beh.constructors[n]]->AddRef();
- // Generate factory stubs for each of the factories
- for( n = 0; n < templateType->beh.factories.GetLength(); n++ )
- {
- asCScriptFunction *func = GenerateTemplateFactoryStub(templateType, ot, templateType->beh.factories[n]);
- // The function's refCount was already initialized to 1
- ot->beh.factories.PushLast(func->id);
- }
- if( ot->beh.factories.GetLength() )
- ot->beh.factory = ot->beh.factories[0];
- else
- {
- asASSERT(false);
- ot->beh.factory = templateType->beh.factory;
- }
- // Generate stub for the list factory as well
- if( templateType->beh.listFactory )
- {
- asCScriptFunction *func = GenerateTemplateFactoryStub(templateType, ot, templateType->beh.listFactory);
- // The function's refCount was already initialized to 1
- ot->beh.listFactory = func->id;
- }
- ot->beh.addref = templateType->beh.addref;
- if( scriptFunctions[ot->beh.addref] ) scriptFunctions[ot->beh.addref]->AddRef();
- ot->beh.release = templateType->beh.release;
- if( scriptFunctions[ot->beh.release] ) scriptFunctions[ot->beh.release]->AddRef();
- ot->beh.copy = templateType->beh.copy;
- if( scriptFunctions[ot->beh.copy] ) scriptFunctions[ot->beh.copy]->AddRef();
- ot->beh.operators = templateType->beh.operators;
- for( n = 1; n < ot->beh.operators.GetLength(); n += 2 )
- {
- scriptFunctions[ot->beh.operators[n]]->AddRef();
- }
- ot->beh.gcGetRefCount = templateType->beh.gcGetRefCount;
- if( scriptFunctions[ot->beh.gcGetRefCount] ) scriptFunctions[ot->beh.gcGetRefCount]->AddRef();
- ot->beh.gcSetFlag = templateType->beh.gcSetFlag;
- if( scriptFunctions[ot->beh.gcSetFlag] ) scriptFunctions[ot->beh.gcSetFlag]->AddRef();
- ot->beh.gcGetFlag = templateType->beh.gcGetFlag;
- if( scriptFunctions[ot->beh.gcGetFlag] ) scriptFunctions[ot->beh.gcGetFlag]->AddRef();
- ot->beh.gcEnumReferences = templateType->beh.gcEnumReferences;
- if( scriptFunctions[ot->beh.gcEnumReferences] ) scriptFunctions[ot->beh.gcEnumReferences]->AddRef();
- ot->beh.gcReleaseAllReferences = templateType->beh.gcReleaseAllReferences;
- if( scriptFunctions[ot->beh.gcReleaseAllReferences] ) scriptFunctions[ot->beh.gcReleaseAllReferences]->AddRef();
- // As the new template type is instanciated, the engine should
- // generate new functions to substitute the ones with the template subtype.
- for( n = 1; n < ot->beh.operators.GetLength(); n += 2 )
- {
- int funcId = ot->beh.operators[n];
- asCScriptFunction *func = scriptFunctions[funcId];
- if( GenerateNewTemplateFunction(templateType, ot, subType, func, &func) )
- {
- // Release the old function, the new one already has its ref count set to 1
- scriptFunctions[ot->beh.operators[n]]->Release();
- ot->beh.operators[n] = func->id;
- }
- }
- // As the new template type is instanciated, the engine should
- // generate new functions to substitute the ones with the template subtype.
- for( n = 0; n < ot->methods.GetLength(); n++ )
- {
- int funcId = ot->methods[n];
- asCScriptFunction *func = scriptFunctions[funcId];
- if( GenerateNewTemplateFunction(templateType, ot, subType, func, &func) )
- {
- // Release the old function, the new one already has its ref count set to 1
- scriptFunctions[ot->methods[n]]->Release();
- ot->methods[n] = func->id;
- }
- }
- // Increase ref counter for sub type if it is an object type
- if( ot->templateSubType.GetObjectType() ) ot->templateSubType.GetObjectType()->AddRef();
- // Verify if the subtype contains a garbage collected object, in which case this template is a potential circular reference.
- // A handle can potentially hold derived types, which may be garbage collected so to be safe we have to set the GC flag.
- if( ot->templateSubType.IsObjectHandle() || (ot->templateSubType.GetObjectType() && (ot->templateSubType.GetObjectType()->flags & asOBJ_GC)) )
- ot->flags |= asOBJ_GC;
- templateTypes.PushLast(ot);
- // We need to store the object type somewhere for clean-up later
- // TODO: Why do we need both templateTypes and templateInstanceTypes? It is possible to differ between template instance and template specialization by checking for the asOBJ_TEMPLATE flag
- templateInstanceTypes.PushLast(ot);
- return ot;
- }
- // internal
- asCScriptFunction *asCScriptEngine::GenerateTemplateFactoryStub(asCObjectType *templateType, asCObjectType *ot, int factoryId)
- {
- asCScriptFunction *factory = scriptFunctions[factoryId];
- asCScriptFunction *func = asNEW(asCScriptFunction)(this, 0, asFUNC_SCRIPT);
- func->name = "factstub";
- func->id = GetNextScriptFunctionId();
- func->returnType = asCDataType::CreateObjectHandle(ot, false);
- // Skip the first parameter as this is the object type pointer that the stub will add
- func->parameterTypes.SetLength(factory->parameterTypes.GetLength()-1);
- func->inOutFlags.SetLength(factory->inOutFlags.GetLength()-1);
- for( asUINT p = 1; p < factory->parameterTypes.GetLength(); p++ )
- {
- if( factory->parameterTypes[p].GetObjectType() == templateType->templateSubType.GetObjectType() )
- {
- func->parameterTypes[p-1] = ot->templateSubType;
- if( factory->parameterTypes[p].IsObjectHandle() )
- func->parameterTypes[p-1].MakeHandle(true);
- func->parameterTypes[p-1].MakeReference(factory->parameterTypes[p].IsReference());
- func->parameterTypes[p-1].MakeReadOnly(factory->parameterTypes[p].IsReference());
- }
- else if( factory->parameterTypes[p].GetObjectType() == templateType )
- {
- if( factory->parameterTypes[p].IsObjectHandle() )
- func->parameterTypes[p-1] = asCDataType::CreateObjectHandle(ot, false);
- else
- func->parameterTypes[p-1] = asCDataType::CreateObject(ot, false);
- func->parameterTypes[p-1].MakeReference(factory->parameterTypes[p].IsReference());
- func->parameterTypes[p-1].MakeReadOnly(factory->parameterTypes[p].IsReadOnly());
- }
- else
- {
- func->parameterTypes[p-1] = factory->parameterTypes[p];
- }
- func->inOutFlags[p-1] = factory->inOutFlags[p];
- }
- SetScriptFunction(func);
- asCBuilder builder(this, 0);
- asCCompiler compiler(this);
- compiler.CompileTemplateFactoryStub(&builder, factoryId, ot, func);
- return func;
- }
- bool asCScriptEngine::GenerateNewTemplateFunction(asCObjectType *templateType, asCObjectType *ot, asCDataType &subType, asCScriptFunction *func, asCScriptFunction **newFunc)
- {
- bool needNewFunc = false;
- if( func->returnType.GetObjectType() == templateType->templateSubType.GetObjectType() ||
- func->returnType.GetObjectType() == templateType )
- needNewFunc = true;
- else
- {
- for( asUINT p = 0; p < func->parameterTypes.GetLength(); p++ )
- {
- if( func->parameterTypes[p].GetObjectType() == templateType->templateSubType.GetObjectType() ||
- func->parameterTypes[p].GetObjectType() == templateType )
- {
- needNewFunc = true;
- break;
- }
- }
- }
- if( needNewFunc )
- {
- asCScriptFunction *func2 = asNEW(asCScriptFunction)(this, 0, func->funcType);
- func2->name = func->name;
- func2->id = GetNextScriptFunctionId();
- if( func->returnType.GetObjectType() == templateType->templateSubType.GetObjectType() )
- {
- func2->returnType = subType;
- if( func->returnType.IsObjectHandle() )
- func2->returnType.MakeHandle(true, true);
- func2->returnType.MakeReference(func->returnType.IsReference());
- func2->returnType.MakeReadOnly(func->returnType.IsReadOnly());
- }
- else if( func->returnType.GetObjectType() == templateType )
- {
- if( func2->returnType.IsObjectHandle() )
- func2->returnType = asCDataType::CreateObjectHandle(ot, false);
- else
- func2->returnType = asCDataType::CreateObject(ot, false);
- func2->returnType.MakeReference(func->returnType.IsReference());
- func2->returnType.MakeReadOnly(func->returnType.IsReadOnly());
- }
- else
- func2->returnType = func->returnType;
- func2->parameterTypes.SetLength(func->parameterTypes.GetLength());
- for( asUINT p = 0; p < func->parameterTypes.GetLength(); p++ )
- {
- if( func->parameterTypes[p].GetObjectType() == templateType->templateSubType.GetObjectType() )
- {
- func2->parameterTypes[p] = subType;
- if( func->parameterTypes[p].IsObjectHandle() )
- func2->parameterTypes[p].MakeHandle(true);
- func2->parameterTypes[p].MakeReference(func->parameterTypes[p].IsReference());
- func2->parameterTypes[p].MakeReadOnly(func->parameterTypes[p].IsReference());
- }
- else if( func->parameterTypes[p].GetObjectType() == templateType )
- {
- if( func->parameterTypes[p].IsObjectHandle() )
- func2->parameterTypes[p] = asCDataType::CreateObjectHandle(ot, false);
- else
- func2->parameterTypes[p] = asCDataType::CreateObject(ot, false);
- func2->parameterTypes[p].MakeReference(func->parameterTypes[p].IsReference());
- func2->parameterTypes[p].MakeReadOnly(func->parameterTypes[p].IsReadOnly());
- }
- else
- func2->parameterTypes[p] = func->parameterTypes[p];
- }
- // TODO: template: Must be careful when instanciating templates for garbage collected types
- // If the template hasn't been registered with the behaviours, it shouldn't
- // permit instanciation of garbage collected types that in turn may refer to
- // this instance.
- func2->inOutFlags = func->inOutFlags;
- func2->isReadOnly = func->isReadOnly;
- func2->objectType = ot;
- func2->stackNeeded = func->stackNeeded;
- func2->sysFuncIntf = asNEW(asSSystemFunctionInterface)(*func->sysFuncIntf);
- SetScriptFunction(func2);
- // Return the new function
- *newFunc = func2;
- }
- return needNewFunc;
- }
- void asCScriptEngine::CallObjectMethod(void *obj, int func)
- {
- asCScriptFunction *s = scriptFunctions[func];
- asASSERT( s != 0 );
- CallObjectMethod(obj, s->sysFuncIntf, s);
- }
- void asCScriptEngine::CallObjectMethod(void *obj, asSSystemFunctionInterface *i, asCScriptFunction *s)
- {
- #ifdef __GNUC__
- if( i->callConv == ICC_GENERIC_METHOD )
- {
- asCGeneric gen(this, s, obj, 0);
- void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
- f(&gen);
- }
- else if( i->callConv == ICC_VIRTUAL_THISCALL )
- {
- // 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
- union
- {
- asSIMPLEMETHOD_t mthd;
- struct
- {
- asFUNCTION_t func;
- asPWORD baseOffset; // Same size as the pointer
- } f;
- } p;
- p.f.func = (void (*)())(i->func);
- p.f.baseOffset = asPWORD(i->baseOffset);
- void (asCSimpleDummy::*f)() = p.mthd;
- (((asCSimpleDummy*)obj)->*f)();
- }
- else /*if( i->callConv == ICC_THISCALL || i->callConv == ICC_CDECL_OBJLAST || i->callConv == ICC_CDECL_OBJFIRST )*/
- {
- // Non-virtual thiscall can be called just like any global function, passing the object as the first parameter
- void (*f)(void *) = (void (*)(void *))(i->func);
- f(obj);
- }
- #else
- #ifndef AS_NO_CLASS_METHODS
- if( i->callConv == ICC_THISCALL )
- {
- union
- {
- asSIMPLEMETHOD_t mthd;
- asFUNCTION_t func;
- } p;
- p.func = (void (*)())(i->func);
- void (asCSimpleDummy::*f)() = p.mthd;
- obj = (void*)(size_t(obj) + i->baseOffset);
- (((asCSimpleDummy*)obj)->*f)();
- }
- else
- #endif
- if( i->callConv == ICC_GENERIC_METHOD )
- {
- asCGeneric gen(this, s, obj, 0);
- void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
- f(&gen);
- }
- else /*if( i->callConv == ICC_CDECL_OBJLAST || i->callConv == ICC_CDECL_OBJFIRST )*/
- {
- void (*f)(void *) = (void (*)(void *))(i->func);
- f(obj);
- }
- #endif
- }
- bool asCScriptEngine::CallObjectMethodRetBool(void *obj, int func)
- {
- asCScriptFunction *s = scriptFunctions[func];
- asASSERT( s != 0 );
- asSSystemFunctionInterface *i = s->sysFuncIntf;
- #ifdef __GNUC__
- if( i->callConv == ICC_GENERIC_METHOD )
- {
- asCGeneric gen(this, s, obj, 0);
- void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
- f(&gen);
- return *(bool*)gen.GetReturnPointer();
- }
- else if( i->callConv == ICC_VIRTUAL_THISCALL )
- {
- // 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
- union
- {
- asSIMPLEMETHOD_t mthd;
- struct
- {
- asFUNCTION_t func;
- asDWORD baseOffset;
- } f;
- } p;
- p.f.func = (void (*)())(i->func);
- p.f.baseOffset = i->baseOffset;
- bool (asCSimpleDummy::*f)() = (bool (asCSimpleDummy::*)())(p.mthd);
- return (((asCSimpleDummy*)obj)->*f)();
- }
- else /*if( i->callConv == ICC_THISCALL || i->callConv == ICC_CDECL_OBJLAST || i->callConv == ICC_CDECL_OBJFIRST )*/
- {
- // Non-virtual thiscall can be called just like any global function, passing the object as the first parameter
- bool (*f)(void *) = (bool (*)(void *))(i->func);
- return f(obj);
- }
- #else
- #ifndef AS_NO_CLASS_METHODS
- if( i->callConv == ICC_THISCALL )
- {
- union
- {
- asSIMPLEMETHOD_t mthd;
- asFUNCTION_t func;
- } p;
- p.func = (void (*)())(i->func);
- bool (asCSimpleDummy::*f)() = (bool (asCSimpleDummy::*)())p.mthd;
- obj = (void*)(size_t(obj) + i->baseOffset);
- return (((asCSimpleDummy*)obj)->*f)();
- }
- else
- #endif
- if( i->callConv == ICC_GENERIC_METHOD )
- {
- asCGeneric gen(this, s, obj, 0);
- void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
- f(&gen);
- return *(bool*)gen.GetReturnPointer();
- }
- else /*if( i->callConv == ICC_CDECL_OBJLAST || i->callConv == ICC_CDECL_OBJFIRST )*/
- {
- bool (*f)(void *) = (bool (*)(void *))(i->func);
- return f(obj);
- }
- #endif
- }
- int asCScriptEngine::CallObjectMethodRetInt(void *obj, int func)
- {
- asCScriptFunction *s = scriptFunctions[func];
- asASSERT( s != 0 );
- asSSystemFunctionInterface *i = s->sysFuncIntf;
- #ifdef __GNUC__
- if( i->callConv == ICC_GENERIC_METHOD )
- {
- asCGeneric gen(this, s, obj, 0);
- void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
- f(&gen);
- return *(int*)gen.GetReturnPointer();
- }
- else if( i->callConv == ICC_VIRTUAL_THISCALL )
- {
- // 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
- union
- {
- asSIMPLEMETHOD_t mthd;
- struct
- {
- asFUNCTION_t func;
- asDWORD baseOffset;
- } f;
- } p;
- p.f.func = (void (*)())(i->func);
- p.f.baseOffset = i->baseOffset;
- int (asCSimpleDummy::*f)() = (int (asCSimpleDummy::*)())(p.mthd);
- return (((asCSimpleDummy*)obj)->*f)();
- }
- else /*if( i->callConv == ICC_THISCALL || i->callConv == ICC_CDECL_OBJLAST || i->callConv == ICC_CDECL_OBJFIRST )*/
- {
- // Non-virtual thiscall can be called just like any global function, passing the object as the first parameter
- int (*f)(void *) = (int (*)(void *))(i->func);
- return f(obj);
- }
- #else
- #ifndef AS_NO_CLASS_METHODS
- if( i->callConv == ICC_THISCALL )
- {
- union
- {
- asSIMPLEMETHOD_t mthd;
- asFUNCTION_t func;
- } p;
- p.func = (void (*)())(i->func);
- int (asCSimpleDummy::*f)() = (int (asCSimpleDummy::*)())p.mthd;
- obj = (void*)(size_t(obj) + i->baseOffset);
- return (((asCSimpleDummy*)obj)->*f)();
- }
- else
- #endif
- if( i->callConv == ICC_GENERIC_METHOD )
- {
- asCGeneric gen(this, s, obj, 0);
- void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
- f(&gen);
- return *(int*)gen.GetReturnPointer();
- }
- else /*if( i->callConv == ICC_CDECL_OBJLAST || i->callConv == ICC_CDECL_OBJFIRST )*/
- {
- int (*f)(void *) = (int (*)(void *))(i->func);
- return f(obj);
- }
- #endif
- }
- void *asCScriptEngine::CallGlobalFunctionRetPtr(int func)
- {
- asCScriptFunction *s = scriptFunctions[func];
- asASSERT( s != 0 );
- return CallGlobalFunctionRetPtr(s->sysFuncIntf, s);
- }
- void *asCScriptEngine::CallGlobalFunctionRetPtr(int func, void *param1)
- {
- asCScriptFunction *s = scriptFunctions[func];
- asASSERT( s != 0 );
- return CallGlobalFunctionRetPtr(s->sysFuncIntf, s, param1);
- }
- void *asCScriptEngine::CallGlobalFunctionRetPtr(asSSystemFunctionInterface *i, asCScriptFunction *s)
- {
- if( i->callConv == ICC_CDECL )
- {
- void *(*f)() = (void *(*)())(i->func);
- return f();
- }
- else if( i->callConv == ICC_STDCALL )
- {
- void *(STDCALL *f)() = (void *(STDCALL *)())(i->func);
- return f();
- }
- else
- {
- asCGeneric gen(this, s, 0, 0);
- void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
- f(&gen);
- return *(void**)gen.GetReturnPointer();
- }
- }
- void *asCScriptEngine::CallGlobalFunctionRetPtr(asSSystemFunctionInterface *i, asCScriptFunction *s, void *param1)
- {
- if( i->callConv == ICC_CDECL )
- {
- void *(*f)(void *) = (void *(*)(void *))(i->func);
- return f(param1);
- }
- else if( i->callConv == ICC_STDCALL )
- {
- void *(STDCALL *f)(void *) = (void *(STDCALL *)(void *))(i->func);
- return f(param1);
- }
- else
- {
- asCGeneric gen(this, s, 0, (asDWORD*)¶m1);
- void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
- f(&gen);
- return *(void**)gen.GetReturnPointer();
- }
- }
- void asCScriptEngine::CallObjectMethod(void *obj, void *param, int func)
- {
- asCScriptFunction *s = scriptFunctions[func];
- asASSERT( s != 0 );
- CallObjectMethod(obj, param, s->sysFuncIntf, s);
- }
- void asCScriptEngine::CallObjectMethod(void *obj, void *param, asSSystemFunctionInterface *i, asCScriptFunction *s)
- {
- #ifdef __GNUC__
- if( i->callConv == ICC_CDECL_OBJLAST )
- {
- void (*f)(void *, void *) = (void (*)(void *, void *))(i->func);
- f(param, obj);
- }
- else if( i->callConv == ICC_GENERIC_METHOD )
- {
- asCGeneric gen(this, s, obj, (asDWORD*)¶m);
- void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
- f(&gen);
- }
- else /*if( i->callConv == ICC_CDECL_OBJFIRST || i->callConv == ICC_THISCALL )*/
- {
- void (*f)(void *, void *) = (void (*)(void *, void *))(i->func);
- f(obj, param);
- }
- #else
- #ifndef AS_NO_CLASS_METHODS
- if( i->callConv == ICC_THISCALL )
- {
- union
- {
- asSIMPLEMETHOD_t mthd;
- asFUNCTION_t func;
- } p;
- p.func = (void (*)())(i->func);
- void (asCSimpleDummy::*f)(void *) = (void (asCSimpleDummy::*)(void *))(p.mthd);
- obj = (void*)(size_t(obj) + i->baseOffset);
- (((asCSimpleDummy*)obj)->*f)(param);
- }
- else
- #endif
- if( i->callConv == ICC_CDECL_OBJLAST )
- {
- void (*f)(void *, void *) = (void (*)(void *, void *))(i->func);
- f(param, obj);
- }
- else if( i->callConv == ICC_GENERIC_METHOD )
- {
- asCGeneric gen(this, s, obj, (asDWORD*)¶m);
- void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
- f(&gen);
- }
- else /*if( i->callConv == ICC_CDECL_OBJFIRST )*/
- {
- void (*f)(void *, void *) = (void (*)(void *, void *))(i->func);
- f(obj, param);
- }
- #endif
- }
- void asCScriptEngine::CallGlobalFunction(void *param1, void *param2, asSSystemFunctionInterface *i, asCScriptFunction *s)
- {
- if( i->callConv == ICC_CDECL )
- {
- void (*f)(void *, void *) = (void (*)(void *, void *))(i->func);
- f(param1, param2);
- }
- else if( i->callConv == ICC_STDCALL )
- {
- void (STDCALL *f)(void *, void *) = (void (STDCALL *)(void *, void *))(i->func);
- f(param1, param2);
- }
- else
- {
- asCGeneric gen(this, s, 0, (asDWORD*)¶m1);
- void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
- f(&gen);
- }
- }
- bool asCScriptEngine::CallGlobalFunctionRetBool(void *param1, void *param2, asSSystemFunctionInterface *i, asCScriptFunction *s)
- {
- if( i->callConv == ICC_CDECL )
- {
- bool (*f)(void *, void *) = (bool (*)(void *, void *))(i->func);
- return f(param1, param2);
- }
- else if( i->callConv == ICC_STDCALL )
- {
- bool (STDCALL *f)(void *, void *) = (bool (STDCALL *)(void *, void *))(i->func);
- return f(param1, param2);
- }
- else
- {
- // TODO: When simulating a 64bit environment by defining AS_64BIT_PTR on a 32bit platform this code
- // fails, because the stack given to asCGeneric is not prepared with two 64bit arguments.
- asCGeneric gen(this, s, 0, (asDWORD*)¶m1);
- void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
- f(&gen);
- return *(bool*)gen.GetReturnPointer();
- }
- }
- void *asCScriptEngine::CallAlloc(asCObjectType *type) const
- {
- // Allocate 4 bytes as the smallest size. Otherwise CallSystemFunction may try to
- // copy a DWORD onto a smaller memory block, in case the object type is return in registers.
- #if defined(AS_DEBUG)
- return ((asALLOCFUNCDEBUG_t)(userAlloc))(type->size < 4 ? 4 : type->size, __FILE__, __LINE__);
- #else
- return userAlloc(type->size < 4 ? 4 : type->size);
- #endif
- }
- void asCScriptEngine::CallFree(void *obj) const
- {
- userFree(obj);
- }
- // interface
- void asCScriptEngine::NotifyGarbageCollectorOfNewObject(void *obj, int typeId)
- {
- asCObjectType *objType = GetObjectTypeFromTypeId(typeId);
- gc.AddScriptObjectToGC(obj, objType);
- }
- // interface
- int asCScriptEngine::GarbageCollect(asDWORD flags)
- {
- return gc.GarbageCollect(flags);
- }
- // interface
- void asCScriptEngine::GetGCStatistics(asUINT *currentSize, asUINT *totalDestroyed, asUINT *totalDetected, asUINT *newObjects, asUINT *totalNewDestroyed) const
- {
- gc.GetStatistics(currentSize, totalDestroyed, totalDetected, newObjects, totalNewDestroyed);
- }
- // interface
- void asCScriptEngine::GCEnumCallback(void *reference)
- {
- gc.GCEnumCallback(reference);
- }
- // TODO: multithread: The mapTypeIdToDataType must be protected with critical sections in all functions that access it
- // Urho3D: modified for id caching
- int asCScriptEngine::GetTypeIdFromDataType(const asCDataType &dt) const
- {
- if( dt.IsNullHandle() ) return 0;
- // ASHANDLE is mimicking a handle, but it really is a value
- // type so only the non-handle form should be registered.
- if( dt.GetObjectType() && dt.GetObjectType()->flags & asOBJ_ASHANDLE && dt.IsObjectHandle() )
- {
- asCDataType dtNoHandle(dt);
- dtNoHandle.MakeHandle(false);
- return GetTypeIdFromDataType(dtNoHandle);
- }
- // Urho3D: check first for cached id in the type itself
- int typeId = dt.GetCachedTypeId();
- if( typeId ) return typeId;
-
- // Find the existing type id
- asSMapNode<int,asCDataType*> *cursor = 0;
- mapTypeIdToDataType.MoveFirst(&cursor);
- while( cursor )
- {
- if( mapTypeIdToDataType.GetValue(cursor)->IsEqualExceptRefAndConst(dt) )
- {
- typeId = mapTypeIdToDataType.GetKey(cursor);
- dt.SetCachedTypeId(typeId);
- return typeId;
- }
- mapTypeIdToDataType.MoveNext(&cursor, cursor);
- }
- // The type id doesn't exist, create it
- // Setup the basic type id
- typeId = typeIdSeqNbr++;
- if( dt.GetObjectType() )
- {
- if( dt.GetObjectType()->flags & asOBJ_SCRIPT_OBJECT ) typeId |= asTYPEID_SCRIPTOBJECT;
- else if( dt.GetObjectType()->flags & asOBJ_TEMPLATE ) typeId |= asTYPEID_TEMPLATE;
- else if( dt.GetObjectType()->flags & asOBJ_ENUM ); // TODO: Should we have a specific bit for this?
- else typeId |= asTYPEID_APPOBJECT;
- }
- // Insert the basic object type
- asCDataType *newDt = asNEW(asCDataType)(dt);
- newDt->MakeReference(false);
- newDt->MakeReadOnly(false);
- newDt->MakeHandle(false);
- mapTypeIdToDataType.Insert(typeId, newDt);
- // If the object type supports object handles then register those types as well
- // Note: Don't check for addref, as asOBJ_SCOPED don't have this
- if( dt.IsObject() && dt.GetObjectType()->beh.release )
- {
- newDt = asNEW(asCDataType)(dt);
- newDt->MakeReference(false);
- newDt->MakeReadOnly(false);
- newDt->MakeHandle(true);
- newDt->MakeHandleToConst(false);
- mapTypeIdToDataType.Insert(typeId | asTYPEID_OBJHANDLE, newDt);
- newDt = asNEW(asCDataType)(dt);
- newDt->MakeReference(false);
- newDt->MakeReadOnly(false);
- newDt->MakeHandle(true);
- newDt->MakeHandleToConst(true);
- mapTypeIdToDataType.Insert(typeId | asTYPEID_OBJHANDLE | asTYPEID_HANDLETOCONST, newDt);
- }
- // Call the method recursively to get the correct type id
- return GetTypeIdFromDataType(dt);
- }
- const asCDataType *asCScriptEngine::GetDataTypeFromTypeId(int typeId) const
- {
- asSMapNode<int,asCDataType*> *cursor = 0;
- if( mapTypeIdToDataType.MoveTo(&cursor, typeId) )
- return mapTypeIdToDataType.GetValue(cursor);
- return 0;
- }
- asCObjectType *asCScriptEngine::GetObjectTypeFromTypeId(int typeId) const
- {
- asSMapNode<int,asCDataType*> *cursor = 0;
- if( mapTypeIdToDataType.MoveTo(&cursor, typeId) )
- return mapTypeIdToDataType.GetValue(cursor)->GetObjectType();
- return 0;
- }
- void asCScriptEngine::RemoveFromTypeIdMap(asCObjectType *type)
- {
- asSMapNode<int,asCDataType*> *cursor = 0;
- mapTypeIdToDataType.MoveFirst(&cursor);
- while( cursor )
- {
- asCDataType *dt = mapTypeIdToDataType.GetValue(cursor);
- asSMapNode<int,asCDataType*> *old = cursor;
- mapTypeIdToDataType.MoveNext(&cursor, cursor);
- if( dt->GetObjectType() == type )
- {
- asDELETE(dt,asCDataType);
- mapTypeIdToDataType.Erase(old);
- }
- }
- }
- // interface
- int asCScriptEngine::GetTypeIdByDecl(const char *decl) const
- {
- asCDataType dt;
- // This cast is ok, because we are not changing anything in the engine
- asCBuilder bld(const_cast<asCScriptEngine*>(this), 0);
- int r = bld.ParseDataType(decl, &dt);
- if( r < 0 )
- return asINVALID_TYPE;
- return GetTypeIdFromDataType(dt);
- }
- // interface
- const char *asCScriptEngine::GetTypeDeclaration(int typeId) const
- {
- const asCDataType *dt = GetDataTypeFromTypeId(typeId);
- if( dt == 0 ) return 0;
- asASSERT(threadManager);
- asCString *tempString = &threadManager->GetLocalData()->string;
- *tempString = dt->Format();
- return tempString->AddressOf();
- }
- // TODO: interface: Deprecate. This function is not necessary now that all primitive types have fixed typeIds
- int asCScriptEngine::GetSizeOfPrimitiveType(int typeId) const
- {
- const asCDataType *dt = GetDataTypeFromTypeId(typeId);
- if( dt == 0 ) return 0;
- if( !dt->IsPrimitive() ) return 0;
- return dt->GetSizeInMemoryBytes();
- }
- // TODO: interface: Should deprecate this. The application should be calling the factory directly
- void *asCScriptEngine::CreateScriptObject(int typeId)
- {
- // Make sure the type id is for an object type, and not a primitive or a handle
- if( (typeId & (asTYPEID_MASK_OBJECT | asTYPEID_MASK_SEQNBR)) != typeId ) return 0;
- if( (typeId & asTYPEID_MASK_OBJECT) == 0 ) return 0;
- const asCDataType *dt = GetDataTypeFromTypeId(typeId);
- // Is the type id valid?
- if( !dt ) return 0;
- // Allocate the memory
- asCObjectType *objType = dt->GetObjectType();
- void *ptr = 0;
- // Construct the object
- if( objType->flags & asOBJ_SCRIPT_OBJECT )
- ptr = ScriptObjectFactory(objType, this);
- else if( objType->flags & asOBJ_TEMPLATE )
- // The registered factory is moved to the construct behaviour when the type is instanciated
- ptr = CallGlobalFunctionRetPtr(objType->beh.construct, objType);
- else if( objType->flags & asOBJ_REF )
- ptr = CallGlobalFunctionRetPtr(objType->beh.factory);
- else
- {
- ptr = CallAlloc(objType);
- int funcIndex = objType->beh.construct;
- if( funcIndex )
- CallObjectMethod(ptr, funcIndex);
- }
- return ptr;
- }
- // TODO: interface: Should deprecate this. The application should be calling the factory directly
- void *asCScriptEngine::CreateScriptObjectCopy(void *origObj, int typeId)
- {
- void *newObj = CreateScriptObject(typeId);
- if( newObj == 0 ) return 0;
- CopyScriptObject(newObj, origObj, typeId);
- return newObj;
- }
- // internal
- void asCScriptEngine::ConstructScriptObjectCopy(void *mem, void *obj, asCObjectType *type)
- {
- // This function is only meant to be used for value types
- asASSERT( type->flags & asOBJ_VALUE );
- // TODO: Should use the copy constructor when available
- int funcIndex = type->beh.construct;
- if( funcIndex )
- CallObjectMethod(mem, funcIndex);
- CopyScriptObject(mem, obj, type->GetTypeId());
- }
- // TODO: interface: Should deprecate this. The application should be calling the opAssign method directly
- void asCScriptEngine::CopyScriptObject(void *dstObj, void *srcObj, int typeId)
- {
- // TODO: optimize: Use the copy constructor when available
- // Make sure the type id is for an object type, and not a primitive or a handle
- if( (typeId & (asTYPEID_MASK_OBJECT | asTYPEID_MASK_SEQNBR)) != typeId ) return;
- if( (typeId & asTYPEID_MASK_OBJECT) == 0 ) return;
- // Copy the contents from the original object, using the assignment operator
- const asCDataType *dt = GetDataTypeFromTypeId(typeId);
- // Is the type id valid?
- if( !dt ) return;
- asCObjectType *objType = dt->GetObjectType();
- // TODO: beh.copy will be removed, so we need to find the default opAssign method instead
- // TODO: Must not copy if the opAssign is not available and the object is not a POD object
- if( objType->beh.copy )
- {
- CallObjectMethod(dstObj, srcObj, objType->beh.copy);
- }
- else if( objType->size )
- {
- memcpy(dstObj, srcObj, objType->size);
- }
- }
- // interface
- void asCScriptEngine::AddRefScriptObject(void *obj, int typeId)
- {
- // Make sure it is not a null pointer
- if( obj == 0 ) return;
- // Make sure the type id is for an object type or a handle
- if( (typeId & asTYPEID_MASK_OBJECT) == 0 ) return;
- const asCDataType *dt = GetDataTypeFromTypeId(typeId);
- // Is the type id valid?
- if( !dt ) return;
- asCObjectType *objType = dt->GetObjectType();
- if( objType->beh.addref )
- {
- // Call the addref behaviour
- CallObjectMethod(obj, objType->beh.addref);
- }
- }
- // interface
- void asCScriptEngine::AddRefScriptObject(void *obj, const asIObjectType *type)
- {
- // Make sure it is not a null pointer
- if( obj == 0 ) return;
- const asCObjectType *objType = static_cast<const asCObjectType *>(type);
- if( objType->beh.addref )
- {
- // Call the addref behaviour
- CallObjectMethod(obj, objType->beh.addref);
- }
- }
- // interface
- void asCScriptEngine::ReleaseScriptObject(void *obj, int typeId)
- {
- // Make sure it is not a null pointer
- if( obj == 0 ) return;
- // Make sure the type id is for an object type or a handle
- if( (typeId & asTYPEID_MASK_OBJECT) == 0 ) return;
- const asCDataType *dt = GetDataTypeFromTypeId(typeId);
- // Is the type id valid?
- if( !dt ) return;
- asCObjectType *objType = dt->GetObjectType();
- if( objType->beh.release )
- {
- // Call the release behaviour
- CallObjectMethod(obj, objType->beh.release);
- }
- // TODO: interface: shouldn't work on non reference types
- else
- {
- // Call the destructor
- if( objType->beh.destruct )
- CallObjectMethod(obj, objType->beh.destruct);
- // Then free the memory
- CallFree(obj);
- }
- }
- // interface
- void asCScriptEngine::ReleaseScriptObject(void *obj, const asIObjectType *type)
- {
- // Make sure it is not a null pointer
- if( obj == 0 ) return;
-
- const asCObjectType *objType = static_cast<const asCObjectType *>(type);
- if( objType->beh.release )
- {
- // Call the release behaviour
- CallObjectMethod(obj, objType->beh.release);
- }
- // TODO: interface: shouldn't work on non reference types
- else
- {
- // Call the destructor
- if( objType->beh.destruct )
- CallObjectMethod(obj, objType->beh.destruct);
- // Then free the memory
- CallFree(obj);
- }
- }
- bool asCScriptEngine::IsHandleCompatibleWithObject(void *obj, int objTypeId, int handleTypeId) const
- {
- // if equal, then it is obvious they are compatible
- if( objTypeId == handleTypeId )
- return true;
- // Get the actual data types from the type ids
- const asCDataType *objDt = GetDataTypeFromTypeId(objTypeId);
- const asCDataType *hdlDt = GetDataTypeFromTypeId(handleTypeId);
- // A handle to const cannot be passed to a handle that is not referencing a const object
- if( objDt->IsHandleToConst() && !hdlDt->IsHandleToConst() )
- return false;
- if( objDt->GetObjectType() == hdlDt->GetObjectType() )
- {
- // The object type is equal
- return true;
- }
- else if( objDt->IsScriptObject() && obj )
- {
- // There's still a chance the object implements the requested interface
- asCObjectType *objType = ((asCScriptObject*)obj)->objType;
- if( objType->Implements(hdlDt->GetObjectType()) )
- return true;
- }
- return false;
- }
- int asCScriptEngine::BeginConfigGroup(const char *groupName)
- {
- // Make sure the group name doesn't already exist
- for( asUINT n = 0; n < configGroups.GetLength(); n++ )
- {
- if( configGroups[n]->groupName == groupName )
- return asNAME_TAKEN;
- }
- if( currentGroup != &defaultGroup )
- return asNOT_SUPPORTED;
- asCConfigGroup *group = asNEW(asCConfigGroup)();
- group->groupName = groupName;
- configGroups.PushLast(group);
- currentGroup = group;
- return 0;
- }
- int asCScriptEngine::EndConfigGroup()
- {
- // Raise error if trying to end the default config
- if( currentGroup == &defaultGroup )
- return asERROR;
- currentGroup = &defaultGroup;
- return 0;
- }
- int asCScriptEngine::RemoveConfigGroup(const char *groupName)
- {
- // It is not allowed to remove a group that is still in use.
- // It would be possible to change the code in such a way that
- // the group could be removed even though it was still in use,
- // but that would cause severe negative impact on runtime
- // performance, since the VM would then have to be able handle
- // situations where the types, functions, and global variables
- // can be removed at any time.
- for( asUINT n = 0; n < configGroups.GetLength(); n++ )
- {
- if( configGroups[n]->groupName == groupName )
- {
- asCConfigGroup *group = configGroups[n];
- // Make sure the group isn't referenced by anyone
- if( group->refCount > 0 )
- return asCONFIG_GROUP_IS_IN_USE;
- // Verify if any objects registered in this group is still alive
- if( group->HasLiveObjects() )
- return asCONFIG_GROUP_IS_IN_USE;
- // Remove the group from the list
- if( n == configGroups.GetLength() - 1 )
- configGroups.PopLast();
- else
- configGroups[n] = configGroups.PopLast();
- // Remove the configurations registered with this group
- group->RemoveConfiguration(this);
- asDELETE(group,asCConfigGroup);
- }
- }
- return 0;
- }
- asCConfigGroup *asCScriptEngine::FindConfigGroupForFunction(int funcId) const
- {
- for( asUINT n = 0; n < configGroups.GetLength(); n++ )
- {
- // Check global functions
- asUINT m;
- for( m = 0; m < configGroups[n]->scriptFunctions.GetLength(); m++ )
- {
- if( configGroups[n]->scriptFunctions[m]->id == funcId )
- return configGroups[n];
- }
- }
- return 0;
- }
- asCConfigGroup *asCScriptEngine::FindConfigGroupForGlobalVar(int gvarId) const
- {
- for( asUINT n = 0; n < configGroups.GetLength(); n++ )
- {
- for( asUINT m = 0; m < configGroups[n]->globalProps.GetLength(); m++ )
- {
- if( int(configGroups[n]->globalProps[m]->id) == gvarId )
- return configGroups[n];
- }
- }
- return 0;
- }
- asCConfigGroup *asCScriptEngine::FindConfigGroupForObjectType(const asCObjectType *objType) const
- {
- for( asUINT n = 0; n < configGroups.GetLength(); n++ )
- {
- for( asUINT m = 0; m < configGroups[n]->objTypes.GetLength(); m++ )
- {
- if( configGroups[n]->objTypes[m] == objType )
- return configGroups[n];
- }
- }
- return 0;
- }
- asCConfigGroup *asCScriptEngine::FindConfigGroupForFuncDef(asCScriptFunction *funcDef) const
- {
- for( asUINT n = 0; n < configGroups.GetLength(); n++ )
- {
- if( configGroups[n]->funcDefs.Exists(funcDef) )
- return configGroups[n];
- }
- return 0;
- }
- #ifdef AS_DEPRECATED
- // deprecated since 2011-10-04
- int asCScriptEngine::SetConfigGroupModuleAccess(const char *groupName, const char *module, bool hasAccess)
- {
- asCConfigGroup *group = 0;
- // Make sure the group name doesn't already exist
- for( asUINT n = 0; n < configGroups.GetLength(); n++ )
- {
- if( configGroups[n]->groupName == groupName )
- {
- group = configGroups[n];
- break;
- }
- }
- if( group == 0 )
- return asWRONG_CONFIG_GROUP;
- return group->SetModuleAccess(module, hasAccess);
- }
- #endif
- // interface
- asDWORD asCScriptEngine::SetDefaultAccessMask(asDWORD defaultMask)
- {
- asDWORD old = defaultAccessMask;
- defaultAccessMask = defaultMask;
- return old;
- }
- int asCScriptEngine::GetNextScriptFunctionId()
- {
- if( freeScriptFunctionIds.GetLength() )
- return freeScriptFunctionIds.PopLast();
- int id = (int)scriptFunctions.GetLength();
- scriptFunctions.PushLast(0);
- return id;
- }
- void asCScriptEngine::SetScriptFunction(asCScriptFunction *func)
- {
- scriptFunctions[func->id] = func;
- }
- void asCScriptEngine::FreeScriptFunctionId(int id)
- {
- if( id < 0 ) return;
- id &= 0xFFFF;
- if( id >= (int)scriptFunctions.GetLength() ) return;
- if( scriptFunctions[id] )
- {
- asCScriptFunction *func = scriptFunctions[id];
- // Remove the function from the list of script functions
- if( id == (int)scriptFunctions.GetLength() - 1 )
- {
- scriptFunctions.PopLast();
- }
- else
- {
- scriptFunctions[id] = 0;
- freeScriptFunctionIds.PushLast(id);
- }
- // Is the function used as signature id?
- if( func->signatureId == id )
- {
- // Remove the signature id
- signatureIds.RemoveValue(func);
- // Update all functions using the signature id
- int newSigId = 0;
- for( asUINT n = 0; n < scriptFunctions.GetLength(); n++ )
- {
- if( scriptFunctions[n] && scriptFunctions[n]->signatureId == id )
- {
- if( newSigId == 0 )
- {
- newSigId = scriptFunctions[n]->id;
- signatureIds.PushLast(scriptFunctions[n]);
- }
- scriptFunctions[n]->signatureId = newSigId;
- }
- }
- }
- }
- }
- // interface
- int asCScriptEngine::RegisterFuncdef(const char *decl)
- {
- if( decl == 0 ) return ConfigError(asINVALID_ARG);
- // Parse the function declaration
- asCScriptFunction *func = asNEW(asCScriptFunction)(this, 0, asFUNC_FUNCDEF);
- asCBuilder bld(this, 0);
- int r = bld.ParseFunctionDeclaration(0, decl, func, false, 0, 0);
- if( r < 0 )
- {
- // Set as dummy function before deleting
- func->funcType = asFUNC_DUMMY;
- asDELETE(func,asCScriptFunction);
- return ConfigError(asINVALID_DECLARATION);
- }
- // Check name conflicts
- r = bld.CheckNameConflict(func->name.AddressOf(), 0, 0);
- if( r < 0 )
- {
- asDELETE(func,asCScriptFunction);
- return ConfigError(asNAME_TAKEN);
- }
- func->id = GetNextScriptFunctionId();
- SetScriptFunction(func);
- funcDefs.PushLast(func);
- registeredFuncDefs.PushLast(func);
- currentGroup->funcDefs.PushLast(func);
- // If parameter type from other groups are used, add references
- if( func->returnType.GetObjectType() )
- {
- asCConfigGroup *group = FindConfigGroupForObjectType(func->returnType.GetObjectType());
- currentGroup->RefConfigGroup(group);
- }
- for( asUINT n = 0; n < func->parameterTypes.GetLength(); n++ )
- {
- if( func->parameterTypes[n].GetObjectType() )
- {
- asCConfigGroup *group = FindConfigGroupForObjectType(func->parameterTypes[n].GetObjectType());
- currentGroup->RefConfigGroup(group);
- }
- }
- // Return the function id as success
- return func->id;
- }
- // interface
- asUINT asCScriptEngine::GetFuncdefCount() const
- {
- return registeredFuncDefs.GetLength();
- }
- // interface
- asIScriptFunction *asCScriptEngine::GetFuncdefByIndex(asUINT index, const char **configGroup) const
- {
- if( index >= registeredFuncDefs.GetLength() )
- return 0;
- if( configGroup )
- {
- asCConfigGroup *group = FindConfigGroupForFuncDef(registeredFuncDefs[index]);
- if( group )
- *configGroup = group->groupName.AddressOf();
- else
- *configGroup = 0;
- }
- return registeredFuncDefs[index];
- }
- // interface
- // TODO: typedef: Accept complex types for the typedefs
- int asCScriptEngine::RegisterTypedef(const char *type, const char *decl)
- {
- if( type == 0 ) return ConfigError(asINVALID_NAME);
- // Verify if the name has been registered as a type already
- asUINT n;
- for( n = 0; n < objectTypes.GetLength(); n++ )
- {
- if( objectTypes[n] && objectTypes[n]->name == type )
- return asALREADY_REGISTERED;
- }
- // Grab the data type
- asCTokenizer t(this);
- size_t tokenLen;
- eTokenType token;
- asCDataType dataType;
- // Create the data type
- token = t.GetToken(decl, strlen(decl), &tokenLen);
- switch(token)
- {
- case ttBool:
- case ttInt:
- case ttInt8:
- case ttInt16:
- case ttInt64:
- case ttUInt:
- case ttUInt8:
- case ttUInt16:
- case ttUInt64:
- case ttFloat:
- case ttDouble:
- if( strlen(decl) != tokenLen )
- {
- return ConfigError(asINVALID_TYPE);
- }
- break;
- default:
- return ConfigError(asINVALID_TYPE);
- }
- dataType = asCDataType::CreatePrimitive(token, false);
- // Make sure the name is not a reserved keyword
- token = t.GetToken(type, strlen(type), &tokenLen);
- if( token != ttIdentifier || strlen(type) != tokenLen )
- return ConfigError(asINVALID_NAME);
- asCBuilder bld(this, 0);
- int r = bld.CheckNameConflict(type, 0, 0);
- if( r < 0 )
- return ConfigError(asNAME_TAKEN);
- // Don't have to check against members of object
- // types as they are allowed to use the names
- // Put the data type in the list
- asCObjectType *object= asNEW(asCObjectType)(this);
- object->flags = asOBJ_TYPEDEF;
- object->size = dataType.GetSizeInMemoryBytes();
- object->name = type;
- object->templateSubType = dataType;
- objectTypes.PushLast(object);
- registeredTypeDefs.PushLast(object);
- currentGroup->objTypes.PushLast(object);
- return asSUCCESS;
- }
- // interface
- asUINT asCScriptEngine::GetTypedefCount() const
- {
- return registeredTypeDefs.GetLength();
- }
- // interface
- const char *asCScriptEngine::GetTypedefByIndex(asUINT index, int *typeId, const char **configGroup) const
- {
- if( index >= registeredTypeDefs.GetLength() )
- return 0;
- if( typeId )
- *typeId = GetTypeIdByDecl(registeredTypeDefs[index]->name.AddressOf());
- if( configGroup )
- {
- asCConfigGroup *group = FindConfigGroupForObjectType(registeredTypeDefs[index]);
- if( group )
- *configGroup = group->groupName.AddressOf();
- else
- *configGroup = 0;
- }
- return registeredTypeDefs[index]->name.AddressOf();
- }
- // interface
- int asCScriptEngine::RegisterEnum(const char *name)
- {
- // Check the name
- if( NULL == name )
- return ConfigError(asINVALID_NAME);
- // Verify if the name has been registered as a type already
- asUINT n;
- for( n = 0; n < objectTypes.GetLength(); n++ )
- if( objectTypes[n] && objectTypes[n]->name == name )
- return asALREADY_REGISTERED;
- // Use builder to parse the datatype
- asCDataType dt;
- asCBuilder bld(this, 0);
- bool oldMsgCallback = msgCallback; msgCallback = false;
- int r = bld.ParseDataType(name, &dt);
- msgCallback = oldMsgCallback;
- if( r >= 0 )
- return ConfigError(asERROR);
- // Make sure the name is not a reserved keyword
- asCTokenizer t(this);
- size_t tokenLen;
- int token = t.GetToken(name, strlen(name), &tokenLen);
- if( token != ttIdentifier || strlen(name) != tokenLen )
- return ConfigError(asINVALID_NAME);
- r = bld.CheckNameConflict(name, 0, 0);
- if( r < 0 )
- return ConfigError(asNAME_TAKEN);
- asCObjectType *st = asNEW(asCObjectType)(this);
- asCDataType dataType;
- dataType.CreatePrimitive(ttInt, false);
- st->flags = asOBJ_ENUM | asOBJ_SHARED;
- st->size = 4;
- st->name = name;
- objectTypes.PushLast(st);
- registeredEnums.PushLast(st);
- currentGroup->objTypes.PushLast(st);
- return asSUCCESS;
- }
- // interface
- int asCScriptEngine::RegisterEnumValue(const char *typeName, const char *valueName, int value)
- {
- // Verify that the correct config group is used
- if( currentGroup->FindType(typeName) == 0 )
- return asWRONG_CONFIG_GROUP;
- asCDataType dt;
- int r;
- asCBuilder bld(this, 0);
- r = bld.ParseDataType(typeName, &dt);
- if( r < 0 )
- return ConfigError(r);
- // Store the enum value
- asCObjectType *ot = dt.GetObjectType();
- if( ot == 0 || !(ot->flags & asOBJ_ENUM) )
- return ConfigError(asINVALID_TYPE);
- if( NULL == valueName )
- return ConfigError(asINVALID_NAME);
- int tokenLen;
- asETokenClass tokenClass = ParseToken(valueName, 0, &tokenLen);
- if( tokenClass != asTC_IDENTIFIER || tokenLen != (int)strlen(valueName) )
- return ConfigError(asINVALID_NAME);
- for( unsigned int n = 0; n < ot->enumValues.GetLength(); n++ )
- {
- if( ot->enumValues[n]->name == valueName )
- return ConfigError(asALREADY_REGISTERED);
- }
- asSEnumValue *e = asNEW(asSEnumValue);
- e->name = valueName;
- e->value = value;
- ot->enumValues.PushLast(e);
- return asSUCCESS;
- }
- // interface
- asUINT asCScriptEngine::GetEnumCount() const
- {
- return registeredEnums.GetLength();
- }
- // interface
- const char *asCScriptEngine::GetEnumByIndex(asUINT index, int *enumTypeId, const char **configGroup) const
- {
- if( index >= registeredEnums.GetLength() )
- return 0;
- if( configGroup )
- {
- asCConfigGroup *group = FindConfigGroupForObjectType(registeredEnums[index]);
- if( group )
- *configGroup = group->groupName.AddressOf();
- else
- *configGroup = 0;
- }
- if( enumTypeId )
- *enumTypeId = GetTypeIdByDecl(registeredEnums[index]->name.AddressOf());
- return registeredEnums[index]->name.AddressOf();
- }
- // interface
- int asCScriptEngine::GetEnumValueCount(int enumTypeId) const
- {
- const asCDataType *dt = GetDataTypeFromTypeId(enumTypeId);
- asCObjectType *t = dt->GetObjectType();
- if( t == 0 || !(t->GetFlags() & asOBJ_ENUM) )
- return asINVALID_TYPE;
- return (int)t->enumValues.GetLength();
- }
- // interface
- const char *asCScriptEngine::GetEnumValueByIndex(int enumTypeId, asUINT index, int *outValue) const
- {
- // TODO: This same function is implemented in as_module.cpp as well. Perhaps it should be moved to asCObjectType?
- const asCDataType *dt = GetDataTypeFromTypeId(enumTypeId);
- asCObjectType *t = dt->GetObjectType();
- if( t == 0 || !(t->GetFlags() & asOBJ_ENUM) )
- return 0;
- if( index >= t->enumValues.GetLength() )
- return 0;
- if( outValue )
- *outValue = t->enumValues[index]->value;
- return t->enumValues[index]->name.AddressOf();
- }
- // interface
- asUINT asCScriptEngine::GetObjectTypeCount() const
- {
- return registeredObjTypes.GetLength();
- }
- // interface
- asIObjectType *asCScriptEngine::GetObjectTypeByIndex(asUINT index) const
- {
- if( index >= registeredObjTypes.GetLength() )
- return 0;
- return registeredObjTypes[index];
- }
- // interface
- asIObjectType *asCScriptEngine::GetObjectTypeById(int typeId) const
- {
- const asCDataType *dt = GetDataTypeFromTypeId(typeId);
- // Is the type id valid?
- if( !dt ) return 0;
- // Enum types are not objects, so we shouldn't return an object type for them
- if( dt->GetObjectType() && dt->GetObjectType()->GetFlags() & asOBJ_ENUM )
- return 0;
- return dt->GetObjectType();
- }
- // interface
- asIScriptFunction *asCScriptEngine::GetFunctionById(int funcId) const
- {
- return GetScriptFunction(funcId);
- }
- #ifdef AS_DEPRECATED
- // deprecated since 2011-10-03
- asIScriptFunction *asCScriptEngine::GetFunctionDescriptorById(int funcId) const
- {
- return GetScriptFunction(funcId);
- }
- #endif
- // internal
- bool asCScriptEngine::IsTemplateType(const char *name) const
- {
- // TODO: optimize: Improve linear search
- for( unsigned int n = 0; n < objectTypes.GetLength(); n++ )
- {
- if( objectTypes[n] && objectTypes[n]->name == name )
- {
- return objectTypes[n]->flags & asOBJ_TEMPLATE ? true : false;
- }
- }
- return false;
- }
- // internal
- int asCScriptEngine::AddConstantString(const char *str, size_t len)
- {
- // The str may contain null chars, so we cannot use strlen, or strcmp, or strcpy
- // TODO: optimize: Improve linear search
- // Has the string been registered before?
- for( size_t n = 0; n < stringConstants.GetLength(); n++ )
- {
- if( stringConstants[n]->Compare(str, len) == 0 )
- {
- return (int)n;
- }
- }
- // No match was found, add the string
- asCString *cstr = asNEW(asCString)(str, len);
- stringConstants.PushLast(cstr);
- // The VM currently doesn't handle string ids larger than 65535
- asASSERT(stringConstants.GetLength() <= 65536);
- return (int)stringConstants.GetLength() - 1;
- }
- // internal
- const asCString &asCScriptEngine::GetConstantString(int id)
- {
- return *stringConstants[id];
- }
- // internal
- int asCScriptEngine::GetScriptSectionNameIndex(const char *name)
- {
- // TODO: These names are only released when the engine is freed. The assumption is that
- // the same script section names will be reused instead of there always being new
- // names. Is this assumption valid? Do we need to add reference counting?
- // Store the script section names for future reference
- for( asUINT n = 0; n < scriptSectionNames.GetLength(); n++ )
- {
- if( scriptSectionNames[n]->Compare(name) == 0 )
- return n;
- }
- scriptSectionNames.PushLast(asNEW(asCString)(name));
- return int(scriptSectionNames.GetLength()-1);
- }
- // interface
- void asCScriptEngine::SetEngineUserDataCleanupCallback(asCLEANENGINEFUNC_t callback)
- {
- cleanEngineFunc = callback;
- }
- // interface
- void asCScriptEngine::SetModuleUserDataCleanupCallback(asCLEANMODULEFUNC_t callback)
- {
- cleanModuleFunc = callback;
- }
- // interface
- void asCScriptEngine::SetContextUserDataCleanupCallback(asCLEANCONTEXTFUNC_t callback)
- {
- cleanContextFunc = callback;
- }
- // interface
- void asCScriptEngine::SetFunctionUserDataCleanupCallback(asCLEANFUNCTIONFUNC_t callback)
- {
- cleanFunctionFunc = callback;
- }
- // interface
- void asCScriptEngine::SetObjectTypeUserDataCleanupCallback(asCLEANOBJECTTYPEFUNC_t callback)
- {
- cleanObjectTypeFunc = callback;
- }
- // Urho3D: modified for smaller executable size
- asSFuncPtr::asSFuncPtr()
- {
- asMemClear(this, sizeof(asSFuncPtr));
- }
- asSFuncPtr::asSFuncPtr(asBYTE f)
- {
- asMemClear(this, sizeof(asSFuncPtr));
- flag = f;
- }
- END_AS_NAMESPACE
|