Script_Program.cpp 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #pragma hdrstop
  21. #include "../../idlib/precompiled.h"
  22. #include "../Game_local.h"
  23. // simple types. function types are dynamically allocated
  24. idTypeDef type_void( ev_void, &def_void, "void", 0, NULL );
  25. idTypeDef type_scriptevent( ev_scriptevent, &def_scriptevent, "scriptevent", sizeof( void * ), NULL );
  26. idTypeDef type_namespace( ev_namespace, &def_namespace, "namespace", sizeof( void * ), NULL );
  27. idTypeDef type_string( ev_string, &def_string, "string", MAX_STRING_LEN, NULL );
  28. idTypeDef type_float( ev_float, &def_float, "float", sizeof( float ), NULL );
  29. idTypeDef type_vector( ev_vector, &def_vector, "vector", sizeof( idVec3 ), NULL );
  30. idTypeDef type_entity( ev_entity, &def_entity, "entity", sizeof( int * ), NULL ); // stored as entity number pointer
  31. idTypeDef type_field( ev_field, &def_field, "field", sizeof( void * ), NULL );
  32. idTypeDef type_function( ev_function, &def_function, "function", sizeof( void * ), &type_void );
  33. idTypeDef type_virtualfunction( ev_virtualfunction, &def_virtualfunction, "virtual function", sizeof( int ), NULL );
  34. idTypeDef type_pointer( ev_pointer, &def_pointer, "pointer", sizeof( void * ), NULL );
  35. idTypeDef type_object( ev_object, &def_object, "object", sizeof( int * ), NULL ); // stored as entity number pointer
  36. idTypeDef type_jumpoffset( ev_jumpoffset, &def_jumpoffset, "<jump>", sizeof( int ), NULL ); // only used for jump opcodes
  37. idTypeDef type_argsize( ev_argsize, &def_argsize, "<argsize>", sizeof( int ), NULL ); // only used for function call and thread opcodes
  38. idTypeDef type_boolean( ev_boolean, &def_boolean, "boolean", sizeof( int ), NULL );
  39. idVarDef def_void( &type_void );
  40. idVarDef def_scriptevent( &type_scriptevent );
  41. idVarDef def_namespace( &type_namespace );
  42. idVarDef def_string( &type_string );
  43. idVarDef def_float( &type_float );
  44. idVarDef def_vector( &type_vector );
  45. idVarDef def_entity( &type_entity );
  46. idVarDef def_field( &type_field );
  47. idVarDef def_function( &type_function );
  48. idVarDef def_virtualfunction( &type_virtualfunction );
  49. idVarDef def_pointer( &type_pointer );
  50. idVarDef def_object( &type_object );
  51. idVarDef def_jumpoffset( &type_jumpoffset ); // only used for jump opcodes
  52. idVarDef def_argsize( &type_argsize );
  53. idVarDef def_boolean( &type_boolean );
  54. /***********************************************************************
  55. function_t
  56. ***********************************************************************/
  57. /*
  58. ================
  59. function_t::function_t
  60. ================
  61. */
  62. function_t::function_t() {
  63. Clear();
  64. }
  65. /*
  66. ================
  67. function_t::Allocated
  68. ================
  69. */
  70. size_t function_t::Allocated() const {
  71. return name.Allocated() + parmSize.Allocated();
  72. }
  73. /*
  74. ================
  75. function_t::SetName
  76. ================
  77. */
  78. void function_t::SetName( const char *name ) {
  79. this->name = name;
  80. }
  81. /*
  82. ================
  83. function_t::Name
  84. ================
  85. */
  86. const char *function_t::Name() const {
  87. return name;
  88. }
  89. /*
  90. ================
  91. function_t::Clear
  92. ================
  93. */
  94. void function_t::Clear() {
  95. eventdef = NULL;
  96. def = NULL;
  97. type = NULL;
  98. firstStatement = 0;
  99. numStatements = 0;
  100. parmTotal = 0;
  101. locals = 0;
  102. filenum = 0;
  103. name.Clear();
  104. parmSize.Clear();
  105. }
  106. /***********************************************************************
  107. idTypeDef
  108. ***********************************************************************/
  109. /*
  110. ================
  111. idTypeDef::idTypeDef
  112. ================
  113. */
  114. idTypeDef::idTypeDef( etype_t etype, idVarDef *edef, const char *ename, int esize, idTypeDef *aux ) {
  115. name = ename;
  116. type = etype;
  117. def = edef;
  118. size = esize;
  119. auxType = aux;
  120. parmTypes.SetGranularity( 1 );
  121. parmNames.SetGranularity( 1 );
  122. functions.SetGranularity( 1 );
  123. }
  124. /*
  125. ================
  126. idTypeDef::idTypeDef
  127. ================
  128. */
  129. idTypeDef::idTypeDef( const idTypeDef &other ) {
  130. *this = other;
  131. }
  132. /*
  133. ================
  134. idTypeDef::operator=
  135. ================
  136. */
  137. void idTypeDef::operator=( const idTypeDef& other ) {
  138. type = other.type;
  139. def = other.def;
  140. name = other.name;
  141. size = other.size;
  142. auxType = other.auxType;
  143. parmTypes = other.parmTypes;
  144. parmNames = other.parmNames;
  145. functions = other.functions;
  146. }
  147. /*
  148. ================
  149. idTypeDef::Allocated
  150. ================
  151. */
  152. size_t idTypeDef::Allocated() const {
  153. size_t memsize;
  154. int i;
  155. memsize = name.Allocated() + parmTypes.Allocated() + parmNames.Allocated() + functions.Allocated();
  156. for( i = 0; i < parmTypes.Num(); i++ ) {
  157. memsize += parmNames[ i ].Allocated();
  158. }
  159. return memsize;
  160. }
  161. /*
  162. ================
  163. idTypeDef::Inherits
  164. Returns true if basetype is an ancestor of this type.
  165. ================
  166. */
  167. bool idTypeDef::Inherits( const idTypeDef *basetype ) const {
  168. idTypeDef *superType;
  169. if ( type != ev_object ) {
  170. return false;
  171. }
  172. if ( this == basetype ) {
  173. return true;
  174. }
  175. for( superType = auxType; superType != NULL; superType = superType->auxType ) {
  176. if ( superType == basetype ) {
  177. return true;
  178. }
  179. }
  180. return false;
  181. }
  182. /*
  183. ================
  184. idTypeDef::MatchesType
  185. Returns true if both types' base types and parameters match
  186. ================
  187. */
  188. bool idTypeDef::MatchesType( const idTypeDef &matchtype ) const {
  189. int i;
  190. if ( this == &matchtype ) {
  191. return true;
  192. }
  193. if ( ( type != matchtype.type ) || ( auxType != matchtype.auxType ) ) {
  194. return false;
  195. }
  196. if ( parmTypes.Num() != matchtype.parmTypes.Num() ) {
  197. return false;
  198. }
  199. for( i = 0; i < matchtype.parmTypes.Num(); i++ ) {
  200. if ( parmTypes[ i ] != matchtype.parmTypes[ i ] ) {
  201. return false;
  202. }
  203. }
  204. return true;
  205. }
  206. /*
  207. ================
  208. idTypeDef::MatchesVirtualFunction
  209. Returns true if both functions' base types and parameters match
  210. ================
  211. */
  212. bool idTypeDef::MatchesVirtualFunction( const idTypeDef &matchfunc ) const {
  213. int i;
  214. if ( this == &matchfunc ) {
  215. return true;
  216. }
  217. if ( ( type != matchfunc.type ) || ( auxType != matchfunc.auxType ) ) {
  218. return false;
  219. }
  220. if ( parmTypes.Num() != matchfunc.parmTypes.Num() ) {
  221. return false;
  222. }
  223. if ( parmTypes.Num() > 0 ) {
  224. if ( !parmTypes[ 0 ]->Inherits( matchfunc.parmTypes[ 0 ] ) ) {
  225. return false;
  226. }
  227. }
  228. for( i = 1; i < matchfunc.parmTypes.Num(); i++ ) {
  229. if ( parmTypes[ i ] != matchfunc.parmTypes[ i ] ) {
  230. return false;
  231. }
  232. }
  233. return true;
  234. }
  235. /*
  236. ================
  237. idTypeDef::AddFunctionParm
  238. Adds a new parameter for a function type.
  239. ================
  240. */
  241. void idTypeDef::AddFunctionParm( idTypeDef *parmtype, const char *name ) {
  242. if ( type != ev_function ) {
  243. throw idCompileError( "idTypeDef::AddFunctionParm : tried to add parameter on non-function type" );
  244. }
  245. parmTypes.Append( parmtype );
  246. idStr &parmName = parmNames.Alloc();
  247. parmName = name;
  248. }
  249. /*
  250. ================
  251. idTypeDef::AddField
  252. Adds a new field to an object type.
  253. ================
  254. */
  255. void idTypeDef::AddField( idTypeDef *fieldtype, const char *name ) {
  256. if ( type != ev_object ) {
  257. throw idCompileError( "idTypeDef::AddField : tried to add field to non-object type" );
  258. }
  259. parmTypes.Append( fieldtype );
  260. idStr &parmName = parmNames.Alloc();
  261. parmName = name;
  262. if ( fieldtype->FieldType()->Inherits( &type_object ) ) {
  263. size += type_object.Size();
  264. } else {
  265. size += fieldtype->FieldType()->Size();
  266. }
  267. }
  268. /*
  269. ================
  270. idTypeDef::SetName
  271. ================
  272. */
  273. void idTypeDef::SetName( const char *newname ) {
  274. name = newname;
  275. }
  276. /*
  277. ================
  278. idTypeDef::Name
  279. ================
  280. */
  281. const char *idTypeDef::Name() const {
  282. return name;
  283. }
  284. /*
  285. ================
  286. idTypeDef::Type
  287. ================
  288. */
  289. etype_t idTypeDef::Type() const {
  290. return type;
  291. }
  292. /*
  293. ================
  294. idTypeDef::Size
  295. ================
  296. */
  297. int idTypeDef::Size() const {
  298. return size;
  299. }
  300. /*
  301. ================
  302. idTypeDef::SuperClass
  303. If type is an object, then returns the object's superclass
  304. ================
  305. */
  306. idTypeDef *idTypeDef::SuperClass() const {
  307. if ( type != ev_object ) {
  308. throw idCompileError( "idTypeDef::SuperClass : tried to get superclass of a non-object type" );
  309. }
  310. return auxType;
  311. }
  312. /*
  313. ================
  314. idTypeDef::ReturnType
  315. If type is a function, then returns the function's return type
  316. ================
  317. */
  318. idTypeDef *idTypeDef::ReturnType() const {
  319. if ( type != ev_function ) {
  320. throw idCompileError( "idTypeDef::ReturnType: tried to get return type on non-function type" );
  321. }
  322. return auxType;
  323. }
  324. /*
  325. ================
  326. idTypeDef::SetReturnType
  327. If type is a function, then sets the function's return type
  328. ================
  329. */
  330. void idTypeDef::SetReturnType( idTypeDef *returntype ) {
  331. if ( type != ev_function ) {
  332. throw idCompileError( "idTypeDef::SetReturnType: tried to set return type on non-function type" );
  333. }
  334. auxType = returntype;
  335. }
  336. /*
  337. ================
  338. idTypeDef::FieldType
  339. If type is a field, then returns it's type
  340. ================
  341. */
  342. idTypeDef *idTypeDef::FieldType() const {
  343. if ( type != ev_field ) {
  344. throw idCompileError( "idTypeDef::FieldType: tried to get field type on non-field type" );
  345. }
  346. return auxType;
  347. }
  348. /*
  349. ================
  350. idTypeDef::SetFieldType
  351. If type is a field, then sets the function's return type
  352. ================
  353. */
  354. void idTypeDef::SetFieldType( idTypeDef *fieldtype ) {
  355. if ( type != ev_field ) {
  356. throw idCompileError( "idTypeDef::SetFieldType: tried to set return type on non-function type" );
  357. }
  358. auxType = fieldtype;
  359. }
  360. /*
  361. ================
  362. idTypeDef::PointerType
  363. If type is a pointer, then returns the type it points to
  364. ================
  365. */
  366. idTypeDef *idTypeDef::PointerType() const {
  367. if ( type != ev_pointer ) {
  368. throw idCompileError( "idTypeDef::PointerType: tried to get pointer type on non-pointer" );
  369. }
  370. return auxType;
  371. }
  372. /*
  373. ================
  374. idTypeDef::SetPointerType
  375. If type is a pointer, then sets the pointer's type
  376. ================
  377. */
  378. void idTypeDef::SetPointerType( idTypeDef *pointertype ) {
  379. if ( type != ev_pointer ) {
  380. throw idCompileError( "idTypeDef::SetPointerType: tried to set type on non-pointer" );
  381. }
  382. auxType = pointertype;
  383. }
  384. /*
  385. ================
  386. idTypeDef::NumParameters
  387. ================
  388. */
  389. int idTypeDef::NumParameters() const {
  390. return parmTypes.Num();
  391. }
  392. /*
  393. ================
  394. idTypeDef::GetParmType
  395. ================
  396. */
  397. idTypeDef *idTypeDef::GetParmType( int parmNumber ) const {
  398. assert( parmNumber >= 0 );
  399. assert( parmNumber < parmTypes.Num() );
  400. return parmTypes[ parmNumber ];
  401. }
  402. /*
  403. ================
  404. idTypeDef::GetParmName
  405. ================
  406. */
  407. const char *idTypeDef::GetParmName( int parmNumber ) const {
  408. assert( parmNumber >= 0 );
  409. assert( parmNumber < parmTypes.Num() );
  410. return parmNames[ parmNumber ];
  411. }
  412. /*
  413. ================
  414. idTypeDef::NumFunctions
  415. ================
  416. */
  417. int idTypeDef::NumFunctions() const {
  418. return functions.Num();
  419. }
  420. /*
  421. ================
  422. idTypeDef::GetFunctionNumber
  423. ================
  424. */
  425. int idTypeDef::GetFunctionNumber( const function_t *func ) const {
  426. int i;
  427. for( i = 0; i < functions.Num(); i++ ) {
  428. if ( functions[ i ] == func ) {
  429. return i;
  430. }
  431. }
  432. return -1;
  433. }
  434. /*
  435. ================
  436. idTypeDef::GetFunction
  437. ================
  438. */
  439. const function_t *idTypeDef::GetFunction( int funcNumber ) const {
  440. assert( funcNumber >= 0 );
  441. assert( funcNumber < functions.Num() );
  442. return functions[ funcNumber ];
  443. }
  444. /*
  445. ================
  446. idTypeDef::AddFunction
  447. ================
  448. */
  449. void idTypeDef::AddFunction( const function_t *func ) {
  450. int i;
  451. for( i = 0; i < functions.Num(); i++ ) {
  452. if ( !strcmp( functions[ i ]->def->Name(), func->def->Name() ) ) {
  453. if ( func->def->TypeDef()->MatchesVirtualFunction( *functions[ i ]->def->TypeDef() ) ) {
  454. functions[ i ] = func;
  455. return;
  456. }
  457. }
  458. }
  459. functions.Append( func );
  460. }
  461. /***********************************************************************
  462. idVarDef
  463. ***********************************************************************/
  464. /*
  465. ================
  466. idVarDef::idVarDef()
  467. ================
  468. */
  469. idVarDef::idVarDef( idTypeDef *typeptr ) {
  470. typeDef = typeptr;
  471. num = 0;
  472. scope = NULL;
  473. numUsers = 0;
  474. initialized = idVarDef::uninitialized;
  475. memset( &value, 0, sizeof( value ) );
  476. name = NULL;
  477. next = NULL;
  478. }
  479. /*
  480. ============
  481. idVarDef::~idVarDef
  482. ============
  483. */
  484. idVarDef::~idVarDef() {
  485. if ( name ) {
  486. name->RemoveDef( this );
  487. }
  488. }
  489. /*
  490. ============
  491. idVarDef::Name
  492. ============
  493. */
  494. const char *idVarDef::Name() const {
  495. return name->Name();
  496. }
  497. /*
  498. ============
  499. idVarDef::GlobalName
  500. ============
  501. */
  502. const char *idVarDef::GlobalName() const {
  503. if ( scope != &def_namespace ) {
  504. return va( "%s::%s", scope->GlobalName(), name->Name() );
  505. } else {
  506. return name->Name();
  507. }
  508. }
  509. /*
  510. ============
  511. idVarDef::DepthOfScope
  512. ============
  513. */
  514. int idVarDef::DepthOfScope( const idVarDef *otherScope ) const {
  515. const idVarDef *def;
  516. int depth;
  517. depth = 1;
  518. for( def = otherScope; def != NULL; def = def->scope ) {
  519. if ( def == scope ) {
  520. return depth;
  521. }
  522. depth++;
  523. }
  524. return 0;
  525. }
  526. /*
  527. ============
  528. idVarDef::SetFunction
  529. ============
  530. */
  531. void idVarDef::SetFunction( function_t *func ) {
  532. assert( typeDef );
  533. initialized = initializedConstant;
  534. assert( typeDef->Type() == ev_function );
  535. value.functionPtr = func;
  536. }
  537. /*
  538. ============
  539. idVarDef::SetObject
  540. ============
  541. */
  542. void idVarDef::SetObject( idScriptObject *object ) {
  543. assert( typeDef );
  544. initialized = initialized;
  545. assert( typeDef->Inherits( &type_object ) );
  546. *value.objectPtrPtr = object;
  547. }
  548. /*
  549. ============
  550. idVarDef::SetValue
  551. ============
  552. */
  553. void idVarDef::SetValue( const eval_t &_value, bool constant ) {
  554. assert( typeDef );
  555. if ( constant ) {
  556. initialized = initializedConstant;
  557. } else {
  558. initialized = initializedVariable;
  559. }
  560. switch( typeDef->Type() ) {
  561. case ev_pointer :
  562. case ev_boolean :
  563. case ev_field :
  564. *value.intPtr = _value._int;
  565. break;
  566. case ev_jumpoffset :
  567. value.jumpOffset = _value._int;
  568. break;
  569. case ev_argsize :
  570. value.argSize = _value._int;
  571. break;
  572. case ev_entity :
  573. *value.entityNumberPtr = _value.entity;
  574. break;
  575. case ev_string :
  576. idStr::Copynz( value.stringPtr, _value.stringPtr, MAX_STRING_LEN );
  577. break;
  578. case ev_float :
  579. *value.floatPtr = _value._float;
  580. break;
  581. case ev_vector :
  582. value.vectorPtr->x = _value.vector[ 0 ];
  583. value.vectorPtr->y = _value.vector[ 1 ];
  584. value.vectorPtr->z = _value.vector[ 2 ];
  585. break;
  586. case ev_function :
  587. value.functionPtr = _value.function;
  588. break;
  589. case ev_virtualfunction :
  590. value.virtualFunction = _value._int;
  591. break;
  592. case ev_object :
  593. *value.entityNumberPtr = _value.entity;
  594. break;
  595. default :
  596. throw idCompileError( va( "weird type on '%s'", Name() ) );
  597. break;
  598. }
  599. }
  600. /*
  601. ============
  602. idVarDef::SetString
  603. ============
  604. */
  605. void idVarDef::SetString( const char *string, bool constant ) {
  606. if ( constant ) {
  607. initialized = initializedConstant;
  608. } else {
  609. initialized = initializedVariable;
  610. }
  611. assert( typeDef && ( typeDef->Type() == ev_string ) );
  612. idStr::Copynz( value.stringPtr, string, MAX_STRING_LEN );
  613. }
  614. /*
  615. ============
  616. idVarDef::PrintInfo
  617. ============
  618. */
  619. void idVarDef::PrintInfo( idFile *file, int instructionPointer ) const {
  620. statement_t *jumpst;
  621. int jumpto;
  622. etype_t etype;
  623. int i;
  624. int len;
  625. const char *ch;
  626. if ( initialized == initializedConstant ) {
  627. file->Printf( "const " );
  628. }
  629. etype = typeDef->Type();
  630. switch( etype ) {
  631. case ev_jumpoffset :
  632. jumpto = instructionPointer + value.jumpOffset;
  633. jumpst = &gameLocal.program.GetStatement( jumpto );
  634. file->Printf( "address %d [%s(%d)]", jumpto, gameLocal.program.GetFilename( jumpst->file ), jumpst->linenumber );
  635. break;
  636. case ev_function :
  637. if ( value.functionPtr->eventdef ) {
  638. file->Printf( "event %s", GlobalName() );
  639. } else {
  640. file->Printf( "function %s", GlobalName() );
  641. }
  642. break;
  643. case ev_field :
  644. file->Printf( "field %d", value.ptrOffset );
  645. break;
  646. case ev_argsize:
  647. file->Printf( "args %d", value.argSize );
  648. break;
  649. default:
  650. file->Printf( "%s ", typeDef->Name() );
  651. if ( initialized == initializedConstant ) {
  652. switch( etype ) {
  653. case ev_string :
  654. file->Printf( "\"" );
  655. len = strlen( value.stringPtr );
  656. ch = value.stringPtr;
  657. for( i = 0; i < len; i++, ch++ ) {
  658. if ( idStr::CharIsPrintable( *ch ) ) {
  659. file->Printf( "%c", *ch );
  660. } else if ( *ch == '\n' ) {
  661. file->Printf( "\\n" );
  662. } else {
  663. file->Printf( "\\x%.2x", static_cast<int>( *ch ) );
  664. }
  665. }
  666. file->Printf( "\"" );
  667. break;
  668. case ev_vector :
  669. file->Printf( "'%s'", value.vectorPtr->ToString() );
  670. break;
  671. case ev_float :
  672. file->Printf( "%f", *value.floatPtr );
  673. break;
  674. case ev_virtualfunction :
  675. file->Printf( "vtable[ %d ]", value.virtualFunction );
  676. break;
  677. default :
  678. file->Printf( "%d", *value.intPtr );
  679. break;
  680. }
  681. } else if ( initialized == stackVariable ) {
  682. file->Printf( "stack[%d]", value.stackOffset );
  683. } else {
  684. file->Printf( "global[%d]", num );
  685. }
  686. break;
  687. }
  688. }
  689. /***********************************************************************
  690. idVarDef
  691. ***********************************************************************/
  692. /*
  693. ============
  694. idVarDefName::AddDef
  695. ============
  696. */
  697. void idVarDefName::AddDef( idVarDef *def ) {
  698. assert( def->next == NULL );
  699. def->name = this;
  700. def->next = defs;
  701. defs = def;
  702. }
  703. /*
  704. ============
  705. idVarDefName::RemoveDef
  706. ============
  707. */
  708. void idVarDefName::RemoveDef( idVarDef *def ) {
  709. if ( defs == def ) {
  710. defs = def->next;
  711. } else {
  712. for ( idVarDef *d = defs; d->next != NULL; d = d->next ) {
  713. if ( d->next == def ) {
  714. d->next = def->next;
  715. break;
  716. }
  717. }
  718. }
  719. def->next = NULL;
  720. def->name = NULL;
  721. }
  722. /***********************************************************************
  723. idScriptObject
  724. ***********************************************************************/
  725. /*
  726. ============
  727. idScriptObject::idScriptObject
  728. ============
  729. */
  730. idScriptObject::idScriptObject() {
  731. data = NULL;
  732. type = &type_object;
  733. }
  734. /*
  735. ============
  736. idScriptObject::~idScriptObject
  737. ============
  738. */
  739. idScriptObject::~idScriptObject() {
  740. Free();
  741. }
  742. /*
  743. ============
  744. idScriptObject::Free
  745. ============
  746. */
  747. void idScriptObject::Free() {
  748. if ( data ) {
  749. Mem_Free( data );
  750. }
  751. data = NULL;
  752. type = &type_object;
  753. }
  754. /*
  755. ================
  756. idScriptObject::Save
  757. ================
  758. */
  759. void idScriptObject::Save( idSaveGame *savefile ) const {
  760. size_t size;
  761. if ( type == &type_object && data == NULL ) {
  762. // Write empty string for uninitialized object
  763. savefile->WriteString( "" );
  764. } else {
  765. savefile->WriteString( type->Name() );
  766. size = type->Size();
  767. savefile->WriteInt( size );
  768. savefile->Write( data, size );
  769. }
  770. }
  771. /*
  772. ================
  773. idScriptObject::Restore
  774. ================
  775. */
  776. void idScriptObject::Restore( idRestoreGame *savefile ) {
  777. idStr typeName;
  778. int size;
  779. savefile->ReadString( typeName );
  780. // Empty string signals uninitialized object
  781. if ( typeName.Length() == 0 ) {
  782. return;
  783. }
  784. if ( !SetType( typeName ) ) {
  785. savefile->Error( "idScriptObject::Restore: failed to restore object of type '%s'.", typeName.c_str() );
  786. }
  787. savefile->ReadInt( size );
  788. if ( size != type->Size() ) {
  789. savefile->Error( "idScriptObject::Restore: size of object '%s' doesn't match size in save game.", typeName.c_str() );
  790. }
  791. savefile->Read( data, size );
  792. }
  793. /*
  794. ============
  795. idScriptObject::SetType
  796. Allocates an object and initializes memory.
  797. ============
  798. */
  799. bool idScriptObject::SetType( const char *typeName ) {
  800. size_t size;
  801. idTypeDef *newtype;
  802. // lookup the type
  803. newtype = gameLocal.program.FindType( typeName );
  804. // only allocate memory if the object type changes
  805. if ( newtype != type ) {
  806. Free();
  807. if ( !newtype ) {
  808. gameLocal.Warning( "idScriptObject::SetType: Unknown type '%s'", typeName );
  809. return false;
  810. }
  811. if ( !newtype->Inherits( &type_object ) ) {
  812. gameLocal.Warning( "idScriptObject::SetType: Can't create object of type '%s'. Must be an object type.", newtype->Name() );
  813. return false;
  814. }
  815. // set the type
  816. type = newtype;
  817. // allocate the memory
  818. size = type->Size();
  819. data = ( byte * )Mem_Alloc( size, TAG_SCRIPT );
  820. }
  821. // init object memory
  822. ClearObject();
  823. return true;
  824. }
  825. /*
  826. ============
  827. idScriptObject::ClearObject
  828. Resets the memory for the script object without changing its type.
  829. ============
  830. */
  831. void idScriptObject::ClearObject() {
  832. size_t size;
  833. if ( type != &type_object ) {
  834. // init object memory
  835. size = type->Size();
  836. memset( data, 0, size );
  837. }
  838. }
  839. /*
  840. ============
  841. idScriptObject::HasObject
  842. ============
  843. */
  844. bool idScriptObject::HasObject() const {
  845. return ( type != &type_object );
  846. }
  847. /*
  848. ============
  849. idScriptObject::GetTypeDef
  850. ============
  851. */
  852. idTypeDef *idScriptObject::GetTypeDef() const {
  853. return type;
  854. }
  855. /*
  856. ============
  857. idScriptObject::GetTypeName
  858. ============
  859. */
  860. const char *idScriptObject::GetTypeName() const {
  861. return type->Name();
  862. }
  863. /*
  864. ============
  865. idScriptObject::GetConstructor
  866. ============
  867. */
  868. const function_t *idScriptObject::GetConstructor() const {
  869. const function_t *func;
  870. func = GetFunction( "init" );
  871. return func;
  872. }
  873. /*
  874. ============
  875. idScriptObject::GetDestructor
  876. ============
  877. */
  878. const function_t *idScriptObject::GetDestructor() const {
  879. const function_t *func;
  880. func = GetFunction( "destroy" );
  881. return func;
  882. }
  883. /*
  884. ============
  885. idScriptObject::GetFunction
  886. ============
  887. */
  888. const function_t *idScriptObject::GetFunction( const char *name ) const {
  889. const function_t *func;
  890. if ( type == &type_object ) {
  891. return NULL;
  892. }
  893. func = gameLocal.program.FindFunction( name, type );
  894. return func;
  895. }
  896. /*
  897. ============
  898. idScriptObject::GetVariable
  899. ============
  900. */
  901. byte *idScriptObject::GetVariable( const char *name, etype_t etype ) const {
  902. int i;
  903. int pos;
  904. const idTypeDef *t = type;
  905. const idTypeDef *parm;
  906. if ( t == &type_object || t == NULL ) {
  907. return NULL;
  908. }
  909. do {
  910. if ( t->SuperClass() != &type_object ) {
  911. pos = t->SuperClass()->Size();
  912. } else {
  913. pos = 0;
  914. }
  915. for( i = 0; i < t->NumParameters(); i++ ) {
  916. parm = t->GetParmType( i );
  917. if ( !strcmp( t->GetParmName( i ), name ) ) {
  918. if ( etype != parm->FieldType()->Type() ) {
  919. return NULL;
  920. }
  921. return &data[ pos ];
  922. }
  923. if ( parm->FieldType()->Inherits( &type_object ) ) {
  924. pos += type_object.Size();
  925. } else {
  926. pos += parm->FieldType()->Size();
  927. }
  928. }
  929. t = t->SuperClass();
  930. } while( t != NULL && ( t != &type_object ) );
  931. return NULL;
  932. }
  933. /***********************************************************************
  934. idProgram
  935. ***********************************************************************/
  936. /*
  937. ============
  938. idProgram::AllocType
  939. ============
  940. */
  941. idTypeDef *idProgram::AllocType( idTypeDef &type ) {
  942. idTypeDef * newtype = new (TAG_SCRIPT) idTypeDef( type );
  943. typesHash.Add( idStr::Hash( type.Name() ), types.Append( newtype ) );
  944. return newtype;
  945. }
  946. /*
  947. ============
  948. idProgram::AllocType
  949. ============
  950. */
  951. idTypeDef *idProgram::AllocType( etype_t etype, idVarDef *edef, const char *ename, int esize, idTypeDef *aux ) {
  952. idTypeDef * newtype = new (TAG_SCRIPT) idTypeDef( etype, edef, ename, esize, aux );
  953. typesHash.Add( idStr::Hash( ename ), types.Append( newtype ) );
  954. return newtype;
  955. }
  956. /*
  957. ============
  958. idProgram::GetType
  959. Returns a preexisting complex type that matches the parm, or allocates
  960. a new one and copies it out.
  961. ============
  962. */
  963. idTypeDef *idProgram::GetType( idTypeDef &type, bool allocate ) {
  964. for ( int i = typesHash.First( idStr::Hash( type.Name() ) ); i != -1; i = typesHash.Next( i ) ) {
  965. if ( types[ i ]->MatchesType( type ) && !strcmp( types[ i ]->Name(), type.Name() ) ) {
  966. return types[ i ];
  967. }
  968. }
  969. if ( !allocate ) {
  970. return NULL;
  971. }
  972. // allocate a new one
  973. return AllocType( type );
  974. }
  975. /*
  976. ============
  977. idProgram::FindType
  978. Returns a preexisting complex type that matches the name, or returns NULL if not found
  979. ============
  980. */
  981. idTypeDef *idProgram::FindType( const char *name ) {
  982. for ( int i = typesHash.First( idStr::Hash( name ) ); i != -1; i = typesHash.Next( i ) ) {
  983. idTypeDef * check = types[ i ];
  984. if ( !strcmp( check->Name(), name ) ) {
  985. return check;
  986. }
  987. }
  988. return NULL;
  989. }
  990. /*
  991. ============
  992. idProgram::GetDefList
  993. ============
  994. */
  995. idVarDef *idProgram::GetDefList( const char *name ) const {
  996. int i, hash;
  997. hash = varDefNameHash.GenerateKey( name, true );
  998. for ( i = varDefNameHash.First( hash ); i != -1; i = varDefNameHash.Next( i ) ) {
  999. if ( idStr::Cmp( varDefNames[i]->Name(), name ) == 0 ) {
  1000. return varDefNames[i]->GetDefs();
  1001. }
  1002. }
  1003. return NULL;
  1004. }
  1005. /*
  1006. ============
  1007. idProgram::AddDefToNameList
  1008. ============
  1009. */
  1010. void idProgram::AddDefToNameList( idVarDef *def, const char *name ) {
  1011. int i, hash;
  1012. hash = varDefNameHash.GenerateKey( name, true );
  1013. for ( i = varDefNameHash.First( hash ); i != -1; i = varDefNameHash.Next( i ) ) {
  1014. if ( idStr::Cmp( varDefNames[i]->Name(), name ) == 0 ) {
  1015. break;
  1016. }
  1017. }
  1018. if ( i == -1 ) {
  1019. i = varDefNames.Append( new (TAG_SCRIPT) idVarDefName( name ) );
  1020. varDefNameHash.Add( hash, i );
  1021. }
  1022. varDefNames[i]->AddDef( def );
  1023. }
  1024. /*
  1025. ============
  1026. idProgram::AllocDef
  1027. ============
  1028. */
  1029. idVarDef *idProgram::AllocDef( idTypeDef *type, const char *name, idVarDef *scope, bool constant ) {
  1030. idVarDef *def;
  1031. idStr element;
  1032. idVarDef *def_x;
  1033. idVarDef *def_y;
  1034. idVarDef *def_z;
  1035. // allocate a new def
  1036. def = new (TAG_SCRIPT) idVarDef( type );
  1037. def->scope = scope;
  1038. def->numUsers = 1;
  1039. def->num = varDefs.Append( def );
  1040. // add the def to the list with defs with this name and set the name pointer
  1041. AddDefToNameList( def, name );
  1042. if ( ( type->Type() == ev_vector ) || ( ( type->Type() == ev_field ) && ( type->FieldType()->Type() == ev_vector ) ) ) {
  1043. //
  1044. // vector
  1045. //
  1046. if ( !strcmp( name, RESULT_STRING ) ) {
  1047. // <RESULT> vector defs don't need the _x, _y and _z components
  1048. assert( scope->Type() == ev_function );
  1049. def->value.stackOffset = scope->value.functionPtr->locals;
  1050. def->initialized = idVarDef::stackVariable;
  1051. scope->value.functionPtr->locals += type->Size();
  1052. } else if ( scope->TypeDef()->Inherits( &type_object ) ) {
  1053. idTypeDef newtype( ev_field, NULL, "float field", 0, &type_float );
  1054. idTypeDef *type = GetType( newtype, true );
  1055. // set the value to the variable's position in the object
  1056. def->value.ptrOffset = scope->TypeDef()->Size();
  1057. // make automatic defs for the vectors elements
  1058. // origin can be accessed as origin_x, origin_y, and origin_z
  1059. sprintf( element, "%s_x", def->Name() );
  1060. def_x = AllocDef( type, element, scope, constant );
  1061. sprintf( element, "%s_y", def->Name() );
  1062. def_y = AllocDef( type, element, scope, constant );
  1063. def_y->value.ptrOffset = def_x->value.ptrOffset + type_float.Size();
  1064. sprintf( element, "%s_z", def->Name() );
  1065. def_z = AllocDef( type, element, scope, constant );
  1066. def_z->value.ptrOffset = def_y->value.ptrOffset + type_float.Size();
  1067. } else {
  1068. // make automatic defs for the vectors elements
  1069. // origin can be accessed as origin_x, origin_y, and origin_z
  1070. sprintf( element, "%s_x", def->Name() );
  1071. def_x = AllocDef( &type_float, element, scope, constant );
  1072. sprintf( element, "%s_y", def->Name() );
  1073. def_y = AllocDef( &type_float, element, scope, constant );
  1074. sprintf( element, "%s_z", def->Name() );
  1075. def_z = AllocDef( &type_float, element, scope, constant );
  1076. // point the vector def to the x coordinate
  1077. def->value = def_x->value;
  1078. def->initialized = def_x->initialized;
  1079. }
  1080. } else if ( scope->TypeDef()->Inherits( &type_object ) ) {
  1081. //
  1082. // object variable
  1083. //
  1084. // set the value to the variable's position in the object
  1085. def->value.ptrOffset = scope->TypeDef()->Size();
  1086. } else if ( scope->Type() == ev_function ) {
  1087. //
  1088. // stack variable
  1089. //
  1090. // since we don't know how many local variables there are,
  1091. // we have to have them go backwards on the stack
  1092. def->value.stackOffset = scope->value.functionPtr->locals;
  1093. def->initialized = idVarDef::stackVariable;
  1094. if ( type->Inherits( &type_object ) ) {
  1095. // objects only have their entity number on the stack, not the entire object
  1096. scope->value.functionPtr->locals += type_object.Size();
  1097. } else {
  1098. scope->value.functionPtr->locals += type->Size();
  1099. }
  1100. } else {
  1101. //
  1102. // global variable
  1103. //
  1104. def->value.bytePtr = &variables[ numVariables ];
  1105. numVariables += def->TypeDef()->Size();
  1106. if ( numVariables > sizeof( variables ) ) {
  1107. throw idCompileError( va( "Exceeded global memory size (%d bytes)", sizeof( variables ) ) );
  1108. }
  1109. memset( def->value.bytePtr, 0, def->TypeDef()->Size() );
  1110. }
  1111. return def;
  1112. }
  1113. /*
  1114. ============
  1115. idProgram::GetDef
  1116. If type is NULL, it will match any type
  1117. ============
  1118. */
  1119. idVarDef *idProgram::GetDef( const idTypeDef *type, const char *name, const idVarDef *scope ) const {
  1120. idVarDef *def;
  1121. idVarDef *bestDef;
  1122. int bestDepth;
  1123. int depth;
  1124. bestDepth = 0;
  1125. bestDef = NULL;
  1126. for( def = GetDefList( name ); def != NULL; def = def->Next() ) {
  1127. if ( def->scope->Type() == ev_namespace ) {
  1128. depth = def->DepthOfScope( scope );
  1129. if ( !depth ) {
  1130. // not in the same namespace
  1131. continue;
  1132. }
  1133. } else if ( def->scope != scope ) {
  1134. // in a different function
  1135. continue;
  1136. } else {
  1137. depth = 1;
  1138. }
  1139. if ( !bestDef || ( depth < bestDepth ) ) {
  1140. bestDepth = depth;
  1141. bestDef = def;
  1142. }
  1143. }
  1144. // see if the name is already in use for another type
  1145. if ( bestDef && type && ( bestDef->TypeDef() != type ) ) {
  1146. throw idCompileError( va( "Type mismatch on redeclaration of %s", name ) );
  1147. }
  1148. return bestDef;
  1149. }
  1150. /*
  1151. ============
  1152. idProgram::FreeDef
  1153. ============
  1154. */
  1155. void idProgram::FreeDef( idVarDef *def, const idVarDef *scope ) {
  1156. idVarDef *e;
  1157. int i;
  1158. if ( def->Type() == ev_vector ) {
  1159. idStr name;
  1160. sprintf( name, "%s_x", def->Name() );
  1161. e = GetDef( NULL, name, scope );
  1162. if ( e ) {
  1163. FreeDef( e, scope );
  1164. }
  1165. sprintf( name, "%s_y", def->Name() );
  1166. e = GetDef( NULL, name, scope );
  1167. if ( e ) {
  1168. FreeDef( e, scope );
  1169. }
  1170. sprintf( name, "%s_z", def->Name() );
  1171. e = GetDef( NULL, name, scope );
  1172. if ( e ) {
  1173. FreeDef( e, scope );
  1174. }
  1175. }
  1176. varDefs.RemoveIndex( def->num );
  1177. for( i = def->num; i < varDefs.Num(); i++ ) {
  1178. varDefs[ i ]->num = i;
  1179. }
  1180. delete def;
  1181. }
  1182. /*
  1183. ============
  1184. idProgram::FindFreeResultDef
  1185. ============
  1186. */
  1187. idVarDef *idProgram::FindFreeResultDef( idTypeDef *type, const char *name, idVarDef *scope, const idVarDef *a, const idVarDef *b ) {
  1188. idVarDef *def;
  1189. for( def = GetDefList( name ); def != NULL; def = def->Next() ) {
  1190. if ( def == a || def == b ) {
  1191. continue;
  1192. }
  1193. if ( def->TypeDef() != type ) {
  1194. continue;
  1195. }
  1196. if ( def->scope != scope ) {
  1197. continue;
  1198. }
  1199. if ( def->numUsers <= 1 ) {
  1200. continue;
  1201. }
  1202. return def;
  1203. }
  1204. return AllocDef( type, name, scope, false );
  1205. }
  1206. /*
  1207. ================
  1208. idProgram::FindFunction
  1209. Searches for the specified function in the currently loaded script. A full namespace should be
  1210. specified if not in the global namespace.
  1211. Returns 0 if function not found.
  1212. Returns >0 if function found.
  1213. ================
  1214. */
  1215. function_t *idProgram::FindFunction( const char *name ) const {
  1216. int start;
  1217. int pos;
  1218. idVarDef *namespaceDef;
  1219. idVarDef *def;
  1220. assert( name );
  1221. idStr fullname = name;
  1222. start = 0;
  1223. namespaceDef = &def_namespace;
  1224. do {
  1225. pos = fullname.Find( "::", true, start );
  1226. if ( pos < 0 ) {
  1227. break;
  1228. }
  1229. idStr namespaceName = fullname.Mid( start, pos - start );
  1230. def = GetDef( NULL, namespaceName, namespaceDef );
  1231. if ( !def ) {
  1232. // couldn't find namespace
  1233. return NULL;
  1234. }
  1235. namespaceDef = def;
  1236. // skip past the ::
  1237. start = pos + 2;
  1238. } while( def->Type() == ev_namespace );
  1239. idStr funcName = fullname.Right( fullname.Length() - start );
  1240. def = GetDef( NULL, funcName, namespaceDef );
  1241. if ( !def ) {
  1242. // couldn't find function
  1243. return NULL;
  1244. }
  1245. if ( ( def->Type() == ev_function ) && ( def->value.functionPtr->eventdef == NULL ) ) {
  1246. return def->value.functionPtr;
  1247. }
  1248. // is not a function, or is an eventdef
  1249. return NULL;
  1250. }
  1251. /*
  1252. ================
  1253. idProgram::FindFunction
  1254. Searches for the specified object function in the currently loaded script.
  1255. Returns 0 if function not found.
  1256. Returns >0 if function found.
  1257. ================
  1258. */
  1259. function_t *idProgram::FindFunction( const char *name, const idTypeDef *type ) const {
  1260. const idVarDef *tdef;
  1261. const idVarDef *def;
  1262. // look for the function
  1263. def = NULL;
  1264. for( tdef = type->def; tdef != &def_object; tdef = tdef->TypeDef()->SuperClass()->def ) {
  1265. def = GetDef( NULL, name, tdef );
  1266. if ( def ) {
  1267. return def->value.functionPtr;
  1268. }
  1269. }
  1270. return NULL;
  1271. }
  1272. /*
  1273. ================
  1274. idProgram::AllocFunction
  1275. ================
  1276. */
  1277. function_t &idProgram::AllocFunction( idVarDef *def ) {
  1278. if ( functions.Num() >= functions.Max() ) {
  1279. throw idCompileError( va( "Exceeded maximum allowed number of functions (%d)", functions.Max() ) );
  1280. }
  1281. // fill in the dfunction
  1282. function_t &func = *functions.Alloc();
  1283. func.eventdef = NULL;
  1284. func.def = def;
  1285. func.type = def->TypeDef();
  1286. func.firstStatement = 0;
  1287. func.numStatements = 0;
  1288. func.parmTotal = 0;
  1289. func.locals = 0;
  1290. func.filenum = filenum;
  1291. func.parmSize.SetGranularity( 1 );
  1292. func.SetName( def->GlobalName() );
  1293. def->SetFunction( &func );
  1294. return func;
  1295. }
  1296. /*
  1297. ================
  1298. idProgram::SetEntity
  1299. ================
  1300. */
  1301. void idProgram::SetEntity( const char *name, idEntity *ent ) {
  1302. idVarDef *def;
  1303. idStr defName( "$" );
  1304. defName += name;
  1305. def = GetDef( &type_entity, defName, &def_namespace );
  1306. if ( def != NULL && ( def->initialized != idVarDef::stackVariable ) ) {
  1307. // 0 is reserved for NULL entity
  1308. if ( !ent ) {
  1309. *def->value.entityNumberPtr = 0;
  1310. } else {
  1311. *def->value.entityNumberPtr = ent->entityNumber + 1;
  1312. }
  1313. }
  1314. }
  1315. /*
  1316. ================
  1317. idProgram::AllocStatement
  1318. ================
  1319. */
  1320. statement_t *idProgram::AllocStatement() {
  1321. if ( statements.Num() >= statements.Max() ) {
  1322. throw idCompileError( va( "Exceeded maximum allowed number of statements (%d)", statements.Max() ) );
  1323. }
  1324. return statements.Alloc();
  1325. }
  1326. /*
  1327. ==============
  1328. idProgram::BeginCompilation
  1329. called before compiling a batch of files, clears the pr struct
  1330. ==============
  1331. */
  1332. void idProgram::BeginCompilation() {
  1333. statement_t *statement;
  1334. FreeData();
  1335. try {
  1336. // make the first statement a return for a "NULL" function
  1337. statement = AllocStatement();
  1338. statement->linenumber = 0;
  1339. statement->file = 0;
  1340. statement->op = OP_RETURN;
  1341. statement->a = NULL;
  1342. statement->b = NULL;
  1343. statement->c = NULL;
  1344. // define NULL
  1345. //AllocDef( &type_void, "<NULL>", &def_namespace, true );
  1346. // define the return def
  1347. returnDef = AllocDef( &type_vector, "<RETURN>", &def_namespace, false );
  1348. // define the return def for strings
  1349. returnStringDef = AllocDef( &type_string, "<RETURN>", &def_namespace, false );
  1350. // define the sys object
  1351. sysDef = AllocDef( &type_void, "sys", &def_namespace, true );
  1352. }
  1353. catch( idCompileError &err ) {
  1354. gameLocal.Error( "%s", err.GetError() );
  1355. }
  1356. }
  1357. /*
  1358. ==============
  1359. idProgram::DisassembleStatement
  1360. ==============
  1361. */
  1362. void idProgram::DisassembleStatement( idFile *file, int instructionPointer ) const {
  1363. opcode_t *op;
  1364. const statement_t *statement;
  1365. statement = &statements[ instructionPointer ];
  1366. op = &idCompiler::opcodes[ statement->op ];
  1367. file->Printf( "%20s(%d):\t%6d: %15s\t", fileList[ statement->file ].c_str(), statement->linenumber, instructionPointer, op->opname );
  1368. if ( statement->a ) {
  1369. file->Printf( "\ta: " );
  1370. statement->a->PrintInfo( file, instructionPointer );
  1371. }
  1372. if ( statement->b ) {
  1373. file->Printf( "\tb: " );
  1374. statement->b->PrintInfo( file, instructionPointer );
  1375. }
  1376. if ( statement->c ) {
  1377. file->Printf( "\tc: " );
  1378. statement->c->PrintInfo( file, instructionPointer );
  1379. }
  1380. file->Printf( "\n" );
  1381. }
  1382. /*
  1383. ==============
  1384. idProgram::Disassemble
  1385. ==============
  1386. */
  1387. void idProgram::Disassemble() const {
  1388. int i;
  1389. int instructionPointer;
  1390. const function_t *func;
  1391. idFile *file;
  1392. file = fileSystem->OpenFileByMode( "script/disasm.txt", FS_WRITE );
  1393. for( i = 0; i < functions.Num(); i++ ) {
  1394. func = &functions[ i ];
  1395. if ( func->eventdef ) {
  1396. // skip eventdefs
  1397. continue;
  1398. }
  1399. file->Printf( "\nfunction %s() %d stack used, %d parms, %d locals {\n", func->Name(), func->locals, func->parmTotal, func->locals - func->parmTotal );
  1400. for( instructionPointer = 0; instructionPointer < func->numStatements; instructionPointer++ ) {
  1401. DisassembleStatement( file, func->firstStatement + instructionPointer );
  1402. }
  1403. file->Printf( "}\n" );
  1404. }
  1405. fileSystem->CloseFile( file );
  1406. }
  1407. /*
  1408. ==============
  1409. idProgram::FinishCompilation
  1410. Called after all files are compiled to check for errors
  1411. ==============
  1412. */
  1413. void idProgram::FinishCompilation() {
  1414. int i;
  1415. top_functions = functions.Num();
  1416. top_statements = statements.Num();
  1417. top_types = types.Num();
  1418. top_defs = varDefs.Num();
  1419. top_files = fileList.Num();
  1420. variableDefaults.Clear();
  1421. variableDefaults.SetNum( numVariables );
  1422. for( i = 0; i < numVariables; i++ ) {
  1423. variableDefaults[ i ] = variables[ i ];
  1424. }
  1425. }
  1426. /*
  1427. ==============
  1428. idProgram::CompileStats
  1429. called after all files are compiled to report memory usage.
  1430. ==============
  1431. */
  1432. void idProgram::CompileStats() {
  1433. int memused;
  1434. int memallocated;
  1435. int numdefs;
  1436. int stringspace;
  1437. int funcMem;
  1438. int i;
  1439. gameLocal.Printf( "---------- Compile stats ----------\n" );
  1440. gameLocal.DPrintf( "Files loaded:\n" );
  1441. stringspace = 0;
  1442. for( i = 0; i < fileList.Num(); i++ ) {
  1443. gameLocal.DPrintf( " %s\n", fileList[ i ].c_str() );
  1444. stringspace += fileList[ i ].Allocated();
  1445. }
  1446. stringspace += fileList.Size();
  1447. numdefs = varDefs.Num();
  1448. memused = varDefs.Num() * sizeof( idVarDef );
  1449. memused += types.Num() * sizeof( idTypeDef );
  1450. memused += stringspace;
  1451. for( i = 0; i < types.Num(); i++ ) {
  1452. memused += types[ i ]->Allocated();
  1453. }
  1454. funcMem = functions.MemoryUsed();
  1455. for( i = 0; i < functions.Num(); i++ ) {
  1456. funcMem += functions[ i ].Allocated();
  1457. }
  1458. memallocated = funcMem + memused + sizeof( idProgram );
  1459. memused += statements.MemoryUsed();
  1460. memused += functions.MemoryUsed(); // name and filename of functions are shared, so no need to include them
  1461. memused += sizeof( variables );
  1462. gameLocal.Printf( "\nMemory usage:\n" );
  1463. gameLocal.Printf( " Strings: %d, %d bytes\n", fileList.Num(), stringspace );
  1464. gameLocal.Printf( " Statements: %d, %d bytes\n", statements.Num(), statements.MemoryUsed() );
  1465. gameLocal.Printf( " Functions: %d, %d bytes\n", functions.Num(), funcMem );
  1466. gameLocal.Printf( " Variables: %d bytes\n", numVariables );
  1467. gameLocal.Printf( " Mem used: %d bytes\n", memused );
  1468. gameLocal.Printf( " Static data: %d bytes\n", sizeof( idProgram ) );
  1469. gameLocal.Printf( " Allocated: %d bytes\n", memallocated );
  1470. gameLocal.Printf( " Thread size: %d bytes\n\n", sizeof( idThread ) );
  1471. }
  1472. /*
  1473. ================
  1474. idProgram::CompileText
  1475. ================
  1476. */
  1477. bool idProgram::CompileText( const char *source, const char *text, bool console ) {
  1478. idCompiler compiler;
  1479. int i;
  1480. idVarDef *def;
  1481. idStr ospath;
  1482. // use a full os path for GetFilenum since it calls OSPathToRelativePath to convert filenames from the parser
  1483. ospath = fileSystem->RelativePathToOSPath( source );
  1484. filenum = GetFilenum( ospath );
  1485. try {
  1486. compiler.CompileFile( text, filename, console );
  1487. // check to make sure all functions prototyped have code
  1488. for( i = 0; i < varDefs.Num(); i++ ) {
  1489. def = varDefs[ i ];
  1490. if ( ( def->Type() == ev_function ) && ( ( def->scope->Type() == ev_namespace ) || def->scope->TypeDef()->Inherits( &type_object ) ) ) {
  1491. if ( !def->value.functionPtr->eventdef && !def->value.functionPtr->firstStatement ) {
  1492. throw idCompileError( va( "function %s was not defined\n", def->GlobalName() ) );
  1493. }
  1494. }
  1495. }
  1496. }
  1497. catch( idCompileError &err ) {
  1498. if ( console ) {
  1499. gameLocal.Printf( "%s\n", err.GetError() );
  1500. return false;
  1501. } else {
  1502. gameLocal.Error( "%s\n", err.GetError() );
  1503. }
  1504. };
  1505. if ( !console ) {
  1506. CompileStats();
  1507. }
  1508. return true;
  1509. }
  1510. /*
  1511. ================
  1512. idProgram::CompileFunction
  1513. ================
  1514. */
  1515. const function_t *idProgram::CompileFunction( const char *functionName, const char *text ) {
  1516. bool result;
  1517. result = CompileText( functionName, text, false );
  1518. if ( g_disasm.GetBool() ) {
  1519. Disassemble();
  1520. }
  1521. if ( !result ) {
  1522. gameLocal.Error( "Compile failed." );
  1523. }
  1524. return FindFunction( functionName );
  1525. }
  1526. /*
  1527. ================
  1528. idProgram::CompileFile
  1529. ================
  1530. */
  1531. void idProgram::CompileFile( const char *filename ) {
  1532. char *src;
  1533. bool result;
  1534. if ( fileSystem->ReadFile( filename, ( void ** )&src, NULL ) < 0 ) {
  1535. gameLocal.Error( "Couldn't load %s\n", filename );
  1536. }
  1537. result = CompileText( filename, src, false );
  1538. fileSystem->FreeFile( src );
  1539. if ( g_disasm.GetBool() ) {
  1540. Disassemble();
  1541. }
  1542. if ( !result ) {
  1543. gameLocal.Error( "Compile failed in file %s.", filename );
  1544. }
  1545. }
  1546. /*
  1547. ================
  1548. idProgram::FreeData
  1549. ================
  1550. */
  1551. void idProgram::FreeData() {
  1552. int i;
  1553. // free the defs
  1554. varDefs.DeleteContents( true );
  1555. varDefNames.DeleteContents( true );
  1556. varDefNameHash.Free();
  1557. returnDef = NULL;
  1558. returnStringDef = NULL;
  1559. sysDef = NULL;
  1560. // free any special types we've created
  1561. types.DeleteContents( true );
  1562. typesHash.Free();
  1563. filenum = 0;
  1564. numVariables = 0;
  1565. memset( variables, 0, sizeof( variables ) );
  1566. // clear all the strings in the functions so that it doesn't look like we're leaking memory.
  1567. for( i = 0; i < functions.Num(); i++ ) {
  1568. functions[ i ].Clear();
  1569. }
  1570. filename.Clear();
  1571. fileList.Clear();
  1572. statements.Clear();
  1573. functions.Clear();
  1574. top_functions = 0;
  1575. top_statements = 0;
  1576. top_types = 0;
  1577. top_defs = 0;
  1578. top_files = 0;
  1579. filename = "";
  1580. }
  1581. /*
  1582. ================
  1583. idProgram::Startup
  1584. ================
  1585. */
  1586. void idProgram::Startup( const char *defaultScript ) {
  1587. gameLocal.Printf( "Initializing scripts\n" );
  1588. // make sure all data is freed up
  1589. idThread::Restart();
  1590. // get ready for loading scripts
  1591. BeginCompilation();
  1592. // load the default script
  1593. if ( defaultScript && *defaultScript ) {
  1594. CompileFile( defaultScript );
  1595. }
  1596. FinishCompilation();
  1597. }
  1598. /*
  1599. ================
  1600. idProgram::Save
  1601. ================
  1602. */
  1603. void idProgram::Save( idSaveGame *savefile ) const {
  1604. int i;
  1605. int currentFileNum = top_files;
  1606. savefile->WriteInt( (fileList.Num() - currentFileNum) );
  1607. while ( currentFileNum < fileList.Num() ) {
  1608. savefile->WriteString( fileList[ currentFileNum ] );
  1609. currentFileNum++;
  1610. }
  1611. for ( i = 0; i < variableDefaults.Num(); i++ ) {
  1612. if ( variables[i] != variableDefaults[i] ) {
  1613. savefile->WriteInt( i );
  1614. savefile->WriteByte( variables[i] );
  1615. }
  1616. }
  1617. // Mark the end of the diff with default variables with -1
  1618. savefile->WriteInt( -1 );
  1619. savefile->WriteInt( numVariables );
  1620. for ( i = variableDefaults.Num(); i < numVariables; i++ ) {
  1621. savefile->WriteByte( variables[i] );
  1622. }
  1623. int checksum = CalculateChecksum();
  1624. savefile->WriteInt( checksum );
  1625. }
  1626. /*
  1627. ================
  1628. idProgram::Restore
  1629. ================
  1630. */
  1631. bool idProgram::Restore( idRestoreGame *savefile ) {
  1632. int i, num, index;
  1633. bool result = true;
  1634. idStr scriptname;
  1635. savefile->ReadInt( num );
  1636. for ( i = 0; i < num; i++ ) {
  1637. savefile->ReadString( scriptname );
  1638. CompileFile( scriptname );
  1639. }
  1640. savefile->ReadInt( index );
  1641. while( index >= 0 ) {
  1642. savefile->ReadByte( variables[index] );
  1643. savefile->ReadInt( index );
  1644. }
  1645. savefile->ReadInt( num );
  1646. for ( i = variableDefaults.Num(); i < num; i++ ) {
  1647. savefile->ReadByte( variables[i] );
  1648. }
  1649. int saved_checksum, checksum;
  1650. savefile->ReadInt( saved_checksum );
  1651. checksum = CalculateChecksum();
  1652. if ( saved_checksum != checksum ) {
  1653. result = false;
  1654. }
  1655. return result;
  1656. }
  1657. /*
  1658. ================
  1659. idProgram::CalculateChecksum
  1660. ================
  1661. */
  1662. int idProgram::CalculateChecksum() const {
  1663. int i, result;
  1664. typedef struct {
  1665. unsigned short op;
  1666. int a;
  1667. int b;
  1668. int c;
  1669. unsigned short linenumber;
  1670. unsigned short file;
  1671. } statementBlock_t;
  1672. statementBlock_t *statementList = new (TAG_SCRIPT) statementBlock_t[ statements.Num() ];
  1673. memset( statementList, 0, ( sizeof(statementBlock_t) * statements.Num() ) );
  1674. // Copy info into new list, using the variable numbers instead of a pointer to the variable
  1675. for( i = 0; i < statements.Num(); i++ ) {
  1676. statementList[i].op = statements[i].op;
  1677. if ( statements[i].a ) {
  1678. statementList[i].a = statements[i].a->num;
  1679. } else {
  1680. statementList[i].a = -1;
  1681. }
  1682. if ( statements[i].b ) {
  1683. statementList[i].b = statements[i].b->num;
  1684. } else {
  1685. statementList[i].b = -1;
  1686. }
  1687. if ( statements[i].c ) {
  1688. statementList[i].c = statements[i].c->num;
  1689. } else {
  1690. statementList[i].c = -1;
  1691. }
  1692. statementList[i].linenumber = statements[i].linenumber;
  1693. statementList[i].file = statements[i].file;
  1694. }
  1695. result = MD4_BlockChecksum( statementList, ( sizeof(statementBlock_t) * statements.Num() ) );
  1696. delete [] statementList;
  1697. return result;
  1698. }
  1699. /*
  1700. ==============
  1701. idProgram::Restart
  1702. Restores all variables to their initial value
  1703. ==============
  1704. */
  1705. void idProgram::Restart() {
  1706. int i;
  1707. idThread::Restart();
  1708. //
  1709. // since there may have been a script loaded by the map or the user may
  1710. // have typed "script" from the console, free up any types and vardefs that
  1711. // have been allocated after the initial startup
  1712. //
  1713. for( i = top_types; i < types.Num(); i++ ) {
  1714. delete types[ i ];
  1715. }
  1716. types.SetNum( top_types );
  1717. typesHash.Free();
  1718. for( i = 0; i < types.Num(); i++ ) {
  1719. typesHash.Add( idStr::Hash( types[i]->Name() ), i );
  1720. }
  1721. for( i = top_defs; i < varDefs.Num(); i++ ) {
  1722. delete varDefs[ i ];
  1723. }
  1724. varDefs.SetNum( top_defs );
  1725. for( i = top_functions; i < functions.Num(); i++ ) {
  1726. functions[ i ].Clear();
  1727. }
  1728. functions.SetNum( top_functions );
  1729. statements.SetNum( top_statements );
  1730. fileList.SetNum( top_files );
  1731. filename.Clear();
  1732. // reset the variables to their default values
  1733. numVariables = variableDefaults.Num();
  1734. for( i = 0; i < numVariables; i++ ) {
  1735. variables[ i ] = variableDefaults[ i ];
  1736. }
  1737. }
  1738. /*
  1739. ================
  1740. idProgram::GetFilenum
  1741. ================
  1742. */
  1743. int idProgram::GetFilenum( const char *name ) {
  1744. if ( filename == name ) {
  1745. return filenum;
  1746. }
  1747. idStr strippedName;
  1748. strippedName = fileSystem->OSPathToRelativePath( name );
  1749. if ( !strippedName.Length() ) {
  1750. // not off the base path so just use the full path
  1751. filenum = fileList.AddUnique( name );
  1752. } else {
  1753. filenum = fileList.AddUnique( strippedName );
  1754. }
  1755. // save the unstripped name so that we don't have to strip the incoming name every time we call GetFilenum
  1756. filename = name;
  1757. return filenum;
  1758. }
  1759. /*
  1760. ================
  1761. idProgram::idProgram
  1762. ================
  1763. */
  1764. idProgram::idProgram() {
  1765. varDefs.SetGranularity( 256 );
  1766. varDefNames.SetGranularity( 256 );
  1767. FreeData();
  1768. }
  1769. /*
  1770. ================
  1771. idProgram::~idProgram
  1772. ================
  1773. */
  1774. idProgram::~idProgram() {
  1775. FreeData();
  1776. }
  1777. /*
  1778. ================
  1779. idProgram::ReturnEntity
  1780. ================
  1781. */
  1782. void idProgram::ReturnEntity( idEntity *ent ) {
  1783. if ( ent ) {
  1784. *returnDef->value.entityNumberPtr = ent->entityNumber + 1;
  1785. } else {
  1786. *returnDef->value.entityNumberPtr = 0;
  1787. }
  1788. }