DeclManager.cpp 69 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433
  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. #include "../idlib/precompiled.h"
  21. #pragma hdrstop
  22. /*
  23. GUIs and script remain separately parsed
  24. Following a parse, all referenced media (and other decls) will have been touched.
  25. sinTable and cosTable are required for the rotate material keyword to function
  26. A new FindType on a purged decl will cause it to be reloaded, but a stale pointer to a purged
  27. decl will look like a defaulted decl.
  28. Moving a decl from one file to another will not be handled correctly by a reload, the material
  29. will be defaulted.
  30. NULL or empty decl names will always return NULL
  31. Should probably make a default decl for this
  32. Decls are initially created without a textSource
  33. A parse without textSource set should always just call MakeDefault()
  34. A parse that has an error should internally call MakeDefault()
  35. A purge does nothing to a defaulted decl
  36. Should we have a "purged" media state separate from the "defaulted" media state?
  37. reloading over a decl name that was defaulted
  38. reloading over a decl name that was valid
  39. missing reload over a previously explicit definition
  40. */
  41. #define USE_COMPRESSED_DECLS
  42. //#define GET_HUFFMAN_FREQUENCIES
  43. class idDeclType {
  44. public:
  45. idStr typeName;
  46. declType_t type;
  47. idDecl * (*allocator)();
  48. };
  49. class idDeclFolder {
  50. public:
  51. idStr folder;
  52. idStr extension;
  53. declType_t defaultType;
  54. };
  55. class idDeclFile;
  56. class idDeclLocal : public idDeclBase {
  57. friend class idDeclFile;
  58. friend class idDeclManagerLocal;
  59. public:
  60. idDeclLocal();
  61. virtual ~idDeclLocal() {};
  62. virtual const char * GetName() const;
  63. virtual declType_t GetType() const;
  64. virtual declState_t GetState() const;
  65. virtual bool IsImplicit() const;
  66. virtual bool IsValid() const;
  67. virtual void Invalidate();
  68. virtual void Reload();
  69. virtual void EnsureNotPurged();
  70. virtual int Index() const;
  71. virtual int GetLineNum() const;
  72. virtual const char * GetFileName() const;
  73. virtual size_t Size() const;
  74. virtual void GetText( char *text ) const;
  75. virtual int GetTextLength() const;
  76. virtual void SetText( const char *text );
  77. virtual bool ReplaceSourceFileText();
  78. virtual bool SourceFileChanged() const;
  79. virtual void MakeDefault();
  80. virtual bool EverReferenced() const;
  81. protected:
  82. virtual bool SetDefaultText();
  83. virtual const char * DefaultDefinition() const;
  84. virtual bool Parse( const char *text, const int textLength, bool allowBinaryVersion );
  85. virtual void FreeData();
  86. virtual void List() const;
  87. virtual void Print() const;
  88. protected:
  89. void AllocateSelf();
  90. // Parses the decl definition.
  91. // After calling parse, a decl will be guaranteed usable.
  92. void ParseLocal();
  93. // Does a MakeDefualt, but flags the decl so that it
  94. // will Parse() the next time the decl is found.
  95. void Purge();
  96. // Set textSource possible with compression.
  97. void SetTextLocal( const char *text, const int length );
  98. private:
  99. idDecl * self;
  100. idStr name; // name of the decl
  101. char * textSource; // decl text definition
  102. int textLength; // length of textSource
  103. int compressedLength; // compressed length
  104. idDeclFile * sourceFile; // source file in which the decl was defined
  105. int sourceTextOffset; // offset in source file to decl text
  106. int sourceTextLength; // length of decl text in source file
  107. int sourceLine; // this is where the actual declaration token starts
  108. int checksum; // checksum of the decl text
  109. declType_t type; // decl type
  110. declState_t declState; // decl state
  111. int index; // index in the per-type list
  112. bool parsedOutsideLevelLoad; // these decls will never be purged
  113. bool everReferenced; // set to true if the decl was ever used
  114. bool referencedThisLevel; // set to true when the decl is used for the current level
  115. bool redefinedInReload; // used during file reloading to make sure a decl that has
  116. // its source removed will be defaulted
  117. idDeclLocal * nextInFile; // next decl in the decl file
  118. };
  119. class idDeclFile {
  120. public:
  121. idDeclFile();
  122. idDeclFile( const char *fileName, declType_t defaultType );
  123. void Reload( bool force );
  124. int LoadAndParse();
  125. public:
  126. idStr fileName;
  127. declType_t defaultType;
  128. ID_TIME_T timestamp;
  129. int checksum;
  130. int fileSize;
  131. int numLines;
  132. idDeclLocal * decls;
  133. };
  134. class idDeclManagerLocal : public idDeclManager {
  135. friend class idDeclLocal;
  136. public:
  137. virtual void Init();
  138. virtual void Init2();
  139. virtual void Shutdown();
  140. virtual void Reload( bool force );
  141. virtual void BeginLevelLoad();
  142. virtual void EndLevelLoad();
  143. virtual void RegisterDeclType( const char *typeName, declType_t type, idDecl *(*allocator)() );
  144. virtual void RegisterDeclFolder( const char *folder, const char *extension, declType_t defaultType );
  145. virtual int GetChecksum() const;
  146. virtual int GetNumDeclTypes() const;
  147. virtual int GetNumDecls( declType_t type );
  148. virtual const char * GetDeclNameFromType( declType_t type ) const;
  149. virtual declType_t GetDeclTypeFromName( const char *typeName ) const;
  150. virtual const idDecl * FindType( declType_t type, const char *name, bool makeDefault = true );
  151. virtual const idDecl * DeclByIndex( declType_t type, int index, bool forceParse = true );
  152. virtual const idDecl* FindDeclWithoutParsing( declType_t type, const char *name, bool makeDefault = true );
  153. virtual void ReloadFile( const char* filename, bool force );
  154. virtual void ListType( const idCmdArgs &args, declType_t type );
  155. virtual void PrintType( const idCmdArgs &args, declType_t type );
  156. virtual idDecl * CreateNewDecl( declType_t type, const char *name, const char *fileName );
  157. //BSM Added for the material editors rename capabilities
  158. virtual bool RenameDecl( declType_t type, const char* oldName, const char* newName );
  159. virtual void MediaPrint( VERIFY_FORMAT_STRING const char *fmt, ... );
  160. virtual void WritePrecacheCommands( idFile *f );
  161. virtual const idMaterial * FindMaterial( const char *name, bool makeDefault = true );
  162. virtual const idDeclSkin * FindSkin( const char *name, bool makeDefault = true );
  163. virtual const idSoundShader * FindSound( const char *name, bool makeDefault = true );
  164. virtual const idMaterial * MaterialByIndex( int index, bool forceParse = true );
  165. virtual const idDeclSkin * SkinByIndex( int index, bool forceParse = true );
  166. virtual const idSoundShader * SoundByIndex( int index, bool forceParse = true );
  167. virtual void Touch( const idDecl * decl );
  168. public:
  169. static void MakeNameCanonical( const char *name, char *result, int maxLength );
  170. idDeclLocal * FindTypeWithoutParsing( declType_t type, const char *name, bool makeDefault = true );
  171. idDeclType * GetDeclType( int type ) const { return declTypes[type]; }
  172. const idDeclFile * GetImplicitDeclFile() const { return &implicitDecls; }
  173. void ConvertPDAsToStrings( const idCmdArgs &args );
  174. private:
  175. idSysMutex mutex;
  176. idList<idDeclType *, TAG_IDLIB_LIST_DECL> declTypes;
  177. idList<idDeclFolder *, TAG_IDLIB_LIST_DECL> declFolders;
  178. idList<idDeclFile *, TAG_IDLIB_LIST_DECL> loadedFiles;
  179. idHashIndex hashTables[DECL_MAX_TYPES];
  180. idList<idDeclLocal *, TAG_IDLIB_LIST_DECL> linearLists[DECL_MAX_TYPES];
  181. idDeclFile implicitDecls; // this holds all the decls that were created because explicit
  182. // text definitions were not found. Decls that became default
  183. // because of a parse error are not in this list.
  184. int checksum; // checksum of all loaded decl text
  185. int indent; // for MediaPrint
  186. bool insideLevelLoad;
  187. static idCVar decl_show;
  188. private:
  189. static void ListDecls_f( const idCmdArgs &args );
  190. static void ReloadDecls_f( const idCmdArgs &args );
  191. static void TouchDecl_f( const idCmdArgs &args );
  192. };
  193. idCVar idDeclManagerLocal::decl_show( "decl_show", "0", CVAR_SYSTEM, "set to 1 to print parses, 2 to also print references", 0, 2, idCmdSystem::ArgCompletion_Integer<0,2> );
  194. idDeclManagerLocal declManagerLocal;
  195. idDeclManager * declManager = &declManagerLocal;
  196. /*
  197. ====================================================================================
  198. decl text huffman compression
  199. ====================================================================================
  200. */
  201. const int MAX_HUFFMAN_SYMBOLS = 256;
  202. typedef struct huffmanNode_s {
  203. int symbol;
  204. int frequency;
  205. struct huffmanNode_s * next;
  206. struct huffmanNode_s * children[2];
  207. } huffmanNode_t;
  208. typedef struct huffmanCode_s {
  209. unsigned long bits[8];
  210. int numBits;
  211. } huffmanCode_t;
  212. // compression ratio = 64%
  213. static int huffmanFrequencies[] = {
  214. 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
  215. 0x00000001, 0x00078fb6, 0x000352a7, 0x00000002, 0x00000001, 0x0002795e, 0x00000001, 0x00000001,
  216. 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
  217. 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
  218. 0x00049600, 0x000000dd, 0x00018732, 0x0000005a, 0x00000007, 0x00000092, 0x0000000a, 0x00000919,
  219. 0x00002dcf, 0x00002dda, 0x00004dfc, 0x0000039a, 0x000058be, 0x00002d13, 0x00014d8c, 0x00023c60,
  220. 0x0002ddb0, 0x0000d1fc, 0x000078c4, 0x00003ec7, 0x00003113, 0x00006b59, 0x00002499, 0x0000184a,
  221. 0x0000250b, 0x00004e38, 0x000001ca, 0x00000011, 0x00000020, 0x000023da, 0x00000012, 0x00000091,
  222. 0x0000000b, 0x00000b14, 0x0000035d, 0x0000137e, 0x000020c9, 0x00000e11, 0x000004b4, 0x00000737,
  223. 0x000006b8, 0x00001110, 0x000006b3, 0x000000fe, 0x00000f02, 0x00000d73, 0x000005f6, 0x00000be4,
  224. 0x00000d86, 0x0000014d, 0x00000d89, 0x0000129b, 0x00000db3, 0x0000015a, 0x00000167, 0x00000375,
  225. 0x00000028, 0x00000112, 0x00000018, 0x00000678, 0x0000081a, 0x00000677, 0x00000003, 0x00018112,
  226. 0x00000001, 0x000441ee, 0x000124b0, 0x0001fa3f, 0x00026125, 0x0005a411, 0x0000e50f, 0x00011820,
  227. 0x00010f13, 0x0002e723, 0x00003518, 0x00005738, 0x0002cc26, 0x0002a9b7, 0x0002db81, 0x0003b5fa,
  228. 0x000185d2, 0x00001299, 0x00030773, 0x0003920d, 0x000411cd, 0x00018751, 0x00005fbd, 0x000099b0,
  229. 0x00009242, 0x00007cf2, 0x00002809, 0x00005a1d, 0x00000001, 0x00005a1d, 0x00000001, 0x00000001,
  230. 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
  231. 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
  232. 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
  233. 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
  234. 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
  235. 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
  236. 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
  237. 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
  238. 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
  239. 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
  240. 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
  241. 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
  242. 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
  243. 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
  244. 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
  245. 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
  246. };
  247. static huffmanCode_t huffmanCodes[MAX_HUFFMAN_SYMBOLS];
  248. static huffmanNode_t *huffmanTree = NULL;
  249. static int totalUncompressedLength = 0;
  250. static int totalCompressedLength = 0;
  251. static int maxHuffmanBits = 0;
  252. /*
  253. ================
  254. ClearHuffmanFrequencies
  255. ================
  256. */
  257. void ClearHuffmanFrequencies() {
  258. int i;
  259. for( i = 0; i < MAX_HUFFMAN_SYMBOLS; i++ ) {
  260. huffmanFrequencies[i] = 1;
  261. }
  262. }
  263. /*
  264. ================
  265. InsertHuffmanNode
  266. ================
  267. */
  268. huffmanNode_t *InsertHuffmanNode( huffmanNode_t *firstNode, huffmanNode_t *node ) {
  269. huffmanNode_t *n, *lastNode;
  270. lastNode = NULL;
  271. for ( n = firstNode; n; n = n->next ) {
  272. if ( node->frequency <= n->frequency ) {
  273. break;
  274. }
  275. lastNode = n;
  276. }
  277. if ( lastNode ) {
  278. node->next = lastNode->next;
  279. lastNode->next = node;
  280. } else {
  281. node->next = firstNode;
  282. firstNode = node;
  283. }
  284. return firstNode;
  285. }
  286. /*
  287. ================
  288. BuildHuffmanCode_r
  289. ================
  290. */
  291. void BuildHuffmanCode_r( huffmanNode_t *node, huffmanCode_t code, huffmanCode_t codes[MAX_HUFFMAN_SYMBOLS] ) {
  292. if ( node->symbol == -1 ) {
  293. huffmanCode_t newCode = code;
  294. assert( code.numBits < sizeof( codes[0].bits ) * 8 );
  295. newCode.numBits++;
  296. if ( code.numBits > maxHuffmanBits ) {
  297. maxHuffmanBits = newCode.numBits;
  298. }
  299. BuildHuffmanCode_r( node->children[0], newCode, codes );
  300. newCode.bits[code.numBits >> 5] |= 1 << ( code.numBits & 31 );
  301. BuildHuffmanCode_r( node->children[1], newCode, codes );
  302. } else {
  303. assert( code.numBits <= sizeof( codes[0].bits ) * 8 );
  304. codes[node->symbol] = code;
  305. }
  306. }
  307. /*
  308. ================
  309. FreeHuffmanTree_r
  310. ================
  311. */
  312. void FreeHuffmanTree_r( huffmanNode_t *node ) {
  313. if ( node->symbol == -1 ) {
  314. FreeHuffmanTree_r( node->children[0] );
  315. FreeHuffmanTree_r( node->children[1] );
  316. }
  317. delete node;
  318. }
  319. /*
  320. ================
  321. HuffmanHeight_r
  322. ================
  323. */
  324. int HuffmanHeight_r( huffmanNode_t *node ) {
  325. if ( node == NULL ) {
  326. return -1;
  327. }
  328. int left = HuffmanHeight_r( node->children[0] );
  329. int right = HuffmanHeight_r( node->children[1] );
  330. if ( left > right ) {
  331. return left + 1;
  332. }
  333. return right + 1;
  334. }
  335. /*
  336. ================
  337. SetupHuffman
  338. ================
  339. */
  340. void SetupHuffman() {
  341. int i, height;
  342. huffmanNode_t *firstNode, *node;
  343. huffmanCode_t code;
  344. firstNode = NULL;
  345. for( i = 0; i < MAX_HUFFMAN_SYMBOLS; i++ ) {
  346. node = new (TAG_DECL) huffmanNode_t;
  347. node->symbol = i;
  348. node->frequency = huffmanFrequencies[i];
  349. node->next = NULL;
  350. node->children[0] = NULL;
  351. node->children[1] = NULL;
  352. firstNode = InsertHuffmanNode( firstNode, node );
  353. }
  354. for( i = 1; i < MAX_HUFFMAN_SYMBOLS; i++ ) {
  355. node = new (TAG_DECL) huffmanNode_t;
  356. node->symbol = -1;
  357. node->frequency = firstNode->frequency + firstNode->next->frequency;
  358. node->next = NULL;
  359. node->children[0] = firstNode;
  360. node->children[1] = firstNode->next;
  361. firstNode = InsertHuffmanNode( firstNode->next->next, node );
  362. }
  363. maxHuffmanBits = 0;
  364. memset( &code, 0, sizeof( code ) );
  365. BuildHuffmanCode_r( firstNode, code, huffmanCodes );
  366. huffmanTree = firstNode;
  367. height = HuffmanHeight_r( firstNode );
  368. assert( maxHuffmanBits == height );
  369. }
  370. /*
  371. ================
  372. ShutdownHuffman
  373. ================
  374. */
  375. void ShutdownHuffman() {
  376. if ( huffmanTree ) {
  377. FreeHuffmanTree_r( huffmanTree );
  378. }
  379. }
  380. /*
  381. ================
  382. HuffmanCompressText
  383. ================
  384. */
  385. int HuffmanCompressText( const char *text, int textLength, byte *compressed, int maxCompressedSize ) {
  386. int i, j;
  387. idBitMsg msg;
  388. totalUncompressedLength += textLength;
  389. msg.InitWrite( compressed, maxCompressedSize );
  390. msg.BeginWriting();
  391. for ( i = 0; i < textLength; i++ ) {
  392. const huffmanCode_t &code = huffmanCodes[(unsigned char)text[i]];
  393. for ( j = 0; j < ( code.numBits >> 5 ); j++ ) {
  394. msg.WriteBits( code.bits[j], 32 );
  395. }
  396. if ( code.numBits & 31 ) {
  397. msg.WriteBits( code.bits[j], code.numBits & 31 );
  398. }
  399. }
  400. totalCompressedLength += msg.GetSize();
  401. return msg.GetSize();
  402. }
  403. /*
  404. ================
  405. HuffmanDecompressText
  406. ================
  407. */
  408. int HuffmanDecompressText( char *text, int textLength, const byte *compressed, int compressedSize ) {
  409. int i, bit;
  410. idBitMsg msg;
  411. huffmanNode_t *node;
  412. msg.InitRead( compressed, compressedSize );
  413. msg.SetSize( compressedSize );
  414. msg.BeginReading();
  415. for ( i = 0; i < textLength; i++ ) {
  416. node = huffmanTree;
  417. do {
  418. bit = msg.ReadBits( 1 );
  419. node = node->children[bit];
  420. } while( node->symbol == -1 );
  421. text[i] = node->symbol;
  422. }
  423. text[i] = '\0';
  424. return msg.GetReadCount();
  425. }
  426. /*
  427. ================
  428. ListHuffmanFrequencies_f
  429. ================
  430. */
  431. void ListHuffmanFrequencies_f( const idCmdArgs &args ) {
  432. int i;
  433. float compression;
  434. compression = !totalUncompressedLength ? 100 : 100 * totalCompressedLength / totalUncompressedLength;
  435. common->Printf( "// compression ratio = %d%%\n", (int)compression );
  436. common->Printf( "static int huffmanFrequencies[] = {\n" );
  437. for( i = 0; i < MAX_HUFFMAN_SYMBOLS; i += 8 ) {
  438. common->Printf( "\t0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x,\n",
  439. huffmanFrequencies[i+0], huffmanFrequencies[i+1],
  440. huffmanFrequencies[i+2], huffmanFrequencies[i+3],
  441. huffmanFrequencies[i+4], huffmanFrequencies[i+5],
  442. huffmanFrequencies[i+6], huffmanFrequencies[i+7]);
  443. }
  444. common->Printf( "}\n" );
  445. }
  446. void ConvertPDAsToStrings_f( const idCmdArgs &args ) {
  447. declManagerLocal.ConvertPDAsToStrings( args );
  448. }
  449. /*
  450. ====================================================================================
  451. idDeclFile
  452. ====================================================================================
  453. */
  454. /*
  455. ================
  456. idDeclFile::idDeclFile
  457. ================
  458. */
  459. idDeclFile::idDeclFile( const char *fileName, declType_t defaultType ) {
  460. this->fileName = fileName;
  461. this->defaultType = defaultType;
  462. this->timestamp = 0;
  463. this->checksum = 0;
  464. this->fileSize = 0;
  465. this->numLines = 0;
  466. this->decls = NULL;
  467. }
  468. /*
  469. ================
  470. idDeclFile::idDeclFile
  471. ================
  472. */
  473. idDeclFile::idDeclFile() {
  474. this->fileName = "<implicit file>";
  475. this->defaultType = DECL_MAX_TYPES;
  476. this->timestamp = 0;
  477. this->checksum = 0;
  478. this->fileSize = 0;
  479. this->numLines = 0;
  480. this->decls = NULL;
  481. }
  482. /*
  483. ================
  484. idDeclFile::Reload
  485. ForceReload will cause it to reload even if the timestamp hasn't changed
  486. ================
  487. */
  488. void idDeclFile::Reload( bool force ) {
  489. // check for an unchanged timestamp
  490. if ( !force && timestamp != 0 ) {
  491. ID_TIME_T testTimeStamp;
  492. fileSystem->ReadFile( fileName, NULL, &testTimeStamp );
  493. if ( testTimeStamp == timestamp ) {
  494. return;
  495. }
  496. }
  497. // parse the text
  498. LoadAndParse();
  499. }
  500. /*
  501. ================
  502. idDeclFile::LoadAndParse
  503. This is used during both the initial load, and any reloads
  504. ================
  505. */
  506. int c_savedMemory = 0;
  507. int idDeclFile::LoadAndParse() {
  508. int i, numTypes;
  509. idLexer src;
  510. idToken token;
  511. int startMarker;
  512. char * buffer;
  513. int length, size;
  514. int sourceLine;
  515. idStr name;
  516. idDeclLocal *newDecl;
  517. bool reparse;
  518. // load the text
  519. common->DPrintf( "...loading '%s'\n", fileName.c_str() );
  520. length = fileSystem->ReadFile( fileName, (void **)&buffer, &timestamp );
  521. if ( length == -1 ) {
  522. common->FatalError( "couldn't load %s", fileName.c_str() );
  523. return 0;
  524. }
  525. if ( !src.LoadMemory( buffer, length, fileName ) ) {
  526. common->Error( "Couldn't parse %s", fileName.c_str() );
  527. Mem_Free( buffer );
  528. return 0;
  529. }
  530. // mark all the defs that were from the last reload of this file
  531. for ( idDeclLocal *decl = decls; decl; decl = decl->nextInFile ) {
  532. decl->redefinedInReload = false;
  533. }
  534. src.SetFlags( DECL_LEXER_FLAGS );
  535. checksum = MD5_BlockChecksum( buffer, length );
  536. fileSize = length;
  537. // scan through, identifying each individual declaration
  538. while( 1 ) {
  539. startMarker = src.GetFileOffset();
  540. sourceLine = src.GetLineNum();
  541. // parse the decl type name
  542. if ( !src.ReadToken( &token ) ) {
  543. break;
  544. }
  545. declType_t identifiedType = DECL_MAX_TYPES;
  546. // get the decl type from the type name
  547. numTypes = declManagerLocal.GetNumDeclTypes();
  548. for ( i = 0; i < numTypes; i++ ) {
  549. idDeclType *typeInfo = declManagerLocal.GetDeclType( i );
  550. if ( typeInfo != NULL && typeInfo->typeName.Icmp( token ) == 0 ) {
  551. identifiedType = (declType_t) typeInfo->type;
  552. break;
  553. }
  554. }
  555. if ( i >= numTypes ) {
  556. if ( token.Icmp( "{" ) == 0 ) {
  557. // if we ever see an open brace, we somehow missed the [type] <name> prefix
  558. src.Warning( "Missing decl name" );
  559. src.SkipBracedSection( false );
  560. continue;
  561. } else {
  562. if ( defaultType == DECL_MAX_TYPES ) {
  563. src.Warning( "No type" );
  564. continue;
  565. }
  566. src.UnreadToken( &token );
  567. // use the default type
  568. identifiedType = defaultType;
  569. }
  570. }
  571. // now parse the name
  572. if ( !src.ReadToken( &token ) ) {
  573. src.Warning( "Type without definition at end of file" );
  574. break;
  575. }
  576. if ( !token.Icmp( "{" ) ) {
  577. // if we ever see an open brace, we somehow missed the [type] <name> prefix
  578. src.Warning( "Missing decl name" );
  579. src.SkipBracedSection( false );
  580. continue;
  581. }
  582. // FIXME: export decls are only used by the model exporter, they are skipped here for now
  583. if ( identifiedType == DECL_MODELEXPORT ) {
  584. src.SkipBracedSection();
  585. continue;
  586. }
  587. name = token;
  588. // make sure there's a '{'
  589. if ( !src.ReadToken( &token ) ) {
  590. src.Warning( "Type without definition at end of file" );
  591. break;
  592. }
  593. if ( token != "{" ) {
  594. src.Warning( "Expecting '{' but found '%s'", token.c_str() );
  595. continue;
  596. }
  597. src.UnreadToken( &token );
  598. // now take everything until a matched closing brace
  599. src.SkipBracedSection();
  600. size = src.GetFileOffset() - startMarker;
  601. // look it up, possibly getting a newly created default decl
  602. reparse = false;
  603. newDecl = declManagerLocal.FindTypeWithoutParsing( identifiedType, name, false );
  604. if ( newDecl ) {
  605. // update the existing copy
  606. if ( newDecl->sourceFile != this || newDecl->redefinedInReload ) {
  607. src.Warning( "%s '%s' previously defined at %s:%i", declManagerLocal.GetDeclNameFromType( identifiedType ),
  608. name.c_str(), newDecl->sourceFile->fileName.c_str(), newDecl->sourceLine );
  609. continue;
  610. }
  611. if ( newDecl->declState != DS_UNPARSED ) {
  612. reparse = true;
  613. }
  614. } else {
  615. // allow it to be created as a default, then add it to the per-file list
  616. newDecl = declManagerLocal.FindTypeWithoutParsing( identifiedType, name, true );
  617. newDecl->nextInFile = this->decls;
  618. this->decls = newDecl;
  619. }
  620. newDecl->redefinedInReload = true;
  621. if ( newDecl->textSource ) {
  622. Mem_Free( newDecl->textSource );
  623. newDecl->textSource = NULL;
  624. }
  625. newDecl->SetTextLocal( buffer + startMarker, size );
  626. newDecl->sourceFile = this;
  627. newDecl->sourceTextOffset = startMarker;
  628. newDecl->sourceTextLength = size;
  629. newDecl->sourceLine = sourceLine;
  630. newDecl->declState = DS_UNPARSED;
  631. // if it is currently in use, reparse it immedaitely
  632. if ( reparse ) {
  633. newDecl->ParseLocal();
  634. }
  635. }
  636. numLines = src.GetLineNum();
  637. Mem_Free( buffer );
  638. // any defs that weren't redefinedInReload should now be defaulted
  639. for ( idDeclLocal *decl = decls ; decl ; decl = decl->nextInFile ) {
  640. if ( decl->redefinedInReload == false ) {
  641. decl->MakeDefault();
  642. decl->sourceTextOffset = decl->sourceFile->fileSize;
  643. decl->sourceTextLength = 0;
  644. decl->sourceLine = decl->sourceFile->numLines;
  645. }
  646. }
  647. return checksum;
  648. }
  649. /*
  650. ====================================================================================
  651. idDeclManagerLocal
  652. ====================================================================================
  653. */
  654. const char *listDeclStrings[] = { "current", "all", "ever", NULL };
  655. /*
  656. ===================
  657. idDeclManagerLocal::Init
  658. ===================
  659. */
  660. void idDeclManagerLocal::Init() {
  661. common->Printf( "----- Initializing Decls -----\n" );
  662. checksum = 0;
  663. #ifdef USE_COMPRESSED_DECLS
  664. SetupHuffman();
  665. #endif
  666. #ifdef GET_HUFFMAN_FREQUENCIES
  667. ClearHuffmanFrequencies();
  668. #endif
  669. // decls used throughout the engine
  670. RegisterDeclType( "table", DECL_TABLE, idDeclAllocator<idDeclTable> );
  671. RegisterDeclType( "material", DECL_MATERIAL, idDeclAllocator<idMaterial> );
  672. RegisterDeclType( "skin", DECL_SKIN, idDeclAllocator<idDeclSkin> );
  673. RegisterDeclType( "sound", DECL_SOUND, idDeclAllocator<idSoundShader> );
  674. RegisterDeclType( "entityDef", DECL_ENTITYDEF, idDeclAllocator<idDeclEntityDef> );
  675. RegisterDeclType( "mapDef", DECL_MAPDEF, idDeclAllocator<idDeclEntityDef> );
  676. RegisterDeclType( "fx", DECL_FX, idDeclAllocator<idDeclFX> );
  677. RegisterDeclType( "particle", DECL_PARTICLE, idDeclAllocator<idDeclParticle> );
  678. RegisterDeclType( "articulatedFigure", DECL_AF, idDeclAllocator<idDeclAF> );
  679. RegisterDeclType( "pda", DECL_PDA, idDeclAllocator<idDeclPDA> );
  680. RegisterDeclType( "email", DECL_EMAIL, idDeclAllocator<idDeclEmail> );
  681. RegisterDeclType( "video", DECL_VIDEO, idDeclAllocator<idDeclVideo> );
  682. RegisterDeclType( "audio", DECL_AUDIO, idDeclAllocator<idDeclAudio> );
  683. RegisterDeclFolder( "materials", ".mtr", DECL_MATERIAL );
  684. // add console commands
  685. cmdSystem->AddCommand( "listDecls", ListDecls_f, CMD_FL_SYSTEM, "lists all decls" );
  686. cmdSystem->AddCommand( "reloadDecls", ReloadDecls_f, CMD_FL_SYSTEM, "reloads decls" );
  687. cmdSystem->AddCommand( "touch", TouchDecl_f, CMD_FL_SYSTEM, "touches a decl" );
  688. cmdSystem->AddCommand( "listTables", idListDecls_f<DECL_TABLE>, CMD_FL_SYSTEM, "lists tables", idCmdSystem::ArgCompletion_String<listDeclStrings> );
  689. cmdSystem->AddCommand( "listMaterials", idListDecls_f<DECL_MATERIAL>, CMD_FL_SYSTEM, "lists materials", idCmdSystem::ArgCompletion_String<listDeclStrings> );
  690. cmdSystem->AddCommand( "listSkins", idListDecls_f<DECL_SKIN>, CMD_FL_SYSTEM, "lists skins", idCmdSystem::ArgCompletion_String<listDeclStrings> );
  691. cmdSystem->AddCommand( "listSoundShaders", idListDecls_f<DECL_SOUND>, CMD_FL_SYSTEM, "lists sound shaders", idCmdSystem::ArgCompletion_String<listDeclStrings> );
  692. cmdSystem->AddCommand( "listEntityDefs", idListDecls_f<DECL_ENTITYDEF>, CMD_FL_SYSTEM, "lists entity defs", idCmdSystem::ArgCompletion_String<listDeclStrings> );
  693. cmdSystem->AddCommand( "listFX", idListDecls_f<DECL_FX>, CMD_FL_SYSTEM, "lists FX systems", idCmdSystem::ArgCompletion_String<listDeclStrings> );
  694. cmdSystem->AddCommand( "listParticles", idListDecls_f<DECL_PARTICLE>, CMD_FL_SYSTEM, "lists particle systems", idCmdSystem::ArgCompletion_String<listDeclStrings> );
  695. cmdSystem->AddCommand( "listAF", idListDecls_f<DECL_AF>, CMD_FL_SYSTEM, "lists articulated figures", idCmdSystem::ArgCompletion_String<listDeclStrings>);
  696. cmdSystem->AddCommand( "listPDAs", idListDecls_f<DECL_PDA>, CMD_FL_SYSTEM, "lists PDAs", idCmdSystem::ArgCompletion_String<listDeclStrings> );
  697. cmdSystem->AddCommand( "listEmails", idListDecls_f<DECL_EMAIL>, CMD_FL_SYSTEM, "lists Emails", idCmdSystem::ArgCompletion_String<listDeclStrings> );
  698. cmdSystem->AddCommand( "listVideos", idListDecls_f<DECL_VIDEO>, CMD_FL_SYSTEM, "lists Videos", idCmdSystem::ArgCompletion_String<listDeclStrings> );
  699. cmdSystem->AddCommand( "listAudios", idListDecls_f<DECL_AUDIO>, CMD_FL_SYSTEM, "lists Audios", idCmdSystem::ArgCompletion_String<listDeclStrings> );
  700. cmdSystem->AddCommand( "printTable", idPrintDecls_f<DECL_TABLE>, CMD_FL_SYSTEM, "prints a table", idCmdSystem::ArgCompletion_Decl<DECL_TABLE> );
  701. cmdSystem->AddCommand( "printMaterial", idPrintDecls_f<DECL_MATERIAL>, CMD_FL_SYSTEM, "prints a material", idCmdSystem::ArgCompletion_Decl<DECL_MATERIAL> );
  702. cmdSystem->AddCommand( "printSkin", idPrintDecls_f<DECL_SKIN>, CMD_FL_SYSTEM, "prints a skin", idCmdSystem::ArgCompletion_Decl<DECL_SKIN> );
  703. cmdSystem->AddCommand( "printSoundShader", idPrintDecls_f<DECL_SOUND>, CMD_FL_SYSTEM, "prints a sound shader", idCmdSystem::ArgCompletion_Decl<DECL_SOUND> );
  704. cmdSystem->AddCommand( "printEntityDef", idPrintDecls_f<DECL_ENTITYDEF>, CMD_FL_SYSTEM, "prints an entity def", idCmdSystem::ArgCompletion_Decl<DECL_ENTITYDEF> );
  705. cmdSystem->AddCommand( "printFX", idPrintDecls_f<DECL_FX>, CMD_FL_SYSTEM, "prints an FX system", idCmdSystem::ArgCompletion_Decl<DECL_FX> );
  706. cmdSystem->AddCommand( "printParticle", idPrintDecls_f<DECL_PARTICLE>, CMD_FL_SYSTEM, "prints a particle system", idCmdSystem::ArgCompletion_Decl<DECL_PARTICLE> );
  707. cmdSystem->AddCommand( "printAF", idPrintDecls_f<DECL_AF>, CMD_FL_SYSTEM, "prints an articulated figure", idCmdSystem::ArgCompletion_Decl<DECL_AF> );
  708. cmdSystem->AddCommand( "printPDA", idPrintDecls_f<DECL_PDA>, CMD_FL_SYSTEM, "prints an PDA", idCmdSystem::ArgCompletion_Decl<DECL_PDA> );
  709. cmdSystem->AddCommand( "printEmail", idPrintDecls_f<DECL_EMAIL>, CMD_FL_SYSTEM, "prints an Email", idCmdSystem::ArgCompletion_Decl<DECL_EMAIL> );
  710. cmdSystem->AddCommand( "printVideo", idPrintDecls_f<DECL_VIDEO>, CMD_FL_SYSTEM, "prints an Audio", idCmdSystem::ArgCompletion_Decl<DECL_VIDEO> );
  711. cmdSystem->AddCommand( "printAudio", idPrintDecls_f<DECL_AUDIO>, CMD_FL_SYSTEM, "prints a Video", idCmdSystem::ArgCompletion_Decl<DECL_AUDIO> );
  712. cmdSystem->AddCommand( "listHuffmanFrequencies", ListHuffmanFrequencies_f, CMD_FL_SYSTEM, "lists decl text character frequencies" );
  713. cmdSystem->AddCommand( "convertPDAsToStrings", ConvertPDAsToStrings_f, CMD_FL_SYSTEM, "Converts *.pda files to text which can be plugged into *.lang files." );
  714. common->Printf( "------------------------------\n" );
  715. }
  716. void idDeclManagerLocal::Init2() {
  717. RegisterDeclFolder( "skins", ".skin", DECL_SKIN );
  718. RegisterDeclFolder( "sound", ".sndshd", DECL_SOUND );
  719. }
  720. /*
  721. ===================
  722. idDeclManagerLocal::Shutdown
  723. ===================
  724. */
  725. void idDeclManagerLocal::Shutdown() {
  726. int i, j;
  727. idDeclLocal *decl;
  728. // free decls
  729. for ( i = 0; i < DECL_MAX_TYPES; i++ ) {
  730. for ( j = 0; j < linearLists[i].Num(); j++ ) {
  731. decl = linearLists[i][j];
  732. if ( decl->self != NULL ) {
  733. decl->self->FreeData();
  734. delete decl->self;
  735. }
  736. if ( decl->textSource ) {
  737. Mem_Free( decl->textSource );
  738. decl->textSource = NULL;
  739. }
  740. delete decl;
  741. }
  742. linearLists[i].Clear();
  743. hashTables[i].Free();
  744. }
  745. // free decl files
  746. loadedFiles.DeleteContents( true );
  747. // free the decl types and folders
  748. declTypes.DeleteContents( true );
  749. declFolders.DeleteContents( true );
  750. #ifdef USE_COMPRESSED_DECLS
  751. ShutdownHuffman();
  752. #endif
  753. }
  754. /*
  755. ===================
  756. idDeclManagerLocal::Reload
  757. ===================
  758. */
  759. void idDeclManagerLocal::Reload( bool force ) {
  760. for ( int i = 0; i < loadedFiles.Num(); i++ ) {
  761. loadedFiles[i]->Reload( force );
  762. }
  763. }
  764. /*
  765. ===================
  766. idDeclManagerLocal::BeginLevelLoad
  767. ===================
  768. */
  769. void idDeclManagerLocal::BeginLevelLoad() {
  770. insideLevelLoad = true;
  771. // clear all the referencedThisLevel flags and purge all the data
  772. // so the next reference will cause a reparse
  773. for ( int i = 0; i < DECL_MAX_TYPES; i++ ) {
  774. int num = linearLists[i].Num();
  775. for ( int j = 0 ; j < num ; j++ ) {
  776. idDeclLocal *decl = linearLists[i][j];
  777. decl->Purge();
  778. }
  779. }
  780. }
  781. /*
  782. ===================
  783. idDeclManagerLocal::EndLevelLoad
  784. ===================
  785. */
  786. void idDeclManagerLocal::EndLevelLoad() {
  787. insideLevelLoad = false;
  788. // we don't need to do anything here, but the image manager, model manager,
  789. // and sound sample manager will need to free media that was not referenced
  790. }
  791. /*
  792. ===================
  793. idDeclManagerLocal::RegisterDeclType
  794. ===================
  795. */
  796. void idDeclManagerLocal::RegisterDeclType( const char *typeName, declType_t type, idDecl *(*allocator)() ) {
  797. idDeclType *declType;
  798. if ( type < declTypes.Num() && declTypes[(int)type] ) {
  799. common->Warning( "idDeclManager::RegisterDeclType: type '%s' already exists", typeName );
  800. return;
  801. }
  802. declType = new (TAG_DECL) idDeclType;
  803. declType->typeName = typeName;
  804. declType->type = type;
  805. declType->allocator = allocator;
  806. if ( (int)type + 1 > declTypes.Num() ) {
  807. declTypes.AssureSize( (int)type + 1, NULL );
  808. }
  809. declTypes[type] = declType;
  810. }
  811. /*
  812. ===================
  813. idDeclManagerLocal::RegisterDeclFolder
  814. ===================
  815. */
  816. void idDeclManagerLocal::RegisterDeclFolder( const char *folder, const char *extension, declType_t defaultType ) {
  817. int i, j;
  818. idStr fileName;
  819. idDeclFolder *declFolder;
  820. idFileList *fileList;
  821. idDeclFile *df;
  822. // check whether this folder / extension combination already exists
  823. for ( i = 0; i < declFolders.Num(); i++ ) {
  824. if ( declFolders[i]->folder.Icmp( folder ) == 0 && declFolders[i]->extension.Icmp( extension ) == 0 ) {
  825. break;
  826. }
  827. }
  828. if ( i < declFolders.Num() ) {
  829. declFolder = declFolders[i];
  830. } else {
  831. declFolder = new (TAG_DECL) idDeclFolder;
  832. declFolder->folder = folder;
  833. declFolder->extension = extension;
  834. declFolder->defaultType = defaultType;
  835. declFolders.Append( declFolder );
  836. }
  837. // scan for decl files
  838. fileList = fileSystem->ListFiles( declFolder->folder, declFolder->extension, true );
  839. // load and parse decl files
  840. for ( i = 0; i < fileList->GetNumFiles(); i++ ) {
  841. fileName = declFolder->folder + "/" + fileList->GetFile( i );
  842. // check whether this file has already been loaded
  843. for ( j = 0; j < loadedFiles.Num(); j++ ) {
  844. if ( fileName.Icmp( loadedFiles[j]->fileName ) == 0 ) {
  845. break;
  846. }
  847. }
  848. if ( j < loadedFiles.Num() ) {
  849. df = loadedFiles[j];
  850. } else {
  851. df = new (TAG_DECL) idDeclFile( fileName, defaultType );
  852. loadedFiles.Append( df );
  853. }
  854. df->LoadAndParse();
  855. }
  856. fileSystem->FreeFileList( fileList );
  857. }
  858. /*
  859. ===================
  860. idDeclManagerLocal::GetChecksum
  861. ===================
  862. */
  863. int idDeclManagerLocal::GetChecksum() const {
  864. int i, j, total, num;
  865. int *checksumData;
  866. // get the total number of decls
  867. total = 0;
  868. for ( i = 0; i < DECL_MAX_TYPES; i++ ) {
  869. total += linearLists[i].Num();
  870. }
  871. checksumData = (int *) _alloca16( total * 2 * sizeof( int ) );
  872. total = 0;
  873. for ( i = 0; i < DECL_MAX_TYPES; i++ ) {
  874. declType_t type = (declType_t) i;
  875. // FIXME: not particularly pretty but PDAs and associated decls are localized and should not be checksummed
  876. if ( type == DECL_PDA || type == DECL_VIDEO || type == DECL_AUDIO || type == DECL_EMAIL ) {
  877. continue;
  878. }
  879. num = linearLists[i].Num();
  880. for ( j = 0; j < num; j++ ) {
  881. idDeclLocal *decl = linearLists[i][j];
  882. if ( decl->sourceFile == &implicitDecls ) {
  883. continue;
  884. }
  885. checksumData[total*2+0] = total;
  886. checksumData[total*2+1] = decl->checksum;
  887. total++;
  888. }
  889. }
  890. LittleRevBytes( checksumData, sizeof(int), total * 2 );
  891. return MD5_BlockChecksum( checksumData, total * 2 * sizeof( int ) );
  892. }
  893. /*
  894. ===================
  895. idDeclManagerLocal::GetNumDeclTypes
  896. ===================
  897. */
  898. int idDeclManagerLocal::GetNumDeclTypes() const {
  899. return declTypes.Num();
  900. }
  901. /*
  902. ===================
  903. idDeclManagerLocal::GetDeclNameFromType
  904. ===================
  905. */
  906. const char * idDeclManagerLocal::GetDeclNameFromType( declType_t type ) const {
  907. int typeIndex = (int)type;
  908. if ( typeIndex < 0 || typeIndex >= declTypes.Num() || declTypes[typeIndex] == NULL ) {
  909. common->FatalError( "idDeclManager::GetDeclNameFromType: bad type: %i", typeIndex );
  910. }
  911. return declTypes[typeIndex]->typeName;
  912. }
  913. /*
  914. ===================
  915. idDeclManagerLocal::GetDeclTypeFromName
  916. ===================
  917. */
  918. declType_t idDeclManagerLocal::GetDeclTypeFromName( const char *typeName ) const {
  919. int i;
  920. for ( i = 0; i < declTypes.Num(); i++ ) {
  921. if ( declTypes[i] && declTypes[i]->typeName.Icmp( typeName ) == 0 ) {
  922. return (declType_t)declTypes[i]->type;
  923. }
  924. }
  925. return DECL_MAX_TYPES;
  926. }
  927. /*
  928. =================
  929. idDeclManagerLocal::FindType
  930. External users will always cause the decl to be parsed before returning
  931. =================
  932. */
  933. const idDecl *idDeclManagerLocal::FindType( declType_t type, const char *name, bool makeDefault ) {
  934. idDeclLocal *decl;
  935. idScopedCriticalSection cs( mutex );
  936. if ( !name || !name[0] ) {
  937. name = "_emptyName";
  938. //common->Warning( "idDeclManager::FindType: empty %s name", GetDeclType( (int)type )->typeName.c_str() );
  939. }
  940. decl = FindTypeWithoutParsing( type, name, makeDefault );
  941. if ( !decl ) {
  942. return NULL;
  943. }
  944. decl->AllocateSelf();
  945. // if it hasn't been parsed yet, parse it now
  946. if ( decl->declState == DS_UNPARSED ) {
  947. if ( !idLib::IsMainThread() ) {
  948. // we can't load images from a background thread on OpenGL,
  949. // the renderer on the main thread should parse it if needed
  950. idLib::Error( "Attempted to load %s decl '%s' from game thread!", GetDeclNameFromType( type ), name );
  951. }
  952. decl->ParseLocal();
  953. }
  954. // mark it as referenced
  955. decl->referencedThisLevel = true;
  956. decl->everReferenced = true;
  957. if ( insideLevelLoad ) {
  958. decl->parsedOutsideLevelLoad = false;
  959. }
  960. return decl->self;
  961. }
  962. /*
  963. ===============
  964. idDeclManagerLocal::FindDeclWithoutParsing
  965. ===============
  966. */
  967. const idDecl* idDeclManagerLocal::FindDeclWithoutParsing( declType_t type, const char *name, bool makeDefault) {
  968. idDeclLocal* decl;
  969. decl = FindTypeWithoutParsing(type, name, makeDefault);
  970. if(decl) {
  971. return decl->self;
  972. }
  973. return NULL;
  974. }
  975. /*
  976. ===============
  977. idDeclManagerLocal::ReloadFile
  978. ===============
  979. */
  980. void idDeclManagerLocal::ReloadFile( const char* filename, bool force ) {
  981. for ( int i = 0; i < loadedFiles.Num(); i++ ) {
  982. if(!loadedFiles[i]->fileName.Icmp(filename)) {
  983. checksum ^= loadedFiles[i]->checksum;
  984. loadedFiles[i]->Reload( force );
  985. checksum ^= loadedFiles[i]->checksum;
  986. }
  987. }
  988. }
  989. /*
  990. ===================
  991. idDeclManagerLocal::GetNumDecls
  992. ===================
  993. */
  994. int idDeclManagerLocal::GetNumDecls( declType_t type ) {
  995. int typeIndex = (int)type;
  996. if ( typeIndex < 0 || typeIndex >= declTypes.Num() || declTypes[typeIndex] == NULL ) {
  997. common->FatalError( "idDeclManager::GetNumDecls: bad type: %i", typeIndex );
  998. return 0;
  999. }
  1000. return linearLists[ typeIndex ].Num();
  1001. }
  1002. /*
  1003. ===================
  1004. idDeclManagerLocal::DeclByIndex
  1005. ===================
  1006. */
  1007. const idDecl *idDeclManagerLocal::DeclByIndex( declType_t type, int index, bool forceParse ) {
  1008. int typeIndex = (int)type;
  1009. if ( typeIndex < 0 || typeIndex >= declTypes.Num() || declTypes[typeIndex] == NULL ) {
  1010. common->FatalError( "idDeclManager::DeclByIndex: bad type: %i", typeIndex );
  1011. return NULL;
  1012. }
  1013. if ( index < 0 || index >= linearLists[ typeIndex ].Num() ) {
  1014. common->Error( "idDeclManager::DeclByIndex: out of range" );
  1015. }
  1016. idDeclLocal *decl = linearLists[ typeIndex ][ index ];
  1017. decl->AllocateSelf();
  1018. if ( forceParse && decl->declState == DS_UNPARSED ) {
  1019. decl->ParseLocal();
  1020. }
  1021. return decl->self;
  1022. }
  1023. /*
  1024. ===================
  1025. idDeclManagerLocal::ListType
  1026. list*
  1027. Lists decls currently referenced
  1028. list* ever
  1029. Lists decls that have been referenced at least once since app launched
  1030. list* all
  1031. Lists every decl declared, even if it hasn't been referenced or parsed
  1032. FIXME: alphabetized, wildcards?
  1033. ===================
  1034. */
  1035. void idDeclManagerLocal::ListType( const idCmdArgs &args, declType_t type ) {
  1036. bool all, ever;
  1037. if ( !idStr::Icmp( args.Argv( 1 ), "all" ) ) {
  1038. all = true;
  1039. } else {
  1040. all = false;
  1041. }
  1042. if ( !idStr::Icmp( args.Argv( 1 ), "ever" ) ) {
  1043. ever = true;
  1044. } else {
  1045. ever = false;
  1046. }
  1047. common->Printf( "--------------------\n" );
  1048. int printed = 0;
  1049. int count = linearLists[ (int)type ].Num();
  1050. for ( int i = 0 ; i < count ; i++ ) {
  1051. idDeclLocal *decl = linearLists[ (int)type ][ i ];
  1052. if ( !all && decl->declState == DS_UNPARSED ) {
  1053. continue;
  1054. }
  1055. if ( !all && !ever && !decl->referencedThisLevel ) {
  1056. continue;
  1057. }
  1058. if ( decl->referencedThisLevel ) {
  1059. common->Printf( "*" );
  1060. } else if ( decl->everReferenced ) {
  1061. common->Printf( "." );
  1062. } else {
  1063. common->Printf( " " );
  1064. }
  1065. if ( decl->declState == DS_DEFAULTED ) {
  1066. common->Printf( "D" );
  1067. } else {
  1068. common->Printf( " " );
  1069. }
  1070. common->Printf( "%4i: ", decl->index );
  1071. printed++;
  1072. if ( decl->declState == DS_UNPARSED ) {
  1073. // doesn't have any type specific data yet
  1074. common->Printf( "%s\n", decl->GetName() );
  1075. } else {
  1076. decl->self->List();
  1077. }
  1078. }
  1079. common->Printf( "--------------------\n" );
  1080. common->Printf( "%i of %i %s\n", printed, count, declTypes[type]->typeName.c_str() );
  1081. }
  1082. /*
  1083. ===================
  1084. idDeclManagerLocal::PrintType
  1085. ===================
  1086. */
  1087. void idDeclManagerLocal::PrintType( const idCmdArgs &args, declType_t type ) {
  1088. // individual decl types may use additional command parameters
  1089. if ( args.Argc() < 2 ) {
  1090. common->Printf( "USAGE: Print<decl type> <decl name> [type specific parms]\n" );
  1091. return;
  1092. }
  1093. // look it up, skipping the public path so it won't parse or reference
  1094. idDeclLocal *decl = FindTypeWithoutParsing( type, args.Argv( 1 ), false );
  1095. if ( !decl ) {
  1096. common->Printf( "%s '%s' not found.\n", declTypes[ type ]->typeName.c_str(), args.Argv( 1 ) );
  1097. return;
  1098. }
  1099. // print information common to all decls
  1100. common->Printf( "%s %s:\n", declTypes[ type ]->typeName.c_str(), decl->name.c_str() );
  1101. common->Printf( "source: %s:%i\n", decl->sourceFile->fileName.c_str(), decl->sourceLine );
  1102. common->Printf( "----------\n" );
  1103. if ( decl->textSource != NULL ) {
  1104. char *declText = (char *)_alloca( decl->textLength + 1 );
  1105. decl->GetText( declText );
  1106. common->Printf( "%s\n", declText );
  1107. } else {
  1108. common->Printf( "NO SOURCE\n" );
  1109. }
  1110. common->Printf( "----------\n" );
  1111. switch( decl->declState ) {
  1112. case DS_UNPARSED:
  1113. common->Printf( "Unparsed.\n" );
  1114. break;
  1115. case DS_DEFAULTED:
  1116. common->Printf( "<DEFAULTED>\n" );
  1117. break;
  1118. case DS_PARSED:
  1119. common->Printf( "Parsed.\n" );
  1120. break;
  1121. }
  1122. if ( decl->referencedThisLevel ) {
  1123. common->Printf( "Currently referenced this level.\n" );
  1124. } else if ( decl->everReferenced ) {
  1125. common->Printf( "Referenced in a previous level.\n" );
  1126. } else {
  1127. common->Printf( "Never referenced.\n" );
  1128. }
  1129. // allow type-specific data to be printed
  1130. if ( decl->self != NULL ) {
  1131. decl->self->Print();
  1132. }
  1133. }
  1134. /*
  1135. ===================
  1136. idDeclManagerLocal::CreateNewDecl
  1137. ===================
  1138. */
  1139. idDecl *idDeclManagerLocal::CreateNewDecl( declType_t type, const char *name, const char *_fileName ) {
  1140. int typeIndex = (int)type;
  1141. int i, hash;
  1142. if ( typeIndex < 0 || typeIndex >= declTypes.Num() || declTypes[typeIndex] == NULL || typeIndex >= DECL_MAX_TYPES ) {
  1143. common->FatalError( "idDeclManager::CreateNewDecl: bad type: %i", typeIndex );
  1144. return NULL;
  1145. }
  1146. char canonicalName[MAX_STRING_CHARS];
  1147. MakeNameCanonical( name, canonicalName, sizeof( canonicalName ) );
  1148. idStr fileName = _fileName;
  1149. fileName.BackSlashesToSlashes();
  1150. // see if it already exists
  1151. hash = hashTables[typeIndex].GenerateKey( canonicalName, false );
  1152. for ( i = hashTables[typeIndex].First( hash ); i >= 0; i = hashTables[typeIndex].Next( i ) ) {
  1153. if ( linearLists[typeIndex][i]->name.Icmp( canonicalName ) == 0 ) {
  1154. linearLists[typeIndex][i]->AllocateSelf();
  1155. return linearLists[typeIndex][i]->self;
  1156. }
  1157. }
  1158. idDeclFile *sourceFile;
  1159. // find existing source file or create a new one
  1160. for ( i = 0; i < loadedFiles.Num(); i++ ) {
  1161. if ( loadedFiles[i]->fileName.Icmp( fileName ) == 0 ) {
  1162. break;
  1163. }
  1164. }
  1165. if ( i < loadedFiles.Num() ) {
  1166. sourceFile = loadedFiles[i];
  1167. } else {
  1168. sourceFile = new (TAG_DECL) idDeclFile( fileName, type );
  1169. loadedFiles.Append( sourceFile );
  1170. }
  1171. idDeclLocal *decl = new (TAG_DECL) idDeclLocal;
  1172. decl->name = canonicalName;
  1173. decl->type = type;
  1174. decl->declState = DS_UNPARSED;
  1175. decl->AllocateSelf();
  1176. idStr header = declTypes[typeIndex]->typeName;
  1177. idStr defaultText = decl->self->DefaultDefinition();
  1178. int size = header.Length() + 1 + idStr::Length( canonicalName ) + 1 + defaultText.Length();
  1179. char *declText = ( char * ) _alloca( size + 1 );
  1180. memcpy( declText, header, header.Length() );
  1181. declText[header.Length()] = ' ';
  1182. memcpy( declText + header.Length() + 1, canonicalName, idStr::Length( canonicalName ) );
  1183. declText[header.Length() + 1 + idStr::Length( canonicalName )] = ' ';
  1184. memcpy( declText + header.Length() + 1 + idStr::Length( canonicalName ) + 1, defaultText, defaultText.Length() + 1 );
  1185. decl->SetTextLocal( declText, size );
  1186. decl->sourceFile = sourceFile;
  1187. decl->sourceTextOffset = sourceFile->fileSize;
  1188. decl->sourceTextLength = 0;
  1189. decl->sourceLine = sourceFile->numLines;
  1190. decl->ParseLocal();
  1191. // add this decl to the source file list
  1192. decl->nextInFile = sourceFile->decls;
  1193. sourceFile->decls = decl;
  1194. // add it to the hash table and linear list
  1195. decl->index = linearLists[typeIndex].Num();
  1196. hashTables[typeIndex].Add( hash, linearLists[typeIndex].Append( decl ) );
  1197. return decl->self;
  1198. }
  1199. /*
  1200. ===============
  1201. idDeclManagerLocal::RenameDecl
  1202. ===============
  1203. */
  1204. bool idDeclManagerLocal::RenameDecl( declType_t type, const char* oldName, const char* newName ) {
  1205. char canonicalOldName[MAX_STRING_CHARS];
  1206. MakeNameCanonical( oldName, canonicalOldName, sizeof( canonicalOldName ));
  1207. char canonicalNewName[MAX_STRING_CHARS];
  1208. MakeNameCanonical( newName, canonicalNewName, sizeof( canonicalNewName ) );
  1209. idDeclLocal *decl = NULL;
  1210. // make sure it already exists
  1211. int typeIndex = (int)type;
  1212. int i, hash;
  1213. hash = hashTables[typeIndex].GenerateKey( canonicalOldName, false );
  1214. for ( i = hashTables[typeIndex].First( hash ); i >= 0; i = hashTables[typeIndex].Next( i ) ) {
  1215. if ( linearLists[typeIndex][i]->name.Icmp( canonicalOldName ) == 0 ) {
  1216. decl = linearLists[typeIndex][i];
  1217. break;
  1218. }
  1219. }
  1220. if(!decl)
  1221. return false;
  1222. //if ( !hashTables[(int)type].Get( canonicalOldName, &declPtr ) )
  1223. // return false;
  1224. //decl = *declPtr;
  1225. //Change the name
  1226. decl->name = canonicalNewName;
  1227. // add it to the hash table
  1228. //hashTables[(int)decl->type].Set( decl->name, decl );
  1229. int newhash = hashTables[typeIndex].GenerateKey( canonicalNewName, false );
  1230. hashTables[typeIndex].Add( newhash, decl->index );
  1231. //Remove the old hash item
  1232. hashTables[typeIndex].Remove(hash, decl->index);
  1233. return true;
  1234. }
  1235. /*
  1236. ===================
  1237. idDeclManagerLocal::MediaPrint
  1238. This is just used to nicely indent media caching prints
  1239. ===================
  1240. */
  1241. void idDeclManagerLocal::MediaPrint( const char *fmt, ... ) {
  1242. if ( !decl_show.GetInteger() ) {
  1243. return;
  1244. }
  1245. for ( int i = 0 ; i < indent ; i++ ) {
  1246. common->Printf( " " );
  1247. }
  1248. va_list argptr;
  1249. char buffer[1024];
  1250. va_start (argptr,fmt);
  1251. idStr::vsnPrintf( buffer, sizeof(buffer), fmt, argptr );
  1252. va_end (argptr);
  1253. buffer[sizeof(buffer)-1] = '\0';
  1254. common->Printf( "%s", buffer );
  1255. }
  1256. /*
  1257. ===================
  1258. idDeclManagerLocal::WritePrecacheCommands
  1259. ===================
  1260. */
  1261. void idDeclManagerLocal::WritePrecacheCommands( idFile *f ) {
  1262. for ( int i = 0; i < declTypes.Num(); i++ ) {
  1263. int num;
  1264. if ( declTypes[i] == NULL ) {
  1265. continue;
  1266. }
  1267. num = linearLists[i].Num();
  1268. for ( int j = 0 ; j < num ; j++ ) {
  1269. idDeclLocal *decl = linearLists[i][j];
  1270. if ( !decl->referencedThisLevel ) {
  1271. continue;
  1272. }
  1273. char str[1024];
  1274. sprintf( str, "touch %s %s\n", declTypes[i]->typeName.c_str(), decl->GetName() );
  1275. common->Printf( "%s", str );
  1276. f->Printf( "%s", str );
  1277. }
  1278. }
  1279. }
  1280. /********************************************************************/
  1281. const idMaterial *idDeclManagerLocal::FindMaterial( const char *name, bool makeDefault ) {
  1282. return static_cast<const idMaterial *>( FindType( DECL_MATERIAL, name, makeDefault ) );
  1283. }
  1284. const idMaterial *idDeclManagerLocal::MaterialByIndex( int index, bool forceParse ) {
  1285. return static_cast<const idMaterial *>( DeclByIndex( DECL_MATERIAL, index, forceParse ) );
  1286. }
  1287. /********************************************************************/
  1288. const idDeclSkin *idDeclManagerLocal::FindSkin( const char *name, bool makeDefault ) {
  1289. return static_cast<const idDeclSkin *>( FindType( DECL_SKIN, name, makeDefault ) );
  1290. }
  1291. const idDeclSkin *idDeclManagerLocal::SkinByIndex( int index, bool forceParse ) {
  1292. return static_cast<const idDeclSkin *>( DeclByIndex( DECL_SKIN, index, forceParse ) );
  1293. }
  1294. /********************************************************************/
  1295. const idSoundShader *idDeclManagerLocal::FindSound( const char *name, bool makeDefault ) {
  1296. return static_cast<const idSoundShader *>( FindType( DECL_SOUND, name, makeDefault ) );
  1297. }
  1298. const idSoundShader *idDeclManagerLocal::SoundByIndex( int index, bool forceParse ) {
  1299. return static_cast<const idSoundShader *>( DeclByIndex( DECL_SOUND, index, forceParse ) );
  1300. }
  1301. /*
  1302. ===================
  1303. idDeclManagerLocal::Touch
  1304. ===================
  1305. */
  1306. void idDeclManagerLocal::Touch( const idDecl * decl ) {
  1307. if( decl->base->GetState() == DS_UNPARSED ) {
  1308. // This should parse the decl as well.
  1309. FindType( decl->GetType(), decl->GetName() );
  1310. }
  1311. }
  1312. /*
  1313. ===================
  1314. idDeclManagerLocal::MakeNameCanonical
  1315. ===================
  1316. */
  1317. void idDeclManagerLocal::MakeNameCanonical( const char *name, char *result, int maxLength ) {
  1318. int i, lastDot;
  1319. lastDot = -1;
  1320. for ( i = 0; i < maxLength && name[i] != '\0'; i++ ) {
  1321. int c = name[i];
  1322. if ( c == '\\' ) {
  1323. result[i] = '/';
  1324. } else if ( c == '.' ) {
  1325. lastDot = i;
  1326. result[i] = c;
  1327. } else {
  1328. result[i] = idStr::ToLower( c );
  1329. }
  1330. }
  1331. if ( lastDot != -1 ) {
  1332. result[lastDot] = '\0';
  1333. } else {
  1334. result[i] = '\0';
  1335. }
  1336. }
  1337. /*
  1338. ================
  1339. idDeclManagerLocal::ListDecls_f
  1340. ================
  1341. */
  1342. void idDeclManagerLocal::ListDecls_f( const idCmdArgs &args ) {
  1343. int i, j;
  1344. int totalDecls = 0;
  1345. int totalText = 0;
  1346. int totalStructs = 0;
  1347. for ( i = 0; i < declManagerLocal.declTypes.Num(); i++ ) {
  1348. int size, num;
  1349. if ( declManagerLocal.declTypes[i] == NULL ) {
  1350. continue;
  1351. }
  1352. num = declManagerLocal.linearLists[i].Num();
  1353. totalDecls += num;
  1354. size = 0;
  1355. for ( j = 0; j < num; j++ ) {
  1356. size += declManagerLocal.linearLists[i][j]->Size();
  1357. if ( declManagerLocal.linearLists[i][j]->self != NULL ) {
  1358. size += declManagerLocal.linearLists[i][j]->self->Size();
  1359. }
  1360. }
  1361. totalStructs += size;
  1362. common->Printf( "%4ik %4i %s\n", size >> 10, num, declManagerLocal.declTypes[i]->typeName.c_str() );
  1363. }
  1364. for ( i = 0 ; i < declManagerLocal.loadedFiles.Num() ; i++ ) {
  1365. idDeclFile *df = declManagerLocal.loadedFiles[i];
  1366. totalText += df->fileSize;
  1367. }
  1368. common->Printf( "%i total decls is %i decl files\n", totalDecls, declManagerLocal.loadedFiles.Num() );
  1369. common->Printf( "%iKB in text, %iKB in structures\n", totalText >> 10, totalStructs >> 10 );
  1370. }
  1371. /*
  1372. ===================
  1373. idDeclManagerLocal::ReloadDecls_f
  1374. Reload will not find any new files created in the directories, it
  1375. will only reload existing files.
  1376. A reload will never cause anything to be purged.
  1377. ===================
  1378. */
  1379. void idDeclManagerLocal::ReloadDecls_f( const idCmdArgs &args ) {
  1380. bool force;
  1381. if ( !idStr::Icmp( args.Argv( 1 ), "all" ) ) {
  1382. force = true;
  1383. common->Printf( "reloading all decl files:\n" );
  1384. } else {
  1385. force = false;
  1386. common->Printf( "reloading changed decl files:\n" );
  1387. }
  1388. declManagerLocal.Reload( force );
  1389. }
  1390. /*
  1391. ===================
  1392. idDeclManagerLocal::TouchDecl_f
  1393. ===================
  1394. */
  1395. void idDeclManagerLocal::TouchDecl_f( const idCmdArgs &args ) {
  1396. int i;
  1397. if ( args.Argc() != 3 ) {
  1398. common->Printf( "usage: touch <type> <name>\n" );
  1399. common->Printf( "valid types: " );
  1400. for ( int i = 0 ; i < declManagerLocal.declTypes.Num() ; i++ ) {
  1401. if ( declManagerLocal.declTypes[i] ) {
  1402. common->Printf( "%s ", declManagerLocal.declTypes[i]->typeName.c_str() );
  1403. }
  1404. }
  1405. common->Printf( "\n" );
  1406. return;
  1407. }
  1408. for ( i = 0; i < declManagerLocal.declTypes.Num(); i++ ) {
  1409. if ( declManagerLocal.declTypes[i] && declManagerLocal.declTypes[i]->typeName.Icmp( args.Argv( 1 ) ) == 0 ) {
  1410. break;
  1411. }
  1412. }
  1413. if ( i >= declManagerLocal.declTypes.Num() ) {
  1414. common->Printf( "unknown decl type '%s'\n", args.Argv( 1 ) );
  1415. return;
  1416. }
  1417. const idDecl *decl = declManagerLocal.FindType( (declType_t)i, args.Argv( 2 ), false );
  1418. if ( !decl ) {
  1419. common->Printf( "%s '%s' not found\n", declManagerLocal.declTypes[i]->typeName.c_str(), args.Argv( 2 ) );
  1420. }
  1421. }
  1422. /*
  1423. ===================
  1424. idDeclManagerLocal::FindTypeWithoutParsing
  1425. This finds or creats the decl, but does not cause a parse. This is only used internally.
  1426. ===================
  1427. */
  1428. idDeclLocal *idDeclManagerLocal::FindTypeWithoutParsing( declType_t type, const char *name, bool makeDefault ) {
  1429. int typeIndex = (int)type;
  1430. int i, hash;
  1431. if ( typeIndex < 0 || typeIndex >= declTypes.Num() || declTypes[typeIndex] == NULL || typeIndex >= DECL_MAX_TYPES ) {
  1432. common->FatalError( "idDeclManager::FindTypeWithoutParsing: bad type: %i", typeIndex );
  1433. return NULL;
  1434. }
  1435. char canonicalName[MAX_STRING_CHARS];
  1436. MakeNameCanonical( name, canonicalName, sizeof( canonicalName ) );
  1437. // see if it already exists
  1438. hash = hashTables[typeIndex].GenerateKey( canonicalName, false );
  1439. for ( i = hashTables[typeIndex].First( hash ); i >= 0; i = hashTables[typeIndex].Next( i ) ) {
  1440. if ( linearLists[typeIndex][i]->name.Icmp( canonicalName ) == 0 ) {
  1441. // only print these when decl_show is set to 2, because it can be a lot of clutter
  1442. if ( decl_show.GetInteger() > 1 ) {
  1443. MediaPrint( "referencing %s %s\n", declTypes[ type ]->typeName.c_str(), name );
  1444. }
  1445. return linearLists[typeIndex][i];
  1446. }
  1447. }
  1448. if ( !makeDefault ) {
  1449. return NULL;
  1450. }
  1451. idDeclLocal *decl = new (TAG_DECL) idDeclLocal;
  1452. decl->self = NULL;
  1453. decl->name = canonicalName;
  1454. decl->type = type;
  1455. decl->declState = DS_UNPARSED;
  1456. decl->textSource = NULL;
  1457. decl->textLength = 0;
  1458. decl->sourceFile = &implicitDecls;
  1459. decl->referencedThisLevel = false;
  1460. decl->everReferenced = false;
  1461. decl->parsedOutsideLevelLoad = !insideLevelLoad;
  1462. // add it to the linear list and hash table
  1463. decl->index = linearLists[typeIndex].Num();
  1464. hashTables[typeIndex].Add( hash, linearLists[typeIndex].Append( decl ) );
  1465. return decl;
  1466. }
  1467. /*
  1468. =================
  1469. idDeclManagerLocal::ConvertPDAsToStrings
  1470. =================
  1471. */
  1472. void idDeclManagerLocal::ConvertPDAsToStrings( const idCmdArgs &args ) {
  1473. idStr pdaStringsFileName = "temppdas/pdas.lang";
  1474. idFileLocal file( fileSystem->OpenFileWrite( pdaStringsFileName ) );
  1475. if ( file == NULL ) {
  1476. idLib::Printf( "Failed to Convert PDA data to Strings.\n" );
  1477. }
  1478. int totalEmailCount = 0;
  1479. int totalAudioCount = 0;
  1480. int totalVideoCount = 0;
  1481. idStr headEnd = "\t\"#str_%s_";
  1482. idStr tailEnd = "\"\t\"%s\"\n";
  1483. idStr temp;
  1484. int count = linearLists[ DECL_PDA ].Num();
  1485. for ( int i = 0; i < count; i++ ) {
  1486. const idDeclPDA *decl = static_cast< const idDeclPDA * >( FindType( DECL_PDA, linearLists[ DECL_PDA ][ i ]->GetName(), false ) );
  1487. idStr pdaBaseStrId = va( headEnd.c_str(), decl->GetName() );
  1488. temp = va( "\n\n//////// %s PDA ////////////\n", decl->GetName() );
  1489. file->Write( temp, temp.Length() );
  1490. idStr pdaBase = pdaBaseStrId + "pda_%s" + tailEnd;
  1491. // Pda Name
  1492. temp = va( pdaBase.c_str(), "name", decl->GetPdaName() );
  1493. file->Write( temp, temp.Length() );
  1494. // Full Name
  1495. temp = va( pdaBase.c_str(), "fullname", decl->GetFullName() );
  1496. file->Write( temp, temp.Length() );
  1497. // ID
  1498. temp = va( pdaBase.c_str(), "id", decl->GetID() );
  1499. file->Write( temp, temp.Length() );
  1500. // Post
  1501. temp = va( pdaBase.c_str(), "post", decl->GetPost() );
  1502. file->Write( temp, temp.Length() );
  1503. // Title
  1504. temp = va( pdaBase.c_str(), "title", decl->GetTitle() );
  1505. file->Write( temp, temp.Length() );
  1506. // Security
  1507. temp = va( pdaBase.c_str(), "security", decl->GetSecurity() );
  1508. file->Write( temp, temp.Length() );
  1509. int emailCount = decl->GetNumEmails();
  1510. for ( int emailIter = 0; emailIter < emailCount; emailIter++ ) {
  1511. const idDeclEmail * email = decl->GetEmailByIndex( emailIter );
  1512. idStr emailBaseStrId = va( headEnd.c_str(), email->GetName() );
  1513. idStr emailBase = emailBaseStrId + "email_%s" + tailEnd;
  1514. file->Write( "\t//Email\n", 9 );
  1515. // Date
  1516. temp = va( emailBase, "date", email->GetDate() );
  1517. file->Write( temp, temp.Length() );
  1518. // To
  1519. temp = va( emailBase, "to", email->GetTo() );
  1520. file->Write( temp, temp.Length() );
  1521. // From
  1522. temp = va( emailBase, "from", email->GetFrom() );
  1523. file->Write( temp, temp.Length() );
  1524. // Subject
  1525. temp = va( emailBase, "subject", email->GetSubject() );
  1526. file->Write( temp, temp.Length() );
  1527. // Body
  1528. idStr body = email->GetBody();
  1529. body.Replace( "\n", "\\n" );
  1530. temp = va( emailBase, "text", body.c_str() );
  1531. file->Write( temp, temp.Length() );
  1532. totalEmailCount++;
  1533. }
  1534. int audioCount = decl->GetNumAudios();
  1535. for ( int audioIter = 0; audioIter < audioCount; audioIter++ ) {
  1536. const idDeclAudio * audio = decl->GetAudioByIndex( audioIter );
  1537. idStr audioBaseStrId = va( headEnd.c_str(), audio->GetName() );
  1538. idStr audioBase = audioBaseStrId + "audio_%s" + tailEnd;
  1539. file->Write( "\t//Audio\n", 9 );
  1540. // Name
  1541. temp = va( audioBase, "name", audio->GetAudioName() );
  1542. file->Write( temp, temp.Length() );
  1543. // Info
  1544. idStr info = audio->GetInfo();
  1545. info.Replace( "\n", "\\n" );
  1546. temp = va( audioBase, "info", info.c_str() );
  1547. file->Write( temp, temp.Length() );
  1548. totalAudioCount++;
  1549. }
  1550. }
  1551. int infoEmailCount = linearLists[ DECL_EMAIL ].Num();
  1552. if ( infoEmailCount > 0 ) {
  1553. temp = "\n\n//////// PDA Info Emails ////////////\n";
  1554. file->Write( temp, temp.Length() );
  1555. }
  1556. for ( int i = 0; i < infoEmailCount; i++ ) {
  1557. const idDeclEmail * email = static_cast< const idDeclEmail * >( FindType( DECL_EMAIL, linearLists[ DECL_EMAIL ][ i ]->GetName(), false ) );
  1558. idStr filename = email->base->GetFileName();
  1559. if ( filename.Icmp( "newpdas/info_emails.pda" ) != 0 ) {
  1560. continue;
  1561. }
  1562. idStr emailBaseStrId = va( "\t\"#str_%s_", email->GetName() );
  1563. idStr emailBase = emailBaseStrId + "email_%s" + tailEnd;
  1564. file->Write( "\t//Email\n", 9 );
  1565. // Date
  1566. temp = va( emailBase, "date", email->GetDate() );
  1567. file->Write( temp, temp.Length() );
  1568. // To
  1569. temp = va( emailBase, "to", email->GetTo() );
  1570. file->Write( temp, temp.Length() );
  1571. // From
  1572. temp = va( emailBase, "from", email->GetFrom() );
  1573. file->Write( temp, temp.Length() );
  1574. // Subject
  1575. temp = va( emailBase, "subject", email->GetSubject() );
  1576. file->Write( temp, temp.Length() );
  1577. // Body
  1578. idStr body = email->GetBody();
  1579. body.Replace( "\n", "\\n" );
  1580. temp = va( emailBase, "text", body.c_str() );
  1581. file->Write( temp, temp.Length() );
  1582. totalEmailCount++;
  1583. }
  1584. int videoCount = linearLists[ DECL_VIDEO ].Num();
  1585. if ( videoCount > 0 ) {
  1586. temp = "\n\n//////// PDA Videos ////////////\n";
  1587. file->Write( temp, temp.Length() );
  1588. }
  1589. for ( int i = 0; i < videoCount; i++ ) {
  1590. const idDeclVideo * video = static_cast< const idDeclVideo * >( FindType( DECL_VIDEO, linearLists[ DECL_VIDEO ][ i ]->GetName(), false ) );
  1591. idStr videoBaseStrId = va( "\t\"#str_%s_", video->GetName() );
  1592. idStr videoBase = videoBaseStrId + "video_%s" + tailEnd;
  1593. file->Write( "\t//Video\n", 9 );
  1594. // Name
  1595. temp = va( videoBase, "name", video->GetVideoName() );
  1596. file->Write( temp, temp.Length() );
  1597. // Info
  1598. idStr info = video->GetInfo();
  1599. info.Replace( "\n", "\\n" );
  1600. temp = va( videoBase, "info", info.c_str() );
  1601. file->Write( temp, temp.Length() );
  1602. totalVideoCount++;
  1603. }
  1604. file->Flush();
  1605. idLib::Printf( "\nData written to %s\n", pdaStringsFileName.c_str() );
  1606. idLib::Printf( "----------------------------\n" );
  1607. idLib::Printf( "Wrote %d PDAs.\n", count );
  1608. idLib::Printf( "Wrote %d Emails.\n", totalEmailCount );
  1609. idLib::Printf( "Wrote %d Audio Records.\n", totalAudioCount );
  1610. idLib::Printf( "Wrote %d Video Records.\n", totalVideoCount );
  1611. idLib::Printf( "Please copy the results into the appropriate .lang file.\n" );
  1612. }
  1613. /*
  1614. ====================================================================================
  1615. idDeclLocal
  1616. ====================================================================================
  1617. */
  1618. /*
  1619. =================
  1620. idDeclLocal::idDeclLocal
  1621. =================
  1622. */
  1623. idDeclLocal::idDeclLocal() {
  1624. name = "unnamed";
  1625. textSource = NULL;
  1626. textLength = 0;
  1627. compressedLength = 0;
  1628. sourceFile = NULL;
  1629. sourceTextOffset = 0;
  1630. sourceTextLength = 0;
  1631. sourceLine = 0;
  1632. checksum = 0;
  1633. type = DECL_ENTITYDEF;
  1634. index = 0;
  1635. declState = DS_UNPARSED;
  1636. parsedOutsideLevelLoad = false;
  1637. referencedThisLevel = false;
  1638. everReferenced = false;
  1639. redefinedInReload = false;
  1640. nextInFile = NULL;
  1641. }
  1642. /*
  1643. =================
  1644. idDeclLocal::GetName
  1645. =================
  1646. */
  1647. const char *idDeclLocal::GetName() const {
  1648. return name.c_str();
  1649. }
  1650. /*
  1651. =================
  1652. idDeclLocal::GetType
  1653. =================
  1654. */
  1655. declType_t idDeclLocal::GetType() const {
  1656. return type;
  1657. }
  1658. /*
  1659. =================
  1660. idDeclLocal::GetState
  1661. =================
  1662. */
  1663. declState_t idDeclLocal::GetState() const {
  1664. return declState;
  1665. }
  1666. /*
  1667. =================
  1668. idDeclLocal::IsImplicit
  1669. =================
  1670. */
  1671. bool idDeclLocal::IsImplicit() const {
  1672. return ( sourceFile == declManagerLocal.GetImplicitDeclFile() );
  1673. }
  1674. /*
  1675. =================
  1676. idDeclLocal::IsValid
  1677. =================
  1678. */
  1679. bool idDeclLocal::IsValid() const {
  1680. return ( declState != DS_UNPARSED );
  1681. }
  1682. /*
  1683. =================
  1684. idDeclLocal::Invalidate
  1685. =================
  1686. */
  1687. void idDeclLocal::Invalidate() {
  1688. declState = DS_UNPARSED;
  1689. }
  1690. /*
  1691. =================
  1692. idDeclLocal::EnsureNotPurged
  1693. =================
  1694. */
  1695. void idDeclLocal::EnsureNotPurged() {
  1696. if ( declState == DS_UNPARSED ) {
  1697. ParseLocal();
  1698. }
  1699. }
  1700. /*
  1701. =================
  1702. idDeclLocal::Index
  1703. =================
  1704. */
  1705. int idDeclLocal::Index() const {
  1706. return index;
  1707. }
  1708. /*
  1709. =================
  1710. idDeclLocal::GetLineNum
  1711. =================
  1712. */
  1713. int idDeclLocal::GetLineNum() const {
  1714. return sourceLine;
  1715. }
  1716. /*
  1717. =================
  1718. idDeclLocal::GetFileName
  1719. =================
  1720. */
  1721. const char *idDeclLocal::GetFileName() const {
  1722. return ( sourceFile ) ? sourceFile->fileName.c_str() : "*invalid*";
  1723. }
  1724. /*
  1725. =================
  1726. idDeclLocal::Size
  1727. =================
  1728. */
  1729. size_t idDeclLocal::Size() const {
  1730. return sizeof( idDecl ) + name.Allocated();
  1731. }
  1732. /*
  1733. =================
  1734. idDeclLocal::GetText
  1735. =================
  1736. */
  1737. void idDeclLocal::GetText( char *text ) const {
  1738. #ifdef USE_COMPRESSED_DECLS
  1739. HuffmanDecompressText( text, textLength, (byte *)textSource, compressedLength );
  1740. #else
  1741. memcpy( text, textSource, textLength+1 );
  1742. #endif
  1743. }
  1744. /*
  1745. =================
  1746. idDeclLocal::GetTextLength
  1747. =================
  1748. */
  1749. int idDeclLocal::GetTextLength() const {
  1750. return textLength;
  1751. }
  1752. /*
  1753. =================
  1754. idDeclLocal::SetText
  1755. =================
  1756. */
  1757. void idDeclLocal::SetText( const char *text ) {
  1758. SetTextLocal( text, idStr::Length( text ) );
  1759. }
  1760. /*
  1761. =================
  1762. idDeclLocal::SetTextLocal
  1763. =================
  1764. */
  1765. void idDeclLocal::SetTextLocal( const char *text, const int length ) {
  1766. Mem_Free( textSource );
  1767. checksum = MD5_BlockChecksum( text, length );
  1768. #ifdef GET_HUFFMAN_FREQUENCIES
  1769. for( int i = 0; i < length; i++ ) {
  1770. huffmanFrequencies[((const unsigned char *)text)[i]]++;
  1771. }
  1772. #endif
  1773. #ifdef USE_COMPRESSED_DECLS
  1774. int maxBytesPerCode = ( maxHuffmanBits + 7 ) >> 3;
  1775. byte *compressed = (byte *)_alloca( length * maxBytesPerCode );
  1776. compressedLength = HuffmanCompressText( text, length, compressed, length * maxBytesPerCode );
  1777. textSource = (char *)Mem_Alloc( compressedLength, TAG_DECLTEXT );
  1778. memcpy( textSource, compressed, compressedLength );
  1779. #else
  1780. compressedLength = length;
  1781. textSource = (char *) Mem_Alloc( length + 1, TAG_DECLTEXT );
  1782. memcpy( textSource, text, length );
  1783. textSource[length] = '\0';
  1784. #endif
  1785. textLength = length;
  1786. }
  1787. /*
  1788. =================
  1789. idDeclLocal::ReplaceSourceFileText
  1790. =================
  1791. */
  1792. bool idDeclLocal::ReplaceSourceFileText() {
  1793. int oldFileLength, newFileLength;
  1794. idFile *file;
  1795. common->Printf( "Writing \'%s\' to \'%s\'...\n", GetName(), GetFileName() );
  1796. if ( sourceFile == &declManagerLocal.implicitDecls ) {
  1797. common->Warning( "Can't save implicit declaration %s.", GetName() );
  1798. return false;
  1799. }
  1800. // get length and allocate buffer to hold the file
  1801. oldFileLength = sourceFile->fileSize;
  1802. newFileLength = oldFileLength - sourceTextLength + textLength;
  1803. idTempArray<char> buffer( Max( newFileLength, oldFileLength ) );
  1804. memset( buffer.Ptr(), 0, buffer.Size() );
  1805. // read original file
  1806. if ( sourceFile->fileSize ) {
  1807. file = fileSystem->OpenFileRead( GetFileName() );
  1808. if ( !file ) {
  1809. common->Warning( "Couldn't open %s for reading.", GetFileName() );
  1810. return false;
  1811. }
  1812. if ( file->Length() != sourceFile->fileSize || file->Timestamp() != sourceFile->timestamp ) {
  1813. common->Warning( "The file %s has been modified outside of the engine.", GetFileName() );
  1814. return false;
  1815. }
  1816. file->Read( buffer.Ptr(), oldFileLength );
  1817. fileSystem->CloseFile( file );
  1818. if ( MD5_BlockChecksum( buffer.Ptr(), oldFileLength ) != (unsigned int)sourceFile->checksum ) {
  1819. common->Warning( "The file %s has been modified outside of the engine.", GetFileName() );
  1820. return false;
  1821. }
  1822. }
  1823. // insert new text
  1824. char *declText = (char *) _alloca( textLength + 1 );
  1825. GetText( declText );
  1826. memmove( buffer.Ptr() + sourceTextOffset + textLength, buffer.Ptr() + sourceTextOffset + sourceTextLength, oldFileLength - sourceTextOffset - sourceTextLength );
  1827. memcpy( buffer.Ptr() + sourceTextOffset, declText, textLength );
  1828. // write out new file
  1829. file = fileSystem->OpenFileWrite( GetFileName(), "fs_basepath" );
  1830. if ( !file ) {
  1831. common->Warning( "Couldn't open %s for writing.", GetFileName() );
  1832. return false;
  1833. }
  1834. file->Write( buffer.Ptr(), newFileLength );
  1835. fileSystem->CloseFile( file );
  1836. // set new file size, checksum and timestamp
  1837. sourceFile->fileSize = newFileLength;
  1838. sourceFile->checksum = MD5_BlockChecksum( buffer.Ptr(), newFileLength );
  1839. fileSystem->ReadFile( GetFileName(), NULL, &sourceFile->timestamp );
  1840. // move all decls in the same file
  1841. for ( idDeclLocal *decl = sourceFile->decls; decl; decl = decl->nextInFile ) {
  1842. if (decl->sourceTextOffset > sourceTextOffset) {
  1843. decl->sourceTextOffset += textLength - sourceTextLength;
  1844. }
  1845. }
  1846. // set new size of text in source file
  1847. sourceTextLength = textLength;
  1848. return true;
  1849. }
  1850. /*
  1851. =================
  1852. idDeclLocal::SourceFileChanged
  1853. =================
  1854. */
  1855. bool idDeclLocal::SourceFileChanged() const {
  1856. int newLength;
  1857. ID_TIME_T newTimestamp;
  1858. if ( sourceFile->fileSize <= 0 ) {
  1859. return false;
  1860. }
  1861. newLength = fileSystem->ReadFile( GetFileName(), NULL, &newTimestamp );
  1862. if ( newLength != sourceFile->fileSize || newTimestamp != sourceFile->timestamp ) {
  1863. return true;
  1864. }
  1865. return false;
  1866. }
  1867. /*
  1868. =================
  1869. idDeclLocal::MakeDefault
  1870. =================
  1871. */
  1872. void idDeclLocal::MakeDefault() {
  1873. static int recursionLevel;
  1874. const char *defaultText;
  1875. declManagerLocal.MediaPrint( "DEFAULTED\n" );
  1876. declState = DS_DEFAULTED;
  1877. AllocateSelf();
  1878. defaultText = self->DefaultDefinition();
  1879. // a parse error inside a DefaultDefinition() string could
  1880. // cause an infinite loop, but normal default definitions could
  1881. // still reference other default definitions, so we can't
  1882. // just dump out on the first recursion
  1883. if ( ++recursionLevel > 100 ) {
  1884. common->FatalError( "idDecl::MakeDefault: bad DefaultDefinition(): %s", defaultText );
  1885. }
  1886. // always free data before parsing
  1887. self->FreeData();
  1888. // parse
  1889. self->Parse( defaultText, strlen( defaultText ), false );
  1890. // we could still eventually hit the recursion if we have enough Error() calls inside Parse...
  1891. --recursionLevel;
  1892. }
  1893. /*
  1894. =================
  1895. idDeclLocal::SetDefaultText
  1896. =================
  1897. */
  1898. bool idDeclLocal::SetDefaultText() {
  1899. return false;
  1900. }
  1901. /*
  1902. =================
  1903. idDeclLocal::DefaultDefinition
  1904. =================
  1905. */
  1906. const char *idDeclLocal::DefaultDefinition() const {
  1907. return "{ }";
  1908. }
  1909. /*
  1910. =================
  1911. idDeclLocal::Parse
  1912. =================
  1913. */
  1914. bool idDeclLocal::Parse( const char *text, const int textLength, bool allowBinaryVersion ) {
  1915. idLexer src;
  1916. src.LoadMemory( text, textLength, GetFileName(), GetLineNum() );
  1917. src.SetFlags( DECL_LEXER_FLAGS );
  1918. src.SkipUntilString( "{" );
  1919. src.SkipBracedSection( false );
  1920. return true;
  1921. }
  1922. /*
  1923. =================
  1924. idDeclLocal::FreeData
  1925. =================
  1926. */
  1927. void idDeclLocal::FreeData() {
  1928. }
  1929. /*
  1930. =================
  1931. idDeclLocal::List
  1932. =================
  1933. */
  1934. void idDeclLocal::List() const {
  1935. common->Printf( "%s\n", GetName() );
  1936. }
  1937. /*
  1938. =================
  1939. idDeclLocal::Print
  1940. =================
  1941. */
  1942. void idDeclLocal::Print() const {
  1943. }
  1944. /*
  1945. =================
  1946. idDeclLocal::Reload
  1947. =================
  1948. */
  1949. void idDeclLocal::Reload() {
  1950. this->sourceFile->Reload( false );
  1951. }
  1952. /*
  1953. =================
  1954. idDeclLocal::AllocateSelf
  1955. =================
  1956. */
  1957. void idDeclLocal::AllocateSelf() {
  1958. if ( self == NULL ) {
  1959. self = declManagerLocal.GetDeclType( (int)type )->allocator();
  1960. self->base = this;
  1961. }
  1962. }
  1963. /*
  1964. =================
  1965. idDeclLocal::ParseLocal
  1966. =================
  1967. */
  1968. void idDeclLocal::ParseLocal() {
  1969. bool generatedDefaultText = false;
  1970. AllocateSelf();
  1971. // always free data before parsing
  1972. self->FreeData();
  1973. declManagerLocal.MediaPrint( "parsing %s %s\n", declManagerLocal.declTypes[type]->typeName.c_str(), name.c_str() );
  1974. // if no text source try to generate default text
  1975. if ( textSource == NULL ) {
  1976. generatedDefaultText = self->SetDefaultText();
  1977. }
  1978. // indent for DEFAULTED or media file references
  1979. declManagerLocal.indent++;
  1980. // no text immediately causes a MakeDefault()
  1981. if ( textSource == NULL ) {
  1982. MakeDefault();
  1983. declManagerLocal.indent--;
  1984. return;
  1985. }
  1986. declState = DS_PARSED;
  1987. // parse
  1988. char *declText = (char *) _alloca( ( GetTextLength() + 1 ) * sizeof( char ) );
  1989. GetText( declText );
  1990. self->Parse( declText, GetTextLength(), true );
  1991. // free generated text
  1992. if ( generatedDefaultText ) {
  1993. Mem_Free( textSource );
  1994. textSource = NULL;
  1995. textLength = 0;
  1996. }
  1997. declManagerLocal.indent--;
  1998. }
  1999. /*
  2000. =================
  2001. idDeclLocal::Purge
  2002. =================
  2003. */
  2004. void idDeclLocal::Purge() {
  2005. // never purge things that were referenced outside level load,
  2006. // like the console and menu graphics
  2007. if ( parsedOutsideLevelLoad ) {
  2008. return;
  2009. }
  2010. referencedThisLevel = false;
  2011. MakeDefault();
  2012. // the next Find() for this will re-parse the real data
  2013. declState = DS_UNPARSED;
  2014. }
  2015. /*
  2016. =================
  2017. idDeclLocal::EverReferenced
  2018. =================
  2019. */
  2020. bool idDeclLocal::EverReferenced() const {
  2021. return everReferenced;
  2022. }